| | |
| | | package com.xiaopeng.operation.service.impl; |
| | | |
| | | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | |
| | | import com.xiaopeng.operation.service.IXpGeoQueryEntityService; |
| | | import com.xiaopeng.operation.service.XpPricingService; |
| | | import com.xiaopeng.operation.utils.XpPricingUtil; |
| | | import com.xiaopeng.operation.utils.holiday.HolidayUtil; |
| | | import com.xiaopeng.operation.utils.map.FastDistanceCalculator; |
| | | import com.xiaopeng.operation.vo.XpPricingCardVo; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | @Resource |
| | | private XpAppUserClient xpAppUserClient; |
| | | |
| | | @Resource |
| | | private HolidayUtil holidayUtil; |
| | | |
| | | @Autowired |
| | | private IXpGeoQueryEntityService geoQueryEntityService; |
| | | |
| | | @Autowired |
| | | private XpElectronicFenceMapper xpElectronicFenceMapper; |
| | | |
| | | |
| | | // 自定义线程池用于并行执行任务 |
| | | private final ExecutorService executorService; |
| | | |
| | | |
| | | // 初始化自定义线程池 |
| | | public XpPricingServiceImpl() { |
| | |
| | | + "-" + routeAndFareDto.getDestination().getLongitude() + "-" + routeAndFareDto.getDestination().getLatitude() + "-" + getCurrentTimeSlot() + "-" + userId; |
| | | |
| | | if (redisService.hasKey(key)) { |
| | | String jsonStr = Objects.requireNonNull(redisService.getCacheObject( key)).toString(); |
| | | String jsonStr = Objects.requireNonNull(redisService.getCacheObject(key)).toString(); |
| | | RouteAndFareVo RouteAndFareVo = JSONObject.parseObject(jsonStr, RouteAndFareVo.class); |
| | | return (RouteAndFareVo); |
| | | } |
| | |
| | | // 优惠券 |
| | | CompletableFuture<R<UserCouponVo>> couponFuture = CompletableFuture.supplyAsync( |
| | | () -> { |
| | | // 优惠券 |
| | | return xpAppUserCouponClient.getUserCoupon( |
| | | // 优惠券 |
| | | return xpAppUserCouponClient.getUserCoupon( |
| | | // new GetUserCouponDto(Long.valueOf(userId), xpPricingCardVo.getTotalPrice(),routeAndFareDto.getOpenCityId()) |
| | | new GetUserCouponDto(Long.valueOf(userId), 1d,routeAndFareDto.getOpenCityId()) |
| | | ); |
| | | new GetUserCouponDto(Long.valueOf(userId), 1d, routeAndFareDto.getOpenCityId()) |
| | | ); |
| | | }, |
| | | executorService |
| | | ); |
| | |
| | | |
| | | // 10. 检查等待时间 |
| | | Integer waitTime = getWaitTime(routeAndFareDto.getOrigin().getLongitude(), routeAndFareDto.getOrigin().getLatitude()); |
| | | if(waitTime>3){ |
| | | if (waitTime > 3) { |
| | | throw new ServiceException("当前区域正在等待中,请耐心等待", I18nKeyConstant.WAITING_TIME); |
| | | } |
| | | fareVo.setWaitingTime(waitTime); |
| | |
| | | * @return |
| | | */ |
| | | @Override |
| | | public Integer getWaitTime(double lon,double lat) { |
| | | public Integer getWaitTime(double lon, double lat) { |
| | | List<XpGeoQueryEntity> entities = geoQueryEntityService.findByLocationWithin500MetersAndLastWeekAndStatusGreater( |
| | | lon, |
| | | lat, |
| | |
| | | |
| | | |
| | | if (entities.isEmpty()) { |
| | | return 1; |
| | | return 1; |
| | | } else { |
| | | // 已完成接单的数据 |
| | | List<XpGeoQueryEntity> validEntities = entities.stream().filter(e -> e.getStatus() > 1).collect(Collectors.toList()); |
| | |
| | | // 未完成接单的数量 |
| | | int count = entities.size() - validEntities.size(); |
| | | if (count == 0) { |
| | | return 1; |
| | | return 1; |
| | | } else { |
| | | double waitMinutes = (average * count) / 60; |
| | | if (waitMinutes > 3) { |
| | |
| | | return (int) waitMinutes; |
| | | } |
| | | } else { |
| | | return 1; |
| | | return 1; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public Long saveOrder(XpOrderDto dto, String uid) { |
| | | // 是否在运营区域时间内 |
| | | XpElectronicFenceArea xpElectronicFenceArea = xpElectronicFenceAreaMapper.selectById(dto.getXpElectronicFenceAreaId()); |
| | | XpElectronicFence xpElectronicFence = xpElectronicFenceMapper.selectById(xpElectronicFenceArea.getElectronicId()); |
| | | String operationStrategy = xpElectronicFence.getOperationStrategy(); |
| | | Boolean inOperationTime = isInOperationTime(operationStrategy); |
| | | if (!inOperationTime) { |
| | | throw new ServiceException("当前区域未开通服务", I18nKeyConstant.NO_CURRENT_REGION); |
| | | } |
| | | |
| | | |
| | | Integer cancelCount = xpTradingStrategyMapper.selectOne(null).getCancleCount(); |
| | | // 判断是否有进行的订单 |
| | | R<Long> r = xpOrderClient.hasUnPaodOrder(uid); |
| | | if(r.getData()>0){ |
| | | if (r.getData() > 0) { |
| | | throw new RuntimeException("有正在进行的订单"); |
| | | } |
| | | |
| | |
| | | |
| | | // 判断当天取消的次数 后台配置 redis 查询 |
| | | Object cancelOrder = redisService.getCacheObject("CANCEL_ORDER_" + uid); |
| | | if(cancelOrder!=null){ |
| | | if (cancelOrder != null) { |
| | | Integer num = Integer.valueOf(cancelOrder.toString()); |
| | | if(num>=cancelCount){ |
| | | if (num >= cancelCount) { |
| | | return 0l; |
| | | } |
| | | } |
| | | |
| | | |
| | | // 获取起步里程 |
| | | XpPricing xpPricing = this.baseMapper.selectOne(new LambdaQueryWrapper<XpPricing>().eq(XpPricing::getCityId, dto.getOpenCityId())); |
| | | Integer startMileage = XpPricingUtil.getStartMileage(xpPricing.getStartingFareJson()); |
| | | if (startMileage == null) { |
| | | throw new ServiceException("当前区域未开通服务", I18nKeyConstant.NO_CURRENT_REGION); |
| | | } |
| | | |
| | | |
| | | // 根据id获取手机号 |
| | | |
| | | Boolean isPriorityDispatch=false; |
| | | Boolean isPriorityDispatch = false; |
| | | R<XpAppUser> xpAppUserR = xpAppUserClient.queryOperationsUserById(Long.valueOf(uid)); |
| | | if(xpAppUserR.getCode()==R.SUCCESS){ |
| | | if (xpAppUserR.getCode() == R.SUCCESS) { |
| | | Long count = xpWhitelistMapper.selectCount(new LambdaQueryWrapper<XpWhitelist>().eq(XpWhitelist::getAccount, xpAppUserR.getData().getPhoneNumber()).eq(XpWhitelist::getIsPriorityDispatch, 1)); |
| | | if(count>0){ |
| | | isPriorityDispatch=true; |
| | | if (count > 0) { |
| | | isPriorityDispatch = true; |
| | | } |
| | | } |
| | | |
| | | // 生成订单数据 |
| | | XpOrder xpOrder = new XpOrder(); |
| | | |
| | | xpOrder.setStartMileage(Double.valueOf(startMileage)); |
| | | |
| | | xpOrder.setAppUserId(Long.valueOf(uid)); |
| | | xpOrder.setOrderNumber("XP"+System.currentTimeMillis()); |
| | | xpOrder.setOrderNumber("XP" + System.currentTimeMillis()); |
| | | xpOrder.setPlacementLon(dto.getPlacementLon()); |
| | | xpOrder.setPlacementLat(dto.getPlacementLat()); |
| | | xpOrder.setPlacementAddress(dto.getPlacementAddress()); |
| | |
| | | R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto); |
| | | Integer distance = 0; |
| | | Integer duration = 0; |
| | | if(distanceAndDuration.getCode()!=200){ |
| | | if (distanceAndDuration.getCode() != 200) { |
| | | //静默处理 |
| | | return 0l; |
| | | } |
| | | distance=distanceAndDuration.getData().getDistance(); |
| | | duration=distanceAndDuration.getData().getDuration(); |
| | | distance = distanceAndDuration.getData().getDistance(); |
| | | duration = distanceAndDuration.getData().getDuration(); |
| | | |
| | | |
| | | // 产生订单 |
| | | R<Long> addOrderR = xpOrderClient.addOrder(xpOrder); |
| | | if(addOrderR.getCode()!=R.SUCCESS){ |
| | | if (addOrderR.getCode() != R.SUCCESS) { |
| | | throw new ServiceException("订单生成失败", I18nKeyConstant.ORDER_CREATE_FAIL); |
| | | } |
| | | Long orderId = addOrderR.getData(); |
| | | // 最大距离 |
| | | Object maxPushDistanceObj = redisService.getCacheObject(CacheConstants.MAX_PUSH_DISTANCE); |
| | | Double maxPushDistance= 0.0; |
| | | if(maxPushDistanceObj!=null){ |
| | | maxPushDistance = Double.valueOf(maxPushDistanceObj.toString()); |
| | | }else { |
| | | maxPushDistance = xpTradingStrategyMapper.selectOne(null).getThreePushDistance(); |
| | | Double maxPushDistance = 0.0; |
| | | if (maxPushDistanceObj != null) { |
| | | maxPushDistance = Double.valueOf(maxPushDistanceObj.toString()); |
| | | } else { |
| | | maxPushDistance = xpTradingStrategyMapper.selectOne(null).getThreePushDistance(); |
| | | } |
| | | |
| | | // 找出现在所有的队列 通过计算距离 算出目前应该放在那个队列 如果没有符合的新增一个队列 符合后看是否白名单账号 是则直接放在队列前端 |
| | |
| | | String lonLat = s.split("-")[2]; |
| | | // 和上车点进行判断是否<maxPushDistance |
| | | double v = FastDistanceCalculator.distanceFast(Double.parseDouble(lonLat.split(",")[1]), Double.parseDouble(lonLat.split(",")[0]), xpPoint.getPointLat(), xpPoint.getPointLon()); |
| | | if(v<maxPushDistance){ |
| | | if(isPriorityDispatch){ |
| | | if (v < maxPushDistance) { |
| | | if (isPriorityDispatch) { |
| | | // 头部 value 订单_经纬度_状态_用户id_订单编号_距离_时间 |
| | | redisService.addToTail(s,orderId+"_"+xpPoint.getPointLon()+","+xpPoint.getPointLat()+"_0"+"_"+uid+"_"+xpOrder.getOrderNumber()+"_"+distance+"_"+duration+"_"+routeAndFareDto.getRoutePlanRule()); |
| | | }else { |
| | | redisService.addToTail(s, orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + routeAndFareDto.getRoutePlanRule()); |
| | | } else { |
| | | // 尾部 |
| | | redisService.addToTail(s,orderId+"_"+xpPoint.getPointLon()+","+xpPoint.getPointLat()+"_0"+"_"+uid+"_"+xpOrder.getOrderNumber()+"_"+distance+"_"+duration+"_"+routeAndFareDto.getRoutePlanRule()); |
| | | redisService.addToTail(s, orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + routeAndFareDto.getRoutePlanRule()); |
| | | } |
| | | return orderId; |
| | | } |
| | | } |
| | | |
| | | String key = CacheConstants.QUEUE_POINT_ID+"-"+ xpPoint.getId()+"-"+xpPoint.getPointLon()+","+xpPoint.getPointLat(); |
| | | redisService.setCacheList(key,Arrays.asList(orderId+"_"+xpPoint.getPointLon()+","+xpPoint.getPointLat()+"_0"+"_"+uid+"_"+xpOrder.getOrderNumber()+"_"+distance+"_"+duration+"_"+routeAndFareDto.getRoutePlanRule())); |
| | | String key = CacheConstants.QUEUE_POINT_ID + "-" + xpPoint.getId() + "-" + xpPoint.getPointLon() + "," + xpPoint.getPointLat(); |
| | | redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + routeAndFareDto.getRoutePlanRule())); |
| | | return orderId; |
| | | |
| | | // |
| | |
| | | // |
| | | |
| | | |
| | | |
| | | |
| | | // 产生订单 存订单数据 // 下发指令 消息推送用户端 |
| | | // return null; |
| | | |
| | | } |
| | | |
| | | |
| | | private Boolean isInOperationTime(String operationStrategy) { |
| | | JSONArray jsonArray = JSONArray.parseArray(operationStrategy); |
| | | Integer holidayToday = holidayUtil.isHolidayToday(); |
| | | for (Object o : jsonArray) { |
| | | JSONObject jsonObject = JSONObject.parseObject(o.toString()); |
| | | String type = jsonObject.getString("type"); |
| | | if (type.equals(holidayToday.toString())) { |
| | | JSONArray time = jsonObject.getJSONArray("time"); |
| | | // 判断当前时间 是否在time时间段中 |
| | | for (Object object : time) { |
| | | String[] timeArray = object.toString().split("-"); |
| | | String startTime = timeArray[0]; |
| | | String endTime = timeArray[1]; |
| | | boolean currentTimeInRange = DateUtils.isCurrentTimeInRange(startTime, endTime); |
| | | if (currentTimeInRange) { |
| | | return true; |
| | | } |
| | | } |
| | | } else if (type.equals("3")) { |
| | | // 判断是什么类型 0每天 1-7 想起 |
| | | String typeStr = jsonObject.getString("typeStr"); |
| | | // 查看今天周几 |
| | | Integer week = DateUtils.getWeek(); |
| | | // 包含每天 或者 包含当天 |
| | | if (typeStr.contains("0") || typeStr.contains(week.toString())) { |
| | | JSONArray time = jsonObject.getJSONArray("time"); |
| | | // 判断当前时间 是否在time时间段中 |
| | | for (Object object : time) { |
| | | String[] timeArray = object.toString().split("-"); |
| | | String startTime = timeArray[0]; |
| | | String endTime = timeArray[1]; |
| | | boolean currentTimeInRange = DateUtils.isCurrentTimeInRange(startTime, endTime); |
| | | if (currentTimeInRange) { |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | |
| | | } |