| | |
| | | package com.xiaopeng.account.controller; |
| | | |
| | | |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.xiaopeng.account.model.dto.ReceiveCouponDto; |
| | | import com.xiaopeng.account.model.dto.SendCouponDto; |
| | |
| | | import com.xiaopeng.account.service.IXpAppUserCouponService; |
| | | import com.xiaopeng.api.dto.account.GetUserCouponDto; |
| | | import com.xiaopeng.api.dto.account.NavigationCouponPickerRequest; |
| | | import com.xiaopeng.api.vo.account.NavigationCouponPickerVo; |
| | | import com.xiaopeng.api.dto.account.UseUserCouponDto; |
| | | import com.xiaopeng.api.feignClient.account.UserResourcesClient; |
| | | import com.xiaopeng.api.feignClient.operation.XpActicityClient; |
| | | import com.xiaopeng.api.feignClient.operation.XpCouponClient; |
| | | import com.xiaopeng.api.feignClient.operation.XpOpenCityClient; |
| | | import com.xiaopeng.api.model.account.XpAppUserCoupon; |
| | | import com.xiaopeng.api.model.operation.XpCoupon; |
| | | import com.xiaopeng.api.query.account.XpAppUserCouponPageListQuery; |
| | | import com.xiaopeng.api.vo.account.NavigationCouponPickerVo; |
| | | import com.xiaopeng.api.vo.account.UserCouponVo; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.common.core.web.page.PageInfo; |
| | | import com.xiaopeng.unifiedverification.interceptor.XpClientCheck; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.validation.Valid; |
| | | import java.math.BigDecimal; |
| | |
| | | private final UserResourcesClient userResourcesClient; |
| | | private final XpCouponClient xpCouponClient; |
| | | |
| | | @Resource |
| | | private XpActicityClient xpActicityClient; |
| | | |
| | | |
| | | public XpAppUserCouponController(IXpAppUserCouponService xpAppUserCouponService, XpOpenCityClient xpOpenCityClient, UserResourcesClient userResourcesClient, XpCouponClient xpCouponClient) { |
| | | this.xpAppUserCouponService = xpAppUserCouponService; |
| | |
| | | this.xpCouponClient = xpCouponClient; |
| | | } |
| | | |
| | | @PostMapping("/v1/api/appUserCoupon/pageList") |
| | | @ApiOperation(value = "用户优惠券列表",tags = {"管理后台-用户优惠券列表"},response = XpAppUserCouponListVo.class) |
| | | public R<PageInfo<XpAppUserCouponListVo>> pageList(@RequestBody XpAppUserCouponPageListQuery query) { |
| | | |
| | | if(StrUtil.isNotBlank(query.getActicityName()) ){ |
| | | List<String> acticityIds = xpActicityClient.findListToIds(query.getActicityName()).getData(); |
| | | query.setActicityIds(acticityIds); |
| | | } |
| | | |
| | | PageInfo<XpAppUserCouponListVo> pageList = xpAppUserCouponService.pageList(query); |
| | | return R.ok(pageList); |
| | | } |
| | | |
| | | @PostMapping("/logan/inner/appUserCoupon/getUserCoupon") |
| | | public R<UserCouponVo> getUserCoupon(@RequestBody GetUserCouponDto dto) { |
| | |
| | | import com.xiaopeng.account.model.query.XpUserCouponListQuery; |
| | | import com.xiaopeng.account.model.vo.XpAppUserCouponListVo; |
| | | import com.xiaopeng.api.model.account.XpAppUserCoupon; |
| | | import com.xiaopeng.api.query.account.XpAppUserCouponPageListQuery; |
| | | import com.xiaopeng.common.core.web.page.PageInfo; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | |
| | | Page<XpAppUserCouponListVo> userCouponList(@Param("page") Page<XpAppUserCouponListVo> page, @Param("query") XpUserCouponListQuery query, @Param("uid") Long uid); |
| | | |
| | | |
| | | List<XpAppUserCouponListVo> pageList(@Param("pageInfo") PageInfo<XpAppUserCouponListVo> pageInfo, @Param("query") XpAppUserCouponPageListQuery query); |
| | | |
| | | } |
| | |
| | | package com.xiaopeng.account.model.vo; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | |
| | | @ApiModel("用户优惠券列表Vo") |
| | | public class XpAppUserCouponListVo { |
| | | |
| | | @TableId(value = "id", type = IdType.ASSIGN_ID) |
| | | private Long id; |
| | | |
| | | @ApiModelProperty(value = "Id") |
| | | private String couponId; |
| | | |
| | | @ApiModelProperty(value = "用户id 根据手机号获取") |
| | | private Long appUserId; |
| | | |
| | | @ApiModelProperty(value = "优惠券名称") |
| | | private String title; |
| | |
| | | |
| | | @ApiModelProperty(value = "优惠券说明") |
| | | private String couponDesc; |
| | | |
| | | @ApiModelProperty(value = "活动名称") |
| | | private String acticityName; |
| | | |
| | | } |
| | |
| | | import com.xiaopeng.account.model.dto.ReceiveCouponDto; |
| | | import com.xiaopeng.account.model.dto.SendCouponDto; |
| | | import com.xiaopeng.account.model.query.XpUserCouponListQuery; |
| | | import com.xiaopeng.account.model.vo.XpAppUserCouponListVo; |
| | | import com.xiaopeng.account.model.vo.XpAppUserCouponTotalVo; |
| | | import com.xiaopeng.account.model.vo.XpAppUserCouponVo; |
| | | import com.xiaopeng.api.dto.account.NavigationCouponPickerRequest; |
| | | import com.xiaopeng.api.model.account.XpAppUserCoupon; |
| | | import com.xiaopeng.api.query.account.XpAppUserCouponPageListQuery; |
| | | import com.xiaopeng.api.vo.account.NavigationCouponPickerVo; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.common.core.web.page.PageInfo; |
| | | |
| | | import java.util.List; |
| | | |
| | |
| | | */ |
| | | public interface IXpAppUserCouponService extends IService<XpAppUserCoupon> { |
| | | |
| | | PageInfo<XpAppUserCouponListVo> pageList(XpAppUserCouponPageListQuery query); |
| | | |
| | | /** |
| | | * 获取用户优惠券列表 |
| | | * @param query |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.google.common.collect.Lists; |
| | | import com.xiaopeng.account.mapper.XpAppUserCouponMapper; |
| | | import com.xiaopeng.account.model.dto.ReceiveCouponDto; |
| | | import com.xiaopeng.account.model.dto.SendCouponDto; |
| | |
| | | import com.xiaopeng.api.dto.account.NavigationCouponPickerRequest; |
| | | import com.xiaopeng.api.dto.account.UcUserInfo; |
| | | import com.xiaopeng.api.enums.NavigationCouponBubbleType; |
| | | import com.xiaopeng.api.query.account.XpAppUserCouponPageListQuery; |
| | | import com.xiaopeng.api.vo.account.NavigationCouponItemVo; |
| | | import com.xiaopeng.api.vo.account.NavigationCouponPickerVo; |
| | | import com.xiaopeng.api.feignClient.account.UserResourcesClient; |
| | |
| | | import com.xiaopeng.api.model.operation.XpCoupon; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.common.core.utils.DateUtils; |
| | | import com.xiaopeng.common.core.web.page.PageInfo; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.scheduling.annotation.Async; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | private UserResourcesClient userResourcesClient; |
| | | |
| | | |
| | | @Override |
| | | public PageInfo<XpAppUserCouponListVo> pageList(XpAppUserCouponPageListQuery query) { |
| | | PageInfo<XpAppUserCouponListVo> pageInfo = new PageInfo<>(query.getPageNum(),query.getPageSize()); |
| | | List<XpAppUserCouponListVo> list = this.baseMapper.pageList(pageInfo,query); |
| | | pageInfo.setRecords(list); |
| | | return pageInfo; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取用户优惠券列表 |
| | | * |
| | |
| | | id, full_money, money, expiration_time, status, coupon_type, app_user_id, coupon_id, activity_id, activity_type, is_deleted, create_time, update_time, create_by, update_by |
| | | </sql> |
| | | |
| | | |
| | | <select id="pageList" resultType="com.xiaopeng.account.model.vo.XpAppUserCouponListVo"> |
| | | select a.* |
| | | from xp_app_user_coupon as a |
| | | where a.is_deleted = 0 and a.app_user_id = #{appUserId} |
| | | <if test="query.createTimeStart != null "> |
| | | a.create_time >= #{query.createTimeStart} |
| | | </if> |
| | | <if test="query.createTimeEnd != null "> |
| | | a.create_time <= #{query.createTimeEnd} |
| | | </if> |
| | | <if test="query.status != null"> |
| | | and a.status = #{query.status} |
| | | </if> |
| | | <if test="query.acticityIds != null"> |
| | | and a.activity_id in |
| | | <foreach item="item" collection="query.acticityIds" separator="," open="(" close=")" index=""> |
| | | #{item} |
| | | </foreach> |
| | | </if> |
| | | order by a.create_time desc |
| | | </select> |
| | | |
| | | <select id="userCouponList" resultType="com.xiaopeng.account.model.vo.XpAppUserCouponListVo"> |
| | | select t.*,t.status from ( |
| | |
| | | private String appId; |
| | | private String headImg; |
| | | private Long id; |
| | | private String mobile; |
| | | private String nickName; |
| | | private String mobile;//用户手机号 |
| | | private String nickName;//用户名称 |
| | | private List<String> orderList; |
| | | private Integer orderType; |
| | | private Integer state; |
| | | private Integer type; |
| | | private Long uid; |
| | | private Long uid; //用户id |
| | | private List<String> bindCars; // 空时为 null |
| | | private Integer musicVip; // 0-非音频会员,1-音频会员 |
| | | } |
| New file |
| | |
| | | package com.xiaopeng.api.factory.operation; |
| | | |
| | | import com.xiaopeng.api.feignClient.operation.XpActicityClient; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.cloud.openfeign.FallbackFactory; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.util.List; |
| | | |
| | | @Slf4j |
| | | @Component |
| | | public class XpActicityClientFallbackFactory implements FallbackFactory<XpActicityClient> { |
| | | |
| | | @Override |
| | | public XpActicityClient create(Throwable cause) { |
| | | return new XpActicityClient() { |
| | | |
| | | @Override |
| | | public R<List<String>> findListToIds(String acticityName) { |
| | | return R.ok(); |
| | | } |
| | | }; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.xiaopeng.api.feignClient.operation; |
| | | |
| | | |
| | | import com.xiaopeng.api.factory.operation.XpCouponClientFallbackFactory; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum; |
| | | import org.springframework.cloud.openfeign.FeignClient; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | |
| | | import java.util.List; |
| | | |
| | | @FeignClient(contextId = "XpActicityClient", |
| | | value = ServiceNameConstantsEnum.XP_OPERATION_SERVICE, |
| | | fallbackFactory = XpCouponClientFallbackFactory.class) |
| | | public interface XpActicityClient { |
| | | |
| | | |
| | | |
| | | @PostMapping("/logan/inner/acticity/findListToIds") |
| | | R<List<String>> findListToIds(@RequestParam("acticityName") String acticityName); |
| | | } |
| | |
| | | @Max(value = 99999, message = "最大不能超过99999") |
| | | private Integer maxOrderNum; |
| | | |
| | | @ApiModelProperty(value = "用户id 根据手机号获取") |
| | | private Long appUserId; |
| | | |
| | | public Boolean getStatus() { |
| | | if (LocalDate.now().isAfter(expireTime)) { |
| | | return false; |
| | | if(expireTime!= null){ |
| | | if (LocalDate.now().isAfter(expireTime)) { |
| | | return false; |
| | | } |
| | | return status; |
| | | } |
| | | return status; |
| | | } |
| New file |
| | |
| | | package com.xiaopeng.api.query.account; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.xiaopeng.common.core.web.page.BasePage; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | public class XpAppUserCouponPageListQuery extends BasePage { |
| | | |
| | | |
| | | @ApiModelProperty(value = "用户id 根据手机号获取") |
| | | private Long appUserId; |
| | | |
| | | |
| | | @ApiModelProperty(value = "状态 1-未使用 2-已使用 3-已过期 0待领取") |
| | | private Integer status; |
| | | |
| | | @ApiModelProperty(value = "活动名称") |
| | | private String acticityName; |
| | | |
| | | @ApiModelProperty(value = "领取时间开始") |
| | | @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") |
| | | private LocalDateTime createTimeStart; |
| | | |
| | | @ApiModelProperty(value = "领取时间结束") |
| | | @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") |
| | | private LocalDateTime createTimeEnd; |
| | | |
| | | private List<String> acticityIds; |
| | | |
| | | } |
| | |
| | | com.xiaopeng.api.factory.map.XpStationClientFallbackFactory |
| | | com.xiaopeng.api.factory.pushMessage.SubscribeMessageClientFallbackFactory |
| | | com.xiaopeng.api.factory.account.UserSubscribeMessageClientFallbackFactory |
| | | com.xiaopeng.api.factory.operation.XpTradingStrategyClientFallbackFactory |
| | | com.xiaopeng.api.factory.operation.XpTradingStrategyClientFallbackFactory |
| | | com.xiaopeng.api.factory.operation.XpActicityClientFallbackFactory |
| | |
| | | package com.xiaopeng.operation.controller; |
| | | |
| | | |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.operation.service.IXpActicityService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | |
| | | import org.springframework.stereotype.Controller; |
| | | import javax.annotation.Resource; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | * @author mitao |
| | | * @since 2026-02-03 |
| | | */ |
| | | @Controller |
| | | @RequestMapping("/xp-acticity") |
| | | @Api(tags = "活动管理") |
| | | @RequiredArgsConstructor(onConstructor_ = @Lazy) |
| | | public class XpActicityController { |
| | | |
| | | @Resource |
| | | private IXpActicityService xpActicityService; |
| | | |
| | | |
| | | /** |
| | | * 获取所有白名单手机号 |
| | | * @return |
| | | */ |
| | | @PostMapping("/logan/inner/acticity/findListToIds") |
| | | @ApiOperation(value = "获取活动信息ids", tags = {"管理后台-获取活动信息ids"}) |
| | | public R<List<String>> findListToIds(@RequestParam String acticityName){ |
| | | if(acticityName == null){ |
| | | return R.ok(); |
| | | } |
| | | return R.ok(xpActicityService.findListToIds(acticityName)); |
| | | } |
| | | } |
| | |
| | | return R.ok(xpWhitelistService.getAllWhiteList()); |
| | | } |
| | | |
| | | |
| | | @ApiOperation(value = "白名单管理详情", tags = {"管理后台-白名单管理详情"}) |
| | | @GetMapping("/api/v1/whitelist/detail/{id}") |
| | | public R<XpWhitelist> detail(@PathVariable("id") Long id) { |
| | | return R.ok(xpWhitelistService.getById(id)); |
| | | } |
| | | |
| | | |
| | | @ApiOperation(value = "白名单管理分页列表", response = XpWhitelist.class) |
| | | @PostMapping("/api/v1/whitelist/pageList") |
| | | public R<PageInfo<XpWhitelist>> pageList(@RequestBody WhitelistPageListQuery query) { |
| | |
| | | xpWhitelistExportExcel.setNickName(xpWhitelist.getNickName()); |
| | | xpWhitelistExportExcel.setStatus(xpWhitelist.getStatus()); |
| | | xpWhitelistExportExcel.setIsPriorityDispatch(xpWhitelist.getIsPriorityDispatch()); |
| | | xpWhitelistExportExcel.setExpireTime(xpWhitelist.getExpireTime().toString()); |
| | | xpWhitelistExportExcel.setMaxOrderNum(xpWhitelist.getMaxOrderNum()); |
| | | |
| | | xpWhitelistExportExcel.setCreateBy(xpWhitelist.getCreateBy()); |
| | | LocalDateTime createTime = xpWhitelist.getCreateTime(); |
| | | // 将LocalDateTime转化为yyyy-MM-dd HH:mm:ss格式字符串 |
| | |
| | | package com.xiaopeng.operation.exportExcle; |
| | | |
| | | import com.xiaopeng.common.core.annotation.Excel; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | |
| | | |
| | | @ApiModelProperty(value = "优先派单 1=是 0=否") |
| | | @cn.afterturn.easypoi.excel.annotation.Excel(name = "优先派单",width = 20,replace = {"是_true","否_false"}) |
| | | |
| | | private Boolean isPriorityDispatch; |
| | | |
| | | @ApiModelProperty(value = "有限期") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | @cn.afterturn.easypoi.excel.annotation.Excel(name = "有限期",width = 20) |
| | | private String expireTime; |
| | | |
| | | @ApiModelProperty(value = "最大下单数量") |
| | | @cn.afterturn.easypoi.excel.annotation.Excel(name = "最大下单数量",width = 20) |
| | | private Integer maxOrderNum; |
| | | |
| | | @ApiModelProperty(value = "记录创建人,前端忽略") |
| | | @cn.afterturn.easypoi.excel.annotation.Excel(name = "创建人",width = 20) |
| | |
| | | @ApiModelProperty(value = "选中的记录id集合") |
| | | private List<Long> ids; |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.xiaopeng.api.model.operation.XpActicity; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | | * 活动管理 服务类 |
| | |
| | | */ |
| | | public interface IXpActicityService extends IService<XpActicity> { |
| | | |
| | | |
| | | List<String> findListToIds(String acticityName); |
| | | } |
| | |
| | | package com.xiaopeng.operation.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.xiaopeng.api.model.operation.XpActicity; |
| | | import com.xiaopeng.operation.mapper.XpActicityMapper; |
| | | import com.xiaopeng.operation.service.IXpActicityService; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | @Service |
| | | public class XpActicityServiceImpl extends ServiceImpl<XpActicityMapper, XpActicity> implements IXpActicityService { |
| | | |
| | | |
| | | |
| | | @Override |
| | | public List<String> findListToIds(String acticityName){ |
| | | LambdaQueryWrapper<XpActicity > query = new LambdaQueryWrapper<>(); |
| | | query.select(XpActicity::getId); |
| | | query.eq(XpActicity::getDeleted, 0); |
| | | query.like(XpActicity::getActicityName, acticityName); |
| | | return listObjs(query, Object::toString); |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.PhoneUtil; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.xiaopeng.api.dto.account.UcUserInfo; |
| | | import com.xiaopeng.api.feignClient.account.UserResourcesClient; |
| | | import com.xiaopeng.api.model.account.SysUser; |
| | | import com.xiaopeng.api.model.operation.XpWhitelist; |
| | | import com.xiaopeng.api.model.operation.XpWhitelistOperlog; |
| | |
| | | import com.xiaopeng.operation.mapper.XpWhitelistOperlogMapper; |
| | | import com.xiaopeng.operation.query.WhitelistPageListQuery; |
| | | import com.xiaopeng.operation.service.IXpWhitelistService; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import org.apache.shardingsphere.transaction.annotation.ShardingSphereTransactionType; |
| | | import org.apache.shardingsphere.transaction.core.TransactionType; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.time.LocalDate; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Comparator; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | |
| | | |
| | | @Autowired |
| | | private XpWhitelistOperlogMapper xpWhitelistOperlogMapper; |
| | | @Autowired |
| | | private UserResourcesClient userResourcesClient; |
| | | |
| | | |
| | | @Override |
| | | public PageInfo<XpWhitelist> pageList(WhitelistPageListQuery query) { |
| | | PageInfo<XpWhitelist> pageInfo = new PageInfo<>(query.getPageNum(),query.getPageSize()); |
| | |
| | | public List<XpWhitelist> exportList(WhitelistPageListQuery query) { |
| | | List<XpWhitelist> list = this.baseMapper.exportList(query); |
| | | return list; |
| | | } |
| | | |
| | | //根据用户账号 通过接口获取用户id |
| | | public UcUserInfo getUserByAccount (String account){ |
| | | UcUserInfo userByMobile = userResourcesClient.getUserByMobile(account); |
| | | if(userByMobile == null){ |
| | | throw new ServiceException(account+"未获取到用户信息"); |
| | | } |
| | | return userByMobile; |
| | | } |
| | | |
| | | @Override |
| | |
| | | Map<String, Long> reasonCountMap = new HashMap<>(); |
| | | Map<String, LinkedHashSet<String>> reasonSampleMap = new HashMap<>(); |
| | | |
| | | Map<String, UcUserInfo> userMap = new HashMap<>(); |
| | | Set<String> seenAccounts = new HashSet<>(); |
| | | List<String> candidates = new ArrayList<>(); |
| | | for (String account : accounts) { |
| | |
| | | recordFail(reasonCountMap, reasonSampleMap, "文件内重复", account, sampleLimitPerReason); |
| | | continue; |
| | | } |
| | | candidates.add(account); |
| | | //根据用户账号 通过接口获取用户id |
| | | UcUserInfo userByAccount = this.getUserByAccount(account); |
| | | if(userByAccount != null){ |
| | | candidates.add(account); |
| | | userMap.put(account, userByAccount); |
| | | } |
| | | } |
| | | if (CollUtil.isEmpty(candidates)) { |
| | | return R.fail("所有帐号添加失败,请检查帐号格式或唯一性"); |
| | |
| | | } |
| | | XpWhitelist xpWhitelist = new XpWhitelist(); |
| | | xpWhitelist.setAccount(account); |
| | | xpWhitelist.setNickName(userMap.get(account).getNickName()); |
| | | xpWhitelist.setAppUserId(userMap.get(account).getUid()); |
| | | xpWhitelist.setStatus(true); |
| | | xpWhitelist.setIsPriorityDispatch(dto.getIsPriorityDispatch()); |
| | | xpWhitelist.setWhitelistSource(1); |
| | |
| | | if (!PhoneUtil.isMobile(dto.getAccount())) { |
| | | throw new ServiceException("以下帐号格式不正确:", I18nKeyConstant.ACCOUNT_FORMAT_ERROR, new Object[]{dto.getAccount()}); |
| | | } |
| | | UcUserInfo userByAccount = this.getUserByAccount(dto.getAccount()); |
| | | XpWhitelist old = this.lambdaQuery() |
| | | .eq(XpWhitelist::getAccount, dto.getAccount()) |
| | | .ne(XpWhitelist::getId, dto.getId()) |
| | |
| | | } |
| | | XpWhitelist whitelist = this.getById(dto.getId()); |
| | | |
| | | whitelist.setAppUserId(userByAccount.getUid()); |
| | | |
| | | StringBuilder operationContent = new StringBuilder("编辑账号:"); |
| | | StringBuilder accountBuilder = new StringBuilder(); |
| | | if (!whitelist.getAccount().equals(dto.getAccount())) { |
| | | accountBuilder.append("白名单账号" + "\"" + whitelist.getAccount() + "\"" + "为" + "\"" + dto.getAccount() + "\""); |
| | | } |
| | | if (StringUtils.hasLength(whitelist.getNickName()) || StringUtils.hasLength(dto.getNickName())) { |
| | | if (!StringUtils.hasLength(whitelist.getNickName())) { |
| | | if (StringUtils.hasLength(whitelist.getNickName())) { |
| | | if (!whitelist.getNickName().equals(dto.getNickName())) { |
| | | accountBuilder.append("用户名称" + "\"" + whitelist.getNickName() + "\"" + "为" + "\"" + dto.getNickName() + "\""); |
| | | } |
| | |
| | | if (whitelist.getIsPriorityDispatch() != dto.getIsPriorityDispatch()) { |
| | | accountBuilder.append("优先派单" + "\"" + (whitelist.getIsPriorityDispatch() ? "是" : "否") + "\"" + "为" + "\"" + (dto.getIsPriorityDispatch() ? "是" : "否") + "\""); |
| | | } |
| | | if ( !dto.getMaxOrderNum().equals(whitelist.getMaxOrderNum()) ) { |
| | | accountBuilder.append("最大下单数量" + "\"" + whitelist.getMaxOrderNum() + "\"" + "为" + "\"" + dto.getMaxOrderNum() + "\""); |
| | | whitelist.setMaxOrderNum(dto.getMaxOrderNum()); |
| | | } |
| | | if (!whitelist.getExpireTime().isEqual(dto.getExpireTime())) { |
| | | accountBuilder.append("有限期" + "\"" + whitelist.getExpireTime() + "\"" + "为" + "\"" + dto.getExpireTime() + "\""); |
| | | whitelist.setExpireTime(dto.getExpireTime()); |
| | | } |
| | | |
| | | XpWhitelistOperlog xpWhitelistOperlog = new XpWhitelistOperlog(); |
| | | xpWhitelistOperlog.setOperationName(sysUser.getNickName()); |
| | | xpWhitelistOperlog.setOperationAccount(sysUser.getPhoneNumber()); |
| | |
| | | |
| | | <!-- 通用查询结果列 --> |
| | | <sql id="Base_Column_List"> |
| | | id, nick_name, account, status, is_priority_dispatch, whitelist_source,expire_time, is_deleted, create_time, update_time, create_by, update_by |
| | | id, nick_name, account, status, is_priority_dispatch, whitelist_source,expire_time,max_order_num, is_deleted, create_time, update_time, create_by, update_by |
| | | </sql> |
| | | <select id="pageList" resultType="com.xiaopeng.api.model.operation.XpWhitelist"> |
| | | select |
| | | id,nick_name as nickName,account,status,is_priority_dispatch as isPriorityDispatch,whitelist_source as whitelistSource,expire_time as expireTime |
| | | id,nick_name as nickName,account,status,is_priority_dispatch as isPriorityDispatch,whitelist_source as whitelistSource, |
| | | expire_time as expireTime,max_order_num as maxOrderNum |
| | | ,create_time as createTime,update_time as updateTime,create_by as createBy,update_by as updateBy |
| | | from xp_whitelist |
| | | where is_deleted = 0 |
| | |
| | | order by create_time desc |
| | | </select> |
| | | <select id="exportList" resultType="com.xiaopeng.api.model.operation.XpWhitelist"> |
| | | select id,nick_name as nickName,account,status,is_priority_dispatch as isPriorityDispatch,whitelist_source as whitelistSource,expire_time as expireTime |
| | | select id,nick_name as nickName,account,status,is_priority_dispatch as isPriorityDispatch,whitelist_source as whitelistSource, |
| | | expire_time as expireTime,max_order_num as maxOrderNum |
| | | ,create_time as createTime,update_time as updateTime,create_by as createBy,update_by as updateBy |
| | | from xp_whitelist |
| | | where is_deleted = 0 |
| | |
| | | import com.xiaopeng.api.vo.operation.RouteVo; |
| | | import com.xiaopeng.api.vo.order.*; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.common.core.exception.ServiceException; |
| | | import com.xiaopeng.common.core.utils.StringUtils; |
| | | import com.xiaopeng.common.core.utils.WebUtils; |
| | | import com.xiaopeng.common.core.web.page.PageInfo; |
| | | import com.xiaopeng.common.redis.service.RedisService; |
| | | import com.xiaopeng.order.mangodb.model.OrderTrajectory; |
| | | import com.xiaopeng.order.mangodb.service.OrderTrajectoryService; |
| | | import com.xiaopeng.order.model.dto.XpOrderCommentDto; |
| | | import com.xiaopeng.order.model.dto.XpOrderOperateDTO; |
| | | import com.xiaopeng.order.model.dto.XpOrderPayDto; |
| | |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | private MongoTemplate mongoTemplate; |
| | | @Resource |
| | | private XpVehicleClient xpVehicleClient; |
| | | private OrderTrajectoryService orderTrajectoryService; |
| | | |
| | | /** |
| | | * 获取订单统计数据(内部接口) |
| | |
| | | String uid = request.getHeader("XP-Uid"); |
| | | OrderDetailVo orderDetailVo = xpOrderService.orderDetail(orderId, uid); |
| | | BigDecimal orderMoney = orderDetailVo.getOrderMoney(); |
| | | if(orderMoney==null){ |
| | | if (orderMoney == null) { |
| | | orderDetailVo.setOrderMoneyStr("0.00"); |
| | | }else { |
| | | } else { |
| | | orderDetailVo.setOrderMoneyStr(orderMoney.setScale(2, RoundingMode.HALF_UP).toString()); |
| | | } |
| | | return R.ok(orderDetailVo); |
| | |
| | | @ApiOperation(value = "获取历史下单成功起点10条数据列表", tags = {"小程序-获取历史下单成功起点10条数据列表"}) |
| | | @GetMapping("/base/v1/mini-program/history/startPoints") |
| | | @XpClientCheck(checkToken = false, checkOtpToken = true) |
| | | public R<List<XpHistoryStartPointsVo>> getHistoryStartPoints(double lon, double lat,Long electronicAreaId, HttpServletRequest request) { |
| | | public R<List<XpHistoryStartPointsVo>> getHistoryStartPoints(double lon, double lat, Long electronicAreaId, HttpServletRequest request) { |
| | | // uid已通过拦截器otp校验,可以直接使用 |
| | | String uid = request.getHeader("XP-Uid"); |
| | | return R.ok(xpOrderService.getHistoryStartPoints(uid, lon, lat,electronicAreaId)); |
| | | return R.ok(xpOrderService.getHistoryStartPoints(uid, lon, lat, electronicAreaId)); |
| | | } |
| | | |
| | | /** |
| | |
| | | @ApiOperation(value = "获取历史下单成功终点10条数据列表", tags = {"小程序-获取历史下单成功终点10条数据列表"}) |
| | | @GetMapping("/base/v1/mini-program/history/endPoints") |
| | | @XpClientCheck(checkToken = false, checkOtpToken = true) |
| | | public R<List<XpHistoryEndPointsVo>> getHistoryEndPoints(double lon, double lat,Long electronicAreaId, HttpServletRequest request) { |
| | | public R<List<XpHistoryEndPointsVo>> getHistoryEndPoints(double lon, double lat, Long electronicAreaId, HttpServletRequest request) { |
| | | // uid已通过拦截器otp校验,可以直接使用 |
| | | String uid = request.getHeader("XP-Uid"); |
| | | return R.ok(xpOrderService.getHistoryEndPoints(uid, lon, lat,electronicAreaId)); |
| | | return R.ok(xpOrderService.getHistoryEndPoints(uid, lon, lat, electronicAreaId)); |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * + |
| | | * 获取行程费用明细 |
| | |
| | | */ |
| | | @ApiOperation(value = "行驶中车辆异常,订单状态修改- 修改状态=7 再修改 金额-再将状态修改成8") |
| | | @PostMapping("/logan/inner/v1/order/carAbnormalUpdateOrderStatus") |
| | | public R<String> carAbnormalUpdateOrderStatus(@RequestParam Long orderId ) { |
| | | public R<String> carAbnormalUpdateOrderStatus(@RequestParam Long orderId) { |
| | | // Integer status = OrderStatusEnum.SEE_OFF_GUESTS.getCode(); |
| | | return xpOrderService.carAbnormalUpdateOrderStatus(orderId); |
| | | } |
| | |
| | | @PostMapping("/api/v1/mini-program/order/queryOrderRoute") |
| | | @XpClientCheck(checkToken = false, checkOtpToken = true) |
| | | public R<RouteVo> queryOrderRoute(@Validated @RequestBody QueryOrderRouteDTO dto, HttpServletRequest request) { |
| | | if(dto.getOrderId() == null){ |
| | | if (dto.getOrderId() == null) { |
| | | return R.fail("参数不能为空"); |
| | | } |
| | | String uid = request.getHeader("XP-Uid"); |
| | |
| | | routeVo.setDirection(null != vehiclePosition ? vehiclePosition.getCourse() : 90); |
| | | return R.ok(routeVo); |
| | | } |
| | | |
| | | /** |
| | | * 订单查询轨迹路线 |
| | | */ |
| | |
| | | @GetMapping("/api/v1/mini-program/order/queryOrderTrajectory") |
| | | @XpClientCheck(checkToken = false, checkOtpToken = true) |
| | | public R<RouteVo> queryOrderTrajectory(@RequestParam String orderId, HttpServletRequest request) { |
| | | if(orderId == null){ |
| | | if (orderId == null) { |
| | | return R.fail("参数不能为空"); |
| | | } |
| | | List<OrderTrajectory> trajectories = mongoTemplate.find( |
| | |
| | | // 封装信息 |
| | | RouteVo routeVo = new RouteVo(); |
| | | List<LonLatDto> polyline = new ArrayList<>(); |
| | | if(!CollectionUtils.isEmpty(trajectories)){ |
| | | if (!CollectionUtils.isEmpty(trajectories)) { |
| | | for (OrderTrajectory trajectory : trajectories) { |
| | | LonLatDto lonLatDto = new LonLatDto(); |
| | | String[] split = trajectory.getLocation().split(","); |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 当日取消订单次数 |
| | | * |
| | |
| | | * @return 订单数量 |
| | | */ |
| | | @PostMapping("/inner/order/todayCancellationCount") |
| | | public R<Integer> todayCancellationCount(@RequestParam Long userId){ |
| | | public R<Integer> todayCancellationCount(@RequestParam Long userId) { |
| | | long count = xpOrderService.count(new QueryWrapper<XpOrder>().eq("app_user_id", userId).eq("status", 0) |
| | | .eq("is_deleted", 0).last(" and DATE_FORMAT(create_time, '%Y-%m-%d') = DATE_FORMAT(NOW(), '%Y-%m-%d')")); |
| | | return R.ok((int)count); |
| | | return R.ok((int) count); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | | @ApiOperation(value = "通过订单id获取蓝牙开锁秘钥", tags = {"小程序-业务流程"}) |
| | | @GetMapping("/api/v1/mini-program/bluetooth/getUnlocktToken/{orderId}") |
| | | @XpClientCheck(checkToken = false, checkOtpToken = true) |
| | | public R<String> getBluetoothToken(@PathVariable("orderId") Long orderId, HttpServletRequest request) { |
| | | String uid = request.getHeader("XP-Uid"); |
| | | XpOrder xpOrder = xpOrderService.getById(orderId); |
| | | if (!Objects.equals(xpOrder.getAppUserId(), Long.valueOf(uid))) { |
| | | return R.ok(); |
| | | } |
| | | if(!Arrays.asList(4, 5, 6, 7, 8).contains(xpOrder.getStatus())){ |
| | | return R.ok(); |
| | | } |
| | | String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + orderId); |
| | | if (StringUtils.isBlank(token)) { |
| | | return R.ok(); |
| | | } |
| | | return R.ok(token); |
| | | } |
| | | } |
| | |
| | | Long userId = order.getAppUserId(); |
| | | if (order.getStatus() == 1) { |
| | | order.setStatus(0); |
| | | Long appUserId = order.getAppUserId(); |
| | | order.setAppUserId(null); |
| | | baseMapper.updateById(order); |
| | | order.setAppUserId(appUserId); |
| | | redisService.setCacheObject("ORDER_STATUS:" + order.getId(), 0, 24L, TimeUnit.HOURS); |
| | | //删除蓝牙秘钥 |
| | | String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + order.getId()); |
| | | if(StringUtils.isNotBlank(token)){ |
| | | redisService.deleteObject("rt:bluetooth:unlock:" + token); |
| | | redisService.deleteObject("rt:bluetooth:unlock:order:" + order.getId()); |
| | | XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData(); |
| | | BluetoothDeliverVo vo = new BluetoothDeliverVo(); |
| | | vo.setVim(xpVehicle.getVehicleVin()); |
| | | vo.setPassengerUid(order.getAppUserId()); |
| | | BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo); |
| | | if(null == delete || delete.getCode() != 0){ |
| | | log.error("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber()); |
| | | } |
| | | } |
| | | // 消息推送 |
| | | Map<String, Object> params = new HashMap<>(); |
| | | Map<String, Object> content = new HashMap<>(); |
| | |
| | | addCruiseMission(xpVehicle.getId()); |
| | | } |
| | | order.setStatus(0); |
| | | Long appUserId = order.getAppUserId(); |
| | | order.setAppUserId(null); |
| | | baseMapper.updateById(order); |
| | | order.setAppUserId(appUserId); |
| | | redisService.setCacheObject("ORDER_STATUS:" + order.getId(), 0, 24L, TimeUnit.HOURS); |
| | | //删除蓝牙秘钥 |
| | | String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + order.getId()); |
| | | if(StringUtils.isNotBlank(token)){ |
| | | redisService.deleteObject("rt:bluetooth:unlock:" + token); |
| | | redisService.deleteObject("rt:bluetooth:unlock:order:" + order.getId()); |
| | | XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData(); |
| | | BluetoothDeliverVo vo = new BluetoothDeliverVo(); |
| | | vo.setVim(xpVehicle.getVehicleVin()); |
| | | vo.setPassengerUid(order.getAppUserId()); |
| | | BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo); |
| | | if(null == delete || delete.getCode() != 0){ |
| | | log.error("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber()); |
| | | } |
| | | } |
| | | |
| | | XpOrderCancel xpOrderCancel = new XpOrderCancel(); |
| | | xpOrderCancel.setOrderId(orderId); |
| | |
| | | order.setStatus(0); |
| | | order.setAppUserId(null); |
| | | baseMapper.updateById(order); |
| | | order.setAppUserId(appUserId); |
| | | redisService.setCacheObject("ORDER_STATUS:" + order.getId(), 0, 24L, TimeUnit.HOURS); |
| | | //删除蓝牙秘钥 |
| | | String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + order.getId()); |
| | | if(StringUtils.isNotBlank(token)){ |
| | | redisService.deleteObject("rt:bluetooth:unlock:" + token); |
| | | redisService.deleteObject("rt:bluetooth:unlock:order:" + order.getId()); |
| | | XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData(); |
| | | BluetoothDeliverVo vo = new BluetoothDeliverVo(); |
| | | vo.setVim(xpVehicle.getVehicleVin()); |
| | | vo.setPassengerUid(order.getAppUserId()); |
| | | BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo); |
| | | if(null == delete || delete.getCode() != 0){ |
| | | log.error("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber()); |
| | | } |
| | | } |
| | | |
| | | XpOrderCancel xpOrderCancel = new XpOrderCancel(); |
| | | xpOrderCancel.setOrderId(Long.valueOf(orderId)); |
| | | xpOrderCancel.setUserId(1l); |
| | |
| | | throw new RuntimeException("订单状态错误"); |
| | | } |
| | | order.setStatus(8); |
| | | Long appUserId = order.getAppUserId(); |
| | | order.setAppUserId(null); |
| | | order.setTripEnd(LocalDateTime.now()); |
| | | baseMapper.updateById(order); |
| | | order.setAppUserId(appUserId); |
| | | redisService.setCacheObject("ORDER_STATUS:" + order.getId(), 8, 24L, TimeUnit.HOURS); |
| | | //删除蓝牙秘钥 |
| | | String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + orderId); |
| | | if(StringUtils.isNotBlank(token)){ |
| | | redisService.deleteObject("rt:bluetooth:unlock:" + token); |
| | | redisService.deleteObject("rt:bluetooth:unlock:order:" + orderId); |
| | | XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData(); |
| | | BluetoothDeliverVo vo = new BluetoothDeliverVo(); |
| | | vo.setVim(xpVehicle.getVehicleVin()); |
| | | vo.setPassengerUid(order.getAppUserId()); |
| | | BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo); |
| | | if(null == delete || delete.getCode() != 0){ |
| | | log.error("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber()); |
| | | } |
| | | } |
| | | |
| | | // 根据订单所属开通城市id 查询定价 |
| | | XpPricing pricing = bootCommonService.getXpPricing(order.getCityId(),order.getVehicleId()); |
| | |
| | | throw new ServiceException("下发蓝牙token失败"); |
| | | } |
| | | if(deliver.getCode() != 0){ |
| | | log.error("下发蓝牙token失败:{} {}", deliver.getMsg(), order.getOrderNumber()); |
| | | throw new ServiceException(deliver.getMsg()); |
| | | } |
| | | log.info("下发蓝牙token成功:{} {}", deliver.getData(), order.getOrderNumber()); |
| | |
| | | |
| | | import com.alibaba.nacos.common.utils.CollectionUtils; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.xiaopeng.api.dto.vehicleConvoy.BaseVehicleUserDto; |
| | | import com.xiaopeng.api.feignClient.vehicleConvoy.BluetoothUnlockClient; |
| | | import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; |
| | | import com.xiaopeng.api.model.order.XpOrder; |
| | | import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; |
| | | import com.xiaopeng.api.vo.vehicleConvoy.BluetoothDeliverVo; |
| | | import com.xiaopeng.common.core.utils.StringUtils; |
| | | import com.xiaopeng.common.redis.service.RedisService; |
| | | import com.xiaopeng.order.service.IXpOrderService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | import java.util.concurrent.TimeUnit; |
| | |
| | | |
| | | @Autowired |
| | | private RedisService redisService; |
| | | |
| | | @Resource |
| | | private XpVehicleClient xpVehicleClient; |
| | | |
| | | @Resource |
| | | private BluetoothUnlockClient bluetoothUnlockClient; |
| | | |
| | | /** |
| | | * 30秒执行一次 |
| | |
| | | order.setAppUserId(null); |
| | | order.setStatus(0); |
| | | xpOrderService.updateById(order); |
| | | order.setAppUserId(appUserId); |
| | | redisService.setCacheObject("ORDER_STATUS:" + order.getId(), 0, 24L, TimeUnit.HOURS); |
| | | //删除蓝牙秘钥 |
| | | String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + order.getId()); |
| | | if(StringUtils.isNotBlank(token)){ |
| | | redisService.deleteObject("rt:bluetooth:unlock:" + token); |
| | | redisService.deleteObject("rt:bluetooth:unlock:order:" + order.getId()); |
| | | XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData(); |
| | | BluetoothDeliverVo vo = new BluetoothDeliverVo(); |
| | | vo.setVim(xpVehicle.getVehicleVin()); |
| | | vo.setPassengerUid(order.getAppUserId()); |
| | | BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo); |
| | | if(null == delete || delete.getCode() != 0){ |
| | | log.error("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |