rk
4 天以前 21bd711a3756850299b443848181ee60708c6377
server/services/src/main/java/com/doumee/service/business/impl/OrdersServiceImpl.java
@@ -33,6 +33,7 @@
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;
@@ -111,6 +112,10 @@
    @Autowired
    private PricingRuleMapper pricingRuleMapper;
    @Autowired
    private PricingRuleService pricingRuleService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
@@ -303,9 +308,9 @@
     */
    @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<>();
@@ -364,9 +369,9 @@
            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();
        }
@@ -504,9 +509,9 @@
            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();
        }
@@ -633,6 +638,11 @@
                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();
@@ -647,15 +657,12 @@
        // ========== 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 {
@@ -667,7 +674,6 @@
            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);
@@ -1714,6 +1720,24 @@
        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);
    }
@@ -2857,4 +2881,29 @@
        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;
    }
}