| 
						 
							
							
							
						 
					 | 
				
			
			 | 
			 | 
			
				@@ -0,0 +1,228 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				package cn.iocoder.yudao.module.trade.service.price.calculator;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import cn.iocoder.yudao.module.member.api.address.AddressApi;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateFreeDO;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateChargeMapper;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateFreeMapper;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO.OrderItem;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.springframework.core.annotation.Order;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.springframework.stereotype.Component;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import javax.annotation.Resource;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import java.util.HashMap;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import java.util.List;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import java.util.Map;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import java.util.Set;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/**
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * 运费的 {@link TradePriceCalculator} 实现类
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 * @author jason
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				@Component
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				@Order(TradePriceCalculator.ORDER_DELIVERY)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    @Resource
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private AddressApi addressApi;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    @Resource
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private ProductSkuApi productSkuApi;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    @Resource
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private DeliveryExpressTemplateService deliveryExpressTemplateService;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    @Resource
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private DeliveryExpressTemplateChargeMapper templateChargeMapper;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    @Resource
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private DeliveryExpressTemplateFreeMapper templateFreeMapper;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    @Override
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // 1.1 判断配送方式
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (param.getDeliveryType() == null || DeliveryTypeEnum.PICK_UP.getMode().equals(param.getDeliveryType())) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (param.getTemplateId() == null || param.getAddressId() == null) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // 1.2 校验运费模板是否存在
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        DeliveryExpressTemplateDO template = deliveryExpressTemplateService.validateDeliveryExpressTemplate(param.getTemplateId());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // 得到包邮配置
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        List<DeliveryExpressTemplateFreeDO> expressTemplateFreeList = templateFreeMapper.selectListByTemplateId(template.getId());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        Map<Integer, DeliveryExpressTemplateFreeDO> areaTemplateFreeMap = new HashMap<>();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        expressTemplateFreeList.forEach(item -> {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            for (Integer areaId : item.getAreaIds()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                // TODO 需要保证 areaId 不能重复
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if (!areaTemplateFreeMap.containsKey(areaId)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    areaTemplateFreeMap.put(areaId, item);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // 得到快递运费配置
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        List<DeliveryExpressTemplateChargeDO> expressTemplateChargeList = templateChargeMapper.selectListByTemplateId(template.getId());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        Map<Integer, DeliveryExpressTemplateChargeDO> areaTemplateChargeMap = new HashMap<>();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        expressTemplateChargeList.forEach(item -> {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            for (Integer areaId : item.getAreaIds()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                // areaId 不能重复
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if (!areaTemplateChargeMap.containsKey(areaId)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    areaTemplateChargeMap.put(areaId, item);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // 得到收件地址区域
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        AddressRespDTO address = addressApi.getAddress(param.getAddressId(), param.getUserId());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // 1.3 计算快递费用
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        calculateDeliveryPrice(address.getAreaId(), template.getChargeMode(),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                areaTemplateFreeMap, areaTemplateChargeMap, result);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    /**
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * 校验订单是否满足包邮条件
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * @param receiverAreaId        收件人地区的区域编号
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * @param chargeMode            配送计费方式
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * @param areaTemplateFreeMap   运费模板包邮区域设置 Map
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * @param areaTemplateChargeMap 运费模板快递费用设置 Map
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private void calculateDeliveryPrice(Integer receiverAreaId,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                        Integer chargeMode,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                        Map<Integer, DeliveryExpressTemplateFreeDO> areaTemplateFreeMap,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                        Map<Integer, DeliveryExpressTemplateChargeDO> areaTemplateChargeMap,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                        TradePriceCalculateRespBO result) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // 过滤出已选中的商品SKU
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        List<OrderItem> selectedItem = filterList(result.getItems(), OrderItem::getSelected);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        Set<Long> skuIds = convertSet(selectedItem, OrderItem::getSkuId);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // 得到SKU 详情。得到 重量体积
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        Map<Long, ProductSkuRespDTO> skuRespMap = convertMap(productSkuApi.getSkuList(skuIds), ProductSkuRespDTO::getId);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // 一个 spuId 可能对应多条订单商品 SKU
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        Map<Long, List<OrderItem>> spuIdItemMap = convertMultiMap(selectedItem, OrderItem::getSpuId);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // 依次计算每个 SPU 的快递运费
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        for (Map.Entry<Long, List<OrderItem>> entry : spuIdItemMap.entrySet()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            List<OrderItem> orderItems = entry.getValue();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // 总件数, 总金额, 总重量, 总体积
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            int totalCount = 0, totalPrice = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            double totalWeight = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            double totalVolume = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            for (OrderItem orderItem : orderItems) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                totalCount += orderItem.getCount();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                totalPrice += orderItem.getPrice();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ProductSkuRespDTO skuResp = skuRespMap.get(orderItem.getSkuId());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if (skuResp != null) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    totalWeight = totalWeight + skuResp.getWeight();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    totalVolume = totalVolume + skuResp.getVolume();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // 优先判断是否包邮. 如果包邮不计算快递运费
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if (areaTemplateFreeMap.containsKey(receiverAreaId) &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    checkExpressFree(chargeMode, totalCount, totalWeight,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            totalVolume, totalPrice, areaTemplateFreeMap.get(receiverAreaId))) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                continue;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // 计算快递运费
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if (areaTemplateChargeMap.containsKey(receiverAreaId)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                DeliveryExpressTemplateChargeDO templateCharge = areaTemplateChargeMap.get(receiverAreaId);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                DeliveryExpressChargeModeEnum chargeModeEnum = DeliveryExpressChargeModeEnum.valueOf(chargeMode);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                switch (chargeModeEnum) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    case PIECE: {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        calculateExpressFeeBySpu(totalCount, templateCharge, orderItems);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    case WEIGHT: {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        calculateExpressFeeBySpu(totalWeight, templateCharge, orderItems);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    case VOLUME: {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        calculateExpressFeeBySpu(totalVolume, templateCharge, orderItems);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        TradePriceCalculatorHelper.recountAllPrice(result);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    /**
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * 按 spu 来计算快递费用
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * @param total          总件数/总重量/总体积
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * @param templateCharge 快递运费配置
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * @param orderItems     SKU 商品项目
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private void calculateExpressFeeBySpu(double total, DeliveryExpressTemplateChargeDO templateCharge, List<OrderItem> orderItems) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        int deliveryPrice;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (total <= templateCharge.getStartCount()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            deliveryPrice = templateCharge.getStartPrice();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            double remainWeight = total - templateCharge.getStartCount();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // 剩余重量/ 续件 = 续件的次数. 向上取整
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            int extraNum = (int) Math.ceil(remainWeight / templateCharge.getExtraCount());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            int extraPrice = templateCharge.getExtraPrice() * extraNum;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            deliveryPrice = templateCharge.getStartPrice() + extraPrice;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        //
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // TODO @芋艿 分摊快递费用到 SKU. 是不是搞复杂了
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        divideDeliveryPrice(deliveryPrice, orderItems);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    /**
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * 快递运费分摊到每个 SKU 商品上
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * @param deliveryPrice 快递运费
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * @param orderItems    SKU 商品
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private void divideDeliveryPrice(int deliveryPrice, List<OrderItem> orderItems) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        int dividePrice = deliveryPrice / orderItems.size();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        for (OrderItem item : orderItems) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // 更新快递运费
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            item.setDeliveryPrice(dividePrice);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    /**
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * 检查是否包邮
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     *
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * @param chargeMode   配送计费方式
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * @param totalCount   总件数
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * @param totalWeight  总重量
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * @param totalVolume  总体积
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * @param totalPrice   总金额
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     * @param templateFree 包邮配置
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				     */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private boolean checkExpressFree(Integer chargeMode, int totalCount, double totalWeight,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                     double totalVolume, int totalPrice, DeliveryExpressTemplateFreeDO templateFree) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        DeliveryExpressChargeModeEnum chargeModeEnum = DeliveryExpressChargeModeEnum.valueOf(chargeMode);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        switch (chargeModeEnum) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            case PIECE:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                // 两个条件都满足才包邮
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if (totalCount >= templateFree.getFreeCount() && totalPrice >= templateFree.getFreePrice()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    return true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            case WEIGHT:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                //  freeCount 是不是应该是 double ??
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if (totalWeight >= templateFree.getFreeCount()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        && totalPrice >= templateFree.getFreePrice()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    return true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            case VOLUME:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if (totalVolume >= templateFree.getFreeCount()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        && totalPrice >= templateFree.getFreePrice()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    return true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 |