| | |
| | | import com.doumee.service.business.OrderLogService; |
| | | import com.doumee.service.business.OrdersService; |
| | | import com.doumee.service.business.AreasService; |
| | | import com.doumee.service.business.PricingRuleService; |
| | | import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest; |
| | | import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; |
| | | import com.github.binarywang.wxpay.exception.WxPayException; |
| | |
| | | |
| | | @Autowired |
| | | private PricingRuleMapper pricingRuleMapper; |
| | | |
| | | @Autowired |
| | | private PricingRuleService pricingRuleService; |
| | | |
| | | @Autowired |
| | | private RedisTemplate<String, Object> redisTemplate; |
| | | |
| | |
| | | */ |
| | | @Override |
| | | public PriceCalculateVO calculateLocalPrice(CalculateLocalPriceDTO dto) { |
| | | // 天数校验,最少1天 |
| | | int days = dto.getEstimatedDepositDays() != null && dto.getEstimatedDepositDays() > 0 |
| | | ? dto.getEstimatedDepositDays() : 1; |
| | | // 根据开始和结束时间计算天数,最少1天 |
| | | long diffMs = dto.getDepositEndTime().getTime() - dto.getDepositStartTime().getTime(); |
| | | int days = (int) Math.max(1, (diffMs / (1000 * 60 * 60 * 24)) + 1); |
| | | |
| | | // 收集所有物品类型ID |
| | | List<Integer> categoryIds = new ArrayList<>(); |
| | |
| | | itemPriceTotal += subtotal; |
| | | } |
| | | |
| | | // 保价费用:报价金额 × 保价费率(字典 INSURANCE_RATE),元→分 |
| | | // 保价费用:报价金额 × 保价费率(字典 INSURANCE_RATE),元→分(保价金额>0时计费) |
| | | long insuranceFeeFen = 0L; |
| | | if (Boolean.TRUE.equals(dto.getInsured()) && dto.getDeclaredAmount() != null) { |
| | | if (dto.getDeclaredAmount() != null && dto.getDeclaredAmount().compareTo(BigDecimal.ZERO) > 0) { |
| | | BigDecimal insuranceFeeYuan = calculateInsuranceFee(dto.getDeclaredAmount()); |
| | | insuranceFeeFen = insuranceFeeYuan.multiply(new BigDecimal(100)).longValue(); |
| | | } |
| | |
| | | itemPriceTotal += subtotal; |
| | | } |
| | | |
| | | // 4. 保价费用:报价金额 × 保价费率(字典 INSURANCE_RATE),元→分 |
| | | // 4. 保价费用:报价金额 × 保价费率(字典 INSURANCE_RATE),元→分(保价金额>0时计费) |
| | | long insuranceFeeFen = 0L; |
| | | if (Boolean.TRUE.equals(dto.getInsured()) && dto.getDeclaredAmount() != null) { |
| | | if (dto.getDeclaredAmount() != null && dto.getDeclaredAmount().compareTo(BigDecimal.ZERO) > 0) { |
| | | BigDecimal insuranceFeeYuan = calculateInsuranceFee(dto.getDeclaredAmount()); |
| | | insuranceFeeFen = insuranceFeeYuan.multiply(new BigDecimal(100)).longValue(); |
| | | } |
| | |
| | | takeLgt = BigDecimal.valueOf(takeShop.getLongitude()); |
| | | takeLocationValue = takeShop.getAddress(); |
| | | } else if (dto.getTakeLat() != null && dto.getTakeLgt() != null && StringUtils.isNotBlank(dto.getTakeLocation())) { |
| | | // 无取件门店,校验存件点与自选取件点是否在同一城市 |
| | | if (MapUtil.isSameCity(depositShop.getLatitude(), depositShop.getLongitude(), |
| | | dto.getTakeLat().doubleValue(), dto.getTakeLgt().doubleValue())) { |
| | | throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "异地寄存订单存取点不能在同一城市,如需同城寄存请选择就近门店"); |
| | | } |
| | | takeLat = dto.getTakeLat(); |
| | | takeLgt = dto.getTakeLgt(); |
| | | takeLocationValue = dto.getTakeLocation(); |
| | |
| | | // ========== 3. 计算费用 ========== |
| | | PriceCalculateVO priceResult; |
| | | if (Constants.ZERO.equals(dto.getType())) { |
| | | // 就地寄存:计算天数 |
| | | long diffMs = takeTime.getTime() - depositTime.getTime(); |
| | | int days = (int) Math.max(1, (diffMs / (1000 * 60 * 60 * 24)) + 1); |
| | | |
| | | // 就地寄存 |
| | | CalculateLocalPriceDTO priceDTO = new CalculateLocalPriceDTO(); |
| | | priceDTO.setCityId(dto.getCityId()); |
| | | priceDTO.setEstimatedDepositDays(days); |
| | | priceDTO.setDepositStartTime(depositTime); |
| | | priceDTO.setDepositEndTime(takeTime); |
| | | priceDTO.setItems(dto.getItems()); |
| | | priceDTO.setInsured(dto.getDeclaredAmount() != null && dto.getDeclaredAmount().compareTo(BigDecimal.ZERO) > 0); |
| | | priceDTO.setDeclaredAmount(dto.getDeclaredAmount()); |
| | | priceResult = calculateLocalPrice(priceDTO); |
| | | } else { |
| | |
| | | priceDTO.setToLat(takeLat); |
| | | priceDTO.setToLgt(takeLgt); |
| | | priceDTO.setItems(dto.getItems()); |
| | | priceDTO.setInsured(dto.getDeclaredAmount() != null && dto.getDeclaredAmount().compareTo(BigDecimal.ZERO) > 0); |
| | | priceDTO.setDeclaredAmount(dto.getDeclaredAmount()); |
| | | priceDTO.setUrgent(Constants.ONE.equals(dto.getIsUrgent())); |
| | | priceResult = calculateRemotePrice(priceDTO); |
| | |
| | | order.setUpdateTime(now); |
| | | // 生成会员核销码 |
| | | order.setMemberVerifyCode(generateVerifyCode()); |
| | | // 异地寄存:计算预计送达时间 |
| | | if (Constants.ONE.equals(order.getType()) |
| | | && order.getDepositLat() != null && order.getDepositLgt() != null |
| | | && order.getTakeLat() != null && order.getTakeLgt() != null) { |
| | | EstimatedDeliveryResultVO deliveryResult = calculateEstimatedDelivery( |
| | | Integer.valueOf(order.getCityId()), |
| | | order.getDepositLat().doubleValue(), order.getDepositLgt().doubleValue(), |
| | | order.getTakeLat().doubleValue(), order.getTakeLgt().doubleValue()); |
| | | // isUrgent: 0=标速达; 1=极速达 |
| | | BigDecimal hours = Constants.ONE.equals(order.getIsUrgent()) |
| | | ? deliveryResult.getExpressHours() |
| | | : deliveryResult.getStandardHours(); |
| | | if (hours != null) { |
| | | long millis = hours.multiply(new BigDecimal("3600000")) |
| | | .setScale(0, RoundingMode.HALF_UP).longValue(); |
| | | order.setEstimatedDeliveryTime(new Date(now.getTime() + millis)); |
| | | } |
| | | } |
| | | ordersMapper.updateById(order); |
| | | } |
| | | |
| | |
| | | return Math.max(days, 0); |
| | | } |
| | | |
| | | @Override |
| | | public EstimatedDeliveryResultVO calculateEstimatedDelivery(Integer cityId, |
| | | Double fromLat, Double fromLng, |
| | | Double toLat, Double toLng) { |
| | | // 腾讯地图距离矩阵API计算实际距离 |
| | | String from = fromLat + "," + fromLng; |
| | | String to = toLat + "," + toLng; |
| | | JSONObject distanceResult = MapUtil.distanceSingle("driving", from, to); |
| | | |
| | | // 获取距离(米),转公里 |
| | | int distanceMeters = distanceResult.getIntValue("distance"); |
| | | BigDecimal distanceKm = new BigDecimal(distanceMeters) |
| | | .divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP); |
| | | |
| | | // 根据pricing_rule type=2 计算 标速达(1) 和 极速达(2) 时效 |
| | | BigDecimal standardTime = pricingRuleService.calculateEstimatedTime(cityId, 1, distanceKm); |
| | | BigDecimal expressTime = pricingRuleService.calculateEstimatedTime(cityId, 2, distanceKm); |
| | | |
| | | EstimatedDeliveryResultVO vo = new EstimatedDeliveryResultVO(); |
| | | vo.setDistanceKm(distanceKm); |
| | | vo.setStandardHours(standardTime); |
| | | vo.setExpressHours(expressTime); |
| | | return vo; |
| | | } |
| | | |
| | | } |