| | |
| | | import cn.afterturn.easypoi.excel.ExcelExportUtil; |
| | | import cn.afterturn.easypoi.excel.entity.ExportParams; |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import cn.hutool.core.util.DesensitizedUtil; |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.xiaopeng.api.dto.QueryOrderRouteDTO; |
| | |
| | | import com.xiaopeng.api.dto.order.PopOrderDto; |
| | | import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO; |
| | | import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO; |
| | | import com.xiaopeng.api.dto.vehicleConvoy.BaseVehicleUserDto; |
| | | import com.xiaopeng.api.feignClient.account.SysGroupMenuClient; |
| | | import com.xiaopeng.api.feignClient.frdXfipEvent.XpFrdXfipEventClient; |
| | | import com.xiaopeng.api.feignClient.operation.XpWhiteListClient; |
| | | import com.xiaopeng.api.feignClient.vehicleConvoy.VehicleMacClient; |
| | | import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; |
| | | import com.xiaopeng.api.model.operation.XpOfficialPartner; |
| | | import com.xiaopeng.api.model.operation.XpWhitelist; |
| | | import com.xiaopeng.api.model.order.OrderTrajectory; |
| | | import com.xiaopeng.api.model.order.XpOrder; |
| | | import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; |
| | | import com.xiaopeng.api.vo.automaticPilot.VehiclePosition; |
| | | import com.xiaopeng.api.vo.account.LoginUser; |
| | | import com.xiaopeng.api.vo.operation.NavigationVo; |
| | | import com.xiaopeng.api.vo.operation.NearestNextVo; |
| | | import com.xiaopeng.api.vo.operation.RouteVo; |
| | | import com.xiaopeng.api.vo.order.*; |
| | | import com.xiaopeng.api.vo.vehicleConvoy.GetBleInfoVo; |
| | | 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 com.xiaopeng.order.model.dto.XpOrderReassignDTO; |
| | | import com.xiaopeng.common.security.service.TokenService; |
| | | import com.xiaopeng.order.config.BluetoothDebugConfig; |
| | | import com.xiaopeng.order.dto.OrderNavigationDto; |
| | | import com.xiaopeng.order.model.dto.*; |
| | | import com.xiaopeng.order.model.exportExcel.XpOrderExportExcel; |
| | | import com.xiaopeng.order.model.query.XpHistoryOrderListQuery; |
| | | import com.xiaopeng.order.model.query.XpOrderExcelQuery; |
| | | import com.xiaopeng.order.model.query.XpOrderPageQuery; |
| | | import com.xiaopeng.order.model.vo.CreditPayCallVo; |
| | | import com.xiaopeng.order.model.vo.XpOrderDetailVO; |
| | | import com.xiaopeng.order.model.vo.XpOrderHistoryVO; |
| | | import com.xiaopeng.order.model.vo.XpOrderPageVO; |
| | | import com.xiaopeng.order.service.IXpOrderService; |
| | | import com.xiaopeng.order.vo.BluetoothTokenVo; |
| | | import com.xiaopeng.order.vo.OrderDetailVo; |
| | | import com.xiaopeng.order.vo.UpdateOrderStatusVo; |
| | | import com.xiaopeng.order.vo.XpOrderInfoVo; |
| | | import com.xiaopeng.unifiedverification.interceptor.XpClientCheck; |
| | | import io.swagger.annotations.*; |
| | | import lombok.RequiredArgsConstructor; |
| | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.net.URLEncoder; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | import java.time.LocalDateTime; |
| | | import java.time.ZoneOffset; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | private MongoTemplate mongoTemplate; |
| | | @Resource |
| | | private XpVehicleClient xpVehicleClient; |
| | | private OrderTrajectoryService orderTrajectoryService; |
| | | |
| | | @Resource |
| | | private VehicleMacClient vehicleMacClient; |
| | | |
| | | @Resource |
| | | private XpWhiteListClient xpWhiteListClient; |
| | | |
| | | @Resource |
| | | private TokenService tokenService; |
| | | |
| | | @Autowired |
| | | private BluetoothDebugConfig bluetoothDebugConfig; |
| | | |
| | | |
| | | |
| | | /** |
| | | * 获取订单统计数据(内部接口) |
| | |
| | | } |
| | | return R.ok(0L); |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 查询是否有未支付订单 |
| | | * 返回0 可以下单,非0为未支付订单ID |
| | | */ |
| | | @PostMapping("/logan/inner/order/has-unpay-order") |
| | | @ApiOperation(value = "查询是否有未支付订单", tags = {"内部接口"}) |
| | | public R<Long> hasUnPayOrder(String uid) { |
| | | XpOrder order = xpOrderService.getOne(new LambdaQueryWrapper<XpOrder>() |
| | | .eq(XpOrder::getAppUserId, Long.parseLong(uid)) |
| | | .eq(XpOrder::getStatus, 8) |
| | | .last("LIMIT 1")); |
| | | if (order != null) { |
| | | return R.ok(order.getId()); |
| | | } |
| | | return R.ok(0L); |
| | | } |
| | | |
| | | /** |
| | |
| | | * @param query 分页查询参数 |
| | | * @return 分页结果 |
| | | */ |
| | | @ApiOperation(value = "订单分页列表", tags = {"管理后台-交易管理-订单管理"}) |
| | | @ApiOperation(value = "订单分页列表", tags = {"管理后台-交易管理-订单管理", "管理后台-活动管理"}) |
| | | @PostMapping("/api/v1/order/pageList") |
| | | public R<PageInfo<XpOrderPageVO>> pageList( @RequestBody XpOrderPageQuery query) { |
| | | LoginUser loginUser = tokenService.getLoginUser(); |
| | | PageInfo<XpOrderPageVO> pageInfo = xpOrderService.pageList(query); |
| | | if(!loginUser.getPhoneDesensitizationExempt()){ |
| | | pageInfo.getRecords().forEach(s->s.setPhoneNumber(DesensitizedUtil.mobilePhone(s.getPhoneNumber()))); |
| | | } |
| | | |
| | | return R.ok(pageInfo); |
| | | } |
| | | |
| | |
| | | @ApiOperation(value = "订单详情", tags = {"管理后台-交易管理-订单管理"}) |
| | | @GetMapping("/api/v1/order/queryById") |
| | | public R<XpOrderDetailVO> queryById(@ApiParam(value = "订单id", required = true) @RequestParam Long id) { |
| | | LoginUser loginUser = tokenService.getLoginUser(); |
| | | XpOrderDetailVO detail = xpOrderService.getOrderDetail(id); |
| | | if(!loginUser.getPhoneDesensitizationExempt()){ |
| | | detail.setPhoneNumber(DesensitizedUtil.mobilePhone(detail.getPhoneNumber())); |
| | | } |
| | | |
| | | return R.ok(detail); |
| | | } |
| | | |
| | |
| | | * + |
| | | * 获取行程费用明细 |
| | | */ |
| | | @PutMapping("/api/v1/mini-program/order/fare-breakdown/{orderId}") |
| | | @PostMapping("/api/v1/mini-program/order/fare-breakdown") |
| | | @ApiOperation(value = "获取行程费用明细", tags = {"小程序-获取行程费用明细"}) |
| | | @XpClientCheck(checkToken = false, checkOtpToken = true) |
| | | public R<FareBreakdownVo> fareBreakdown(@PathVariable("orderId") Long orderId, HttpServletRequest request) { |
| | | public R<FareBreakdownVo> fareBreakdown(@RequestBody com.xiaopeng.order.vo.FareBreakdownVo vo, HttpServletRequest request) { |
| | | // uid已通过拦截器otp校验,可以直接使用 |
| | | String uid = request.getHeader("XP-Uid"); |
| | | return xpOrderService.fareBreakdown(orderId, uid); |
| | | return xpOrderService.fareBreakdown(vo, uid); |
| | | } |
| | | |
| | | /** |
| | |
| | | Object cacheObject = redisService.getCacheObject(key); |
| | | RouteVo routeVo = JSON.parseObject(cacheObject.toString(), RouteVo.class); |
| | | XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData(); |
| | | VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class); |
| | | routeVo.setDirection(null != vehiclePosition ? vehiclePosition.getCourse() : 90); |
| | | // VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class); |
| | | // routeVo.setDirection(null != vehiclePosition ? vehiclePosition.getCourse() : 90); |
| | | |
| | | Long vehicleId = xpOrder.getVehicleId(); |
| | | XpOrder one = xpOrderService.getOne(new QueryWrapper<XpOrder>().eq("vehicle_id", vehicleId).in("status", Arrays.asList(6, 7)).eq("is_deleted", 0)); |
| | |
| | | @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) { |
| | | public R<BluetoothTokenVo> getBluetoothToken(@PathVariable("orderId") Long orderId, HttpServletRequest request) { |
| | | |
| | | // ========== 联调临时逻辑:通过 Nacos 配置返回固定蓝牙信息(bluetooth-debug.enabled=true 时生效) ========== |
| | | if (bluetoothDebugConfig.isEnabled()) { |
| | | BluetoothTokenVo vo = new BluetoothTokenVo(); |
| | | vo.setToken(bluetoothDebugConfig.getToken()); |
| | | vo.setMacAddress(bluetoothDebugConfig.getMacAddress()); |
| | | vo.setSlaveMacList(bluetoothDebugConfig.getSlaveMacList()); |
| | | return R.ok(vo); |
| | | } |
| | | // ========== 联调临时逻辑结束 ========== |
| | | |
| | | // 原逻辑 |
| | | String uid = request.getHeader("XP-Uid"); |
| | | XpOrder xpOrder = xpOrderService.getById(orderId); |
| | | if (!Objects.equals(xpOrder.getAppUserId(), Long.valueOf(uid))) { |
| | |
| | | if (StringUtils.isBlank(token)) { |
| | | return R.ok(); |
| | | } |
| | | return R.ok(token); |
| | | XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData(); |
| | | GetBleInfoVo getBleInfoVo = new GetBleInfoVo(); |
| | | getBleInfoVo.setVin(xpVehicle.getVehicleVin()); |
| | | BaseVehicleUserDto baseVehicleUserDto = vehicleMacClient.getBleInfo(uid, getBleInfoVo); |
| | | if(null == baseVehicleUserDto || 200 != baseVehicleUserDto.getCode()){ |
| | | throw new ServiceException("获取蓝牙信息失败"); |
| | | } |
| | | JSONObject jsonObject = JSON.parseObject(baseVehicleUserDto.getData().toString()); |
| | | BluetoothTokenVo vo = new BluetoothTokenVo(); |
| | | vo.setToken(token); |
| | | vo.setMacAddress(jsonObject.getString("macAddress")); |
| | | vo.setSlaveMacList(jsonObject.getList("slaveMacList", String.class)); |
| | | return R.ok(vo); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 判断用户类型 |
| | | * @param userId |
| | | * @return 2=老用户,3=新用户,4=流失用户 |
| | | */ |
| | | @PostMapping("/logan/inner/order/determineUserType") |
| | | public R<Integer> determineUserType(@RequestParam Long userId){ |
| | | //判断流失用户 |
| | | XpOrder one = xpOrderService.getOne(new QueryWrapper<XpOrder>().eq("app_user_id", userId).in("status", Arrays.asList(9, 10)).last(" order by create_time desc limit 1")); |
| | | if(null != one){ |
| | | long time = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) - one.getCreateTime().toEpochSecond(ZoneOffset.of("+8")); |
| | | if(time >= 60 * 60 * 24 * 5){ |
| | | return R.ok(4); |
| | | } |
| | | return R.ok(2); |
| | | }else{ |
| | | return R.ok(3); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 判断用户类型 |
| | | * @param userType |
| | | * @return 2=老用户,3=新用户,4=流失用户 |
| | | */ |
| | | @PostMapping("/logan/inner/order/getUserTypeIdList") |
| | | public R<List<Long>> getUserTypeIdList(@RequestParam Integer userType){ |
| | | List<XpWhitelist> data = xpWhiteListClient.getXpWhitelistByName("").getData(); |
| | | //判断流失用户 |
| | | if(4 == userType){ |
| | | Set<Long> collect = data.stream().map(XpWhitelist::getAppUserId).collect(Collectors.toSet()); |
| | | List<XpOrder> one = xpOrderService.list(new QueryWrapper<XpOrder>().in("app_user_id", collect).in("status", Arrays.asList(9, 10)).last(" order by create_time desc limit 1")); |
| | | if(one.isEmpty()){ |
| | | return R.ok(new ArrayList<>()); |
| | | } |
| | | List<Long> appUserIds = new ArrayList<>(); |
| | | for (XpOrder order : one) { |
| | | long time = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) - order.getCreateTime().toEpochSecond(ZoneOffset.of("+8")); |
| | | if(time >= 60 * 60 * 24 * 5){ |
| | | appUserIds.add(order.getAppUserId()); |
| | | } |
| | | } |
| | | return R.ok(appUserIds); |
| | | } |
| | | //新用户 |
| | | if(3 == userType){ |
| | | Set<Long> collect = data.stream().map(XpWhitelist::getAppUserId).collect(Collectors.toSet()); |
| | | List<XpOrder> one = xpOrderService.list(new QueryWrapper<XpOrder>().in("app_user_id", collect).in("status", Arrays.asList(9, 10)).last(" order by create_time desc limit 1")); |
| | | if(one.isEmpty()){ |
| | | return R.ok(new ArrayList<>(collect)); |
| | | } |
| | | collect.removeAll(one.stream().map(XpOrder::getAppUserId).collect(Collectors.toList())); |
| | | return R.ok(new ArrayList<>(collect)); |
| | | } |
| | | |
| | | |
| | | //老用户 |
| | | if(2 == userType){ |
| | | Set<Long> collect = data.stream().map(XpWhitelist::getAppUserId).collect(Collectors.toSet()); |
| | | List<XpOrder> one = xpOrderService.list(new QueryWrapper<XpOrder>().in("app_user_id", collect).in("status", Arrays.asList(9, 10)).last(" order by create_time desc limit 1")); |
| | | if(one.isEmpty()){ |
| | | return R.ok(new ArrayList<>()); |
| | | } |
| | | List<Long> appUserIds = new ArrayList<>(); |
| | | for (XpOrder order : one) { |
| | | appUserIds.add(order.getAppUserId()); |
| | | } |
| | | return R.ok(appUserIds); |
| | | } |
| | | return R.ok(new ArrayList<>()); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取用户订单数量 |
| | | * @param userId |
| | | * @return |
| | | */ |
| | | @PostMapping("/logan/inner/order/getUserOrderNum") |
| | | public R<Long> getUserOrderNum(@RequestParam Long userId){ |
| | | long count = xpOrderService.count(new QueryWrapper<XpOrder>().eq("app_user_id", userId) |
| | | .ne("status", 0).eq("is_deleted", 0)); |
| | | return R.ok(count); |
| | | } |
| | | |
| | | |
| | | |
| | | @PostMapping("/drainage/v1/order/updateOrderStatus") |
| | | @ApiOperation(value = "更新订单状态", notes = "流量接入-订单信息") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header") |
| | | }) |
| | | public R<?> officialPartnerUpdateOrderStatus(@RequestBody UpdateOrderStatusVo vo, HttpServletRequest request){ |
| | | XpOfficialPartner officialPartner = tokenService.getOfficialPartner(); |
| | | return xpOrderService.officialPartnerUpdateOrderStatus(vo, officialPartner.getId()); |
| | | } |
| | | |
| | | |
| | | @PostMapping("/drainage/v1/order/getOrderNavigation") |
| | | @ApiOperation(value = "获取订单导航数据", notes = "流量接入-订单信息") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header") |
| | | }) |
| | | public R<NavigationVo> getOrderNavigation(@RequestBody OrderNavigationDto dto, HttpServletRequest request){ |
| | | XpOfficialPartner officialPartner = tokenService.getOfficialPartner(); |
| | | XpOrder xpOrder = xpOrderService.getById(dto.getOrderId()); |
| | | if(!xpOrder.getOfficialPartnerId().equals(officialPartner.getId())){ |
| | | return R.fail("无权限"); |
| | | } |
| | | NavigationVo navigationVo = null; |
| | | if(1 == dto.getNavigationType()){ |
| | | Object cacheObject = redisService.getCacheObject("ORDER_NAVIGATION_START_DATA:" + xpOrder.getAppUserId()); |
| | | if(null != cacheObject){ |
| | | navigationVo = JSON.parseObject(cacheObject.toString(), NavigationVo.class); |
| | | } |
| | | } |
| | | if(2 == dto.getNavigationType()){ |
| | | Object cacheObject = redisService.getCacheObject("ORDER_NAVIGATION_END_DATA:" + xpOrder.getAppUserId()); |
| | | if(null != cacheObject){ |
| | | navigationVo = JSON.parseObject(cacheObject.toString(), NavigationVo.class); |
| | | } |
| | | } |
| | | return R.ok(navigationVo); |
| | | } |
| | | |
| | | |
| | | @PostMapping("/drainage/v1/order/getOrderInfo") |
| | | @ApiOperation(value = "获取订单详情", notes = "流量接入-订单信息") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header") |
| | | }) |
| | | public R<XpOrderInfoVo> getOfficialPartnerOrderInfo(@PathVariable Long orderId){ |
| | | XpOfficialPartner officialPartner = tokenService.getOfficialPartner(); |
| | | XpOrder xpOrder = xpOrderService.getById(orderId); |
| | | if(!xpOrder.getOfficialPartnerId().equals(officialPartner.getId())){ |
| | | return R.fail("无权限"); |
| | | } |
| | | XpOrderInfoVo xpOrderInfoVo = BeanUtil.copyProperties(xpOrder, XpOrderInfoVo.class); |
| | | return R.ok(xpOrderInfoVo); |
| | | } |
| | | |
| | | |
| | | |
| | | @ApiOperation(value = "获取订单支付状态", tags = {"小程序-业务流程"}) |
| | | @GetMapping("/api/v1/mini-program/order/queryOrderStatusFromOrderId") |
| | | @XpClientCheck(checkToken = false, checkOtpToken = true) |
| | | public R<OrderStatusFromOrderIdVo> queryOrderStatusFromOrderId(Long orderId) { |
| | | |
| | | XpOrder order = xpOrderService.getById(orderId); |
| | | |
| | | OrderStatusFromOrderIdVo orderStatusFromOrderIdVo = new OrderStatusFromOrderIdVo(); |
| | | orderStatusFromOrderIdVo.setOrderId(order.getId()); |
| | | orderStatusFromOrderIdVo.setStatus(order.getStatus()); |
| | | return R.ok( xpOrderService.queryOrderStatusFromOrderId(orderId)); |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 信用支付下单回调 |
| | | */ |
| | | @PostMapping("/base/v1/mini-program/order/creditPayCall") |
| | | @ApiOperation(value = "信用支付下单回调", tags = {"小程序-发起支付"}, response = CreditPayCallVo.class) |
| | | public CreditPayCallVo creditPayCall(@RequestBody CreditPayCallDto dto) { |
| | | CreditPayCallVo vo = new CreditPayCallVo(); |
| | | vo.setRetCode("0"); |
| | | vo.setRetMsg("成功"); |
| | | |
| | | if (dto == null || (StringUtils.isBlank(dto.getAuthOrderId()) || StringUtils.isBlank(dto.getBusinessOrderId()))) { |
| | | return vo; |
| | | } |
| | | |
| | | LambdaQueryWrapper<XpOrder> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.eq(XpOrder::getAuthOrderId, dto.getAuthOrderId()); |
| | | XpOrder order = xpOrderService.getOne(wrapper.last("LIMIT 1")); |
| | | if (order == null) { |
| | | return vo; |
| | | } |
| | | if ("SUCCESS".equals(dto.getCreditOrderStatus())) { |
| | | // 发起扣款 |
| | | xpOrderService.creditPayCall(order); |
| | | } |
| | | return vo; |
| | | } |
| | | |
| | | /** |
| | | * 信用扣款回调 |
| | | */ |
| | | @PostMapping("/base/v1/mini-program/order/creditPaySuccessCall") |
| | | @ApiOperation(value = "信用扣款回调", tags = {"小程序-发起支付"}, response = CreditPayCallVo.class) |
| | | public CreditPayCallVo creditPaySuccessCall(@RequestBody CreditPaySuccessCallDto dto) { |
| | | |
| | | LambdaQueryWrapper<XpOrder> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.eq(XpOrder::getAuthOrderId, dto.getAuthOrderId()); |
| | | XpOrder order = xpOrderService.getOne(wrapper.last("LIMIT 1")); |
| | | if(dto.getPayStatus()==1){ |
| | | order.setStatus(9); |
| | | order.setAppUserId(null); |
| | | xpOrderService.updateById(order); |
| | | CreditPayCallVo vo = new CreditPayCallVo(); |
| | | vo.setRetCode("0"); |
| | | vo.setRetMsg("成功"); |
| | | |
| | | // 对接财务 |
| | | xpOrderService.xpFrdXfipEventPush(order,dto.getPayFee(),dto.getOrderId()); |
| | | |
| | | return vo; |
| | | } |
| | | return null; |
| | | |
| | | } |
| | | |
| | | } |