Commit 36c45bd44e1b0ac18fa432dc21a8e85b395785e4

Authored by jason
1 parent dd932151

review 价格运算修改.

yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java
... ... @@ -103,6 +103,15 @@ public class ProductSpuRespDTO {
103 103 */
104 104 private Integer stock;
105 105  
  106 + // ========== 物流相关字段 =========
  107 +
  108 + /**
  109 + * 物流配置模板编号
  110 + *
  111 + * 对应 TradeDeliveryExpressTemplateDO 的 id 编号
  112 + */
  113 + private Long deliveryTemplateId;
  114 +
106 115 // ========== 统计相关字段 =========
107 116  
108 117 /**
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateService.java
... ... @@ -6,10 +6,12 @@ import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplat
6 6 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplatePageReqVO;
7 7 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateUpdateReqVO;
8 8 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO;
  9 +import cn.iocoder.yudao.module.trade.service.delivery.bo.SpuDeliveryExpressTemplateRespBO;
9 10  
10 11 import javax.validation.Valid;
11 12 import java.util.Collection;
12 13 import java.util.List;
  14 +import java.util.Map;
13 15  
14 16 /**
15 17 * 快递运费模板 Service 接口
... ... @@ -73,11 +75,21 @@ public interface DeliveryExpressTemplateService {
73 75  
74 76 /**
75 77 * 校验快递运费模板
76   - *
  78 + * <p>
77 79 * 如果校验不通过,抛出 {@link cn.iocoder.yudao.framework.common.exception.ServiceException} 异常
78 80 *
79 81 * @param templateId 模板编号
80 82 * @return 快递运费模板
81 83 */
82 84 DeliveryExpressTemplateDO validateDeliveryExpressTemplate(Long templateId);
  85 +
  86 + /**
  87 + * 基于指定的 SPU 编号数组和收件人地址区域编号. 获取匹配运费模板
  88 + *
  89 + * @param ids SPU 编号列表
  90 + * @param areaId 区域编号
  91 + * @return Map (spuId -> 运费模板设置)
  92 + */
  93 + Map<Long, SpuDeliveryExpressTemplateRespBO> getExpressTemplateBySpuIdsAndArea(Collection<Long> ids, Integer areaId);
  94 +
83 95 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateServiceImpl.java
1 1 package cn.iocoder.yudao.module.trade.service.delivery;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.lang.Assert;
4 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
  7 +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
5 8 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.*;
6 9 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO;
7 10 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO;
... ... @@ -9,6 +12,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemp
9 12 import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateChargeMapper;
10 13 import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateFreeMapper;
11 14 import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateMapper;
  15 +import cn.iocoder.yudao.module.trade.service.delivery.bo.SpuDeliveryExpressTemplateRespBO;
12 16 import org.springframework.stereotype.Service;
13 17 import org.springframework.transaction.annotation.Transactional;
14 18 import org.springframework.validation.annotation.Validated;
... ... @@ -17,6 +21,7 @@ import javax.annotation.Resource;
17 21 import java.util.*;
18 22  
19 23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  24 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
20 25 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
21 26 import static cn.iocoder.yudao.module.trade.convert.delivery.DeliveryExpressTemplateConvert.INSTANCE;
22 27 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_TEMPLATE_NAME_DUPLICATE;
... ... @@ -37,6 +42,8 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla
37 42 private DeliveryExpressTemplateChargeMapper expressTemplateChargeMapper;
38 43 @Resource
39 44 private DeliveryExpressTemplateFreeMapper expressTemplateFreeMapper;
  45 + @Resource
  46 + private ProductSpuApi productSpuApi;
40 47  
41 48 @Override
42 49 @Transactional(rollbackFor = Exception.class)
... ... @@ -216,4 +223,50 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla
216 223 return template;
217 224 }
218 225  
  226 + @Override
  227 + public Map<Long, SpuDeliveryExpressTemplateRespBO> getExpressTemplateBySpuIdsAndArea(Collection<Long> spuIds, Integer areaId) {
  228 + Assert.notNull(areaId, "区域编号 {} 不能为空", areaId);
  229 + List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(spuIds);
  230 + if (CollUtil.isEmpty(spuList)) {
  231 + return Collections.emptyMap();
  232 + }
  233 + Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getDeliveryTemplateId);
  234 + List<DeliveryExpressTemplateDO> templateList = expressTemplateMapper.selectBatchIds(spuMap.keySet());
  235 + Map<Long, SpuDeliveryExpressTemplateRespBO> result = new HashMap<>(templateList.size());
  236 + templateList.forEach(item -> {
  237 + if (spuMap.containsKey(item.getId())) {
  238 + ProductSpuRespDTO spuDTO = spuMap.get(item.getId());
  239 + SpuDeliveryExpressTemplateRespBO bo = new SpuDeliveryExpressTemplateRespBO()
  240 + .setSpuId(spuDTO.getId()).setAreaId(areaId)
  241 + .setChargeMode(item.getChargeMode())
  242 + .setTemplateCharge(findMatchExpressTemplateCharge(item.getId(), areaId))
  243 + .setTemplateFree(findMatchExpressTemplateFree(item.getId(), areaId));
  244 + result.put(spuDTO.getId(), bo);
  245 + }
  246 + });
  247 + return result;
  248 + }
  249 +
  250 + private DeliveryExpressTemplateChargeDO findMatchExpressTemplateCharge(Long templateId, Integer areaId) {
  251 + List<DeliveryExpressTemplateChargeDO> list = expressTemplateChargeMapper.selectListByTemplateId(templateId);
  252 + for (DeliveryExpressTemplateChargeDO item : list) {
  253 + // 第一个匹配的返回。 areaId 不能重复
  254 + if (item.getAreaIds().contains(areaId)) {
  255 + return item;
  256 + }
  257 + }
  258 + return null;
  259 + }
  260 +
  261 + private DeliveryExpressTemplateFreeDO findMatchExpressTemplateFree(Long templateId, Integer areaId) {
  262 + List<DeliveryExpressTemplateFreeDO> list = expressTemplateFreeMapper.selectListByTemplateId(templateId);
  263 + for (DeliveryExpressTemplateFreeDO item : list) {
  264 + // 第一个匹配的返回。 areaId 不能重复
  265 + if (item.getAreaIds().contains(areaId)) {
  266 + return item;
  267 + }
  268 + }
  269 + return null;
  270 + }
  271 +
219 272 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/bo/SpuDeliveryExpressTemplateRespBO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.service.delivery.bo;
  2 +
  3 +import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO;
  4 +import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateFreeDO;
  5 +import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
  6 +import lombok.Data;
  7 +
  8 +/**
  9 + * SPU 运费模板配置 Resp BO
  10 + *
  11 + * @author jason
  12 + */
  13 +@Data
  14 +public class SpuDeliveryExpressTemplateRespBO {
  15 +
  16 + /**
  17 + * 配送计费方式
  18 + * <p>
  19 + * 枚举 {@link DeliveryExpressChargeModeEnum}
  20 + */
  21 + private Integer chargeMode;
  22 +
  23 + /**
  24 + * 运费模板快递运费设置
  25 + */
  26 + private DeliveryExpressTemplateChargeDO templateCharge;
  27 +
  28 + /**
  29 + * 运费模板包邮设置
  30 + */
  31 + private DeliveryExpressTemplateFreeDO templateFree;
  32 +
  33 + /**
  34 + * SPU 编号
  35 + * <p>
  36 + * 关联 ProductSpuDO 的 id 编号
  37 + */
  38 + private Long spuId;
  39 +
  40 + /**
  41 + * 区域编号
  42 + */
  43 + private Integer areaId;
  44 +
  45 +}
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java
1 1 package cn.iocoder.yudao.module.trade.service.price.bo;
2 2  
3   -import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO;
4 3 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
5 4 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
6 5 import lombok.Data;
... ... @@ -54,14 +53,6 @@ public class TradePriceCalculateReqBO {
54 53 private Integer deliveryType;
55 54  
56 55 /**
57   - * 配送模板编号
58   - *
59   - * 关联 {@link DeliveryExpressTemplateDO#getId()}
60   - */
61   - // TODO @jason:运费模版,是不是每个 SKU 传入哈
62   - private Long templateId;
63   -
64   - /**
65 56 * 商品 SKU 数组
66 57 */
67 58 @NotNull(message = "商品数组不能为空")
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDeliveryPriceCalculator.java
1 1 package cn.iocoder.yudao.module.trade.service.price.calculator;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.lang.Assert;
3 5 import cn.iocoder.yudao.module.member.api.address.AddressApi;
4 6 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
5 7 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
6 8 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
7 9 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO;
8   -import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO;
9 10 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateFreeDO;
10   -import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateChargeMapper;
11   -import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateFreeMapper;
12 11 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
13 12 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
14 13 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService;
  14 +import cn.iocoder.yudao.module.trade.service.delivery.bo.SpuDeliveryExpressTemplateRespBO;
15 15 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
16 16 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
17 17 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO.OrderItem;
... ... @@ -19,7 +19,6 @@ import org.springframework.core.annotation.Order;
19 19 import org.springframework.stereotype.Component;
20 20  
21 21 import javax.annotation.Resource;
22   -import java.util.HashMap;
23 22 import java.util.List;
24 23 import java.util.Map;
25 24 import java.util.Set;
... ... @@ -39,14 +38,8 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
39 38 private AddressApi addressApi;
40 39 @Resource
41 40 private ProductSkuApi productSkuApi;
42   -
43 41 @Resource
44 42 private DeliveryExpressTemplateService deliveryExpressTemplateService;
45   - // TODO @jason:走 Service 哈。Mapper 只允许自己的 Service 调用,保护好数据结构;
46   - @Resource
47   - private DeliveryExpressTemplateChargeMapper templateChargeMapper;
48   - @Resource
49   - private DeliveryExpressTemplateFreeMapper templateFreeMapper;
50 43  
51 44 @Override
52 45 public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
... ... @@ -54,66 +47,45 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
54 47 if (param.getDeliveryType() == null || DeliveryTypeEnum.PICK_UP.getMode().equals(param.getDeliveryType())) {
55 48 return;
56 49 }
57   -
58   - if (param.getTemplateId() == null || param.getAddressId() == null) {
  50 + // 1.2 得到收件地址区域
  51 + if (param.getAddressId() == null) {
59 52 return;
60 53 }
61   - // 1.2 校验运费模板是否存在
62   - DeliveryExpressTemplateDO template = deliveryExpressTemplateService.validateDeliveryExpressTemplate(param.getTemplateId());
63   -
64   - // 得到包邮配置
65   - List<DeliveryExpressTemplateFreeDO> expressTemplateFreeList = templateFreeMapper.selectListByTemplateId(template.getId());
66   - Map<Integer, DeliveryExpressTemplateFreeDO> areaTemplateFreeMap = new HashMap<>();
67   - expressTemplateFreeList.forEach(item -> {
68   - for (Integer areaId : item.getAreaIds()) {
69   - // TODO 需要保证 areaId 不能重复
70   - if (!areaTemplateFreeMap.containsKey(areaId)) {
71   - areaTemplateFreeMap.put(areaId, item);
72   - }
73   - }
74   - });
75   - // 得到快递运费配置
76   - List<DeliveryExpressTemplateChargeDO> expressTemplateChargeList = templateChargeMapper.selectListByTemplateId(template.getId());
77   - Map<Integer, DeliveryExpressTemplateChargeDO> areaTemplateChargeMap = new HashMap<>();
78   - expressTemplateChargeList.forEach(item -> {
79   - for (Integer areaId : item.getAreaIds()) {
80   - // areaId 不能重复
81   - if (!areaTemplateChargeMap.containsKey(areaId)) {
82   - areaTemplateChargeMap.put(areaId, item);
83   - }
84   - }
85   - });
86   - // 得到收件地址区域
87 54 AddressRespDTO address = addressApi.getAddress(param.getAddressId(), param.getUserId());
88   - // 1.3 计算快递费用
89   - calculateDeliveryPrice(address.getAreaId(), template.getChargeMode(),
90   - areaTemplateFreeMap, areaTemplateChargeMap, result);
  55 + Assert.notNull(address, "收件人({})的地址,不能为空", param.getUserId());
  56 +
  57 + //1.3 过滤出已选中的商品SKU
  58 + List<OrderItem> selectedItem = filterList(result.getItems(), OrderItem::getSelected);
  59 +
  60 + Map<Long, SpuDeliveryExpressTemplateRespBO> spuExpressTemplateMap =
  61 + deliveryExpressTemplateService.getExpressTemplateBySpuIdsAndArea(
  62 + convertSet(selectedItem, OrderItem::getSpuId), address.getAreaId());
  63 +
  64 + // 1.4 计算配送费用
  65 + if (CollUtil.isNotEmpty(spuExpressTemplateMap)) {
  66 + calculateDeliveryPrice(selectedItem, spuExpressTemplateMap, result);
  67 + }
  68 +
91 69 }
92 70  
93   - /**
94   - * 校验订单是否满足包邮条件
95   - *
96   - * @param receiverAreaId 收件人地区的区域编号
97   - * @param chargeMode 配送计费方式
98   - * @param areaTemplateFreeMap 运费模板包邮区域设置 Map
99   - * @param areaTemplateChargeMap 运费模板快递费用设置 Map
100   - */
101   - private void calculateDeliveryPrice(Integer receiverAreaId,
102   - Integer chargeMode,
103   - Map<Integer, DeliveryExpressTemplateFreeDO> areaTemplateFreeMap,
104   - Map<Integer, DeliveryExpressTemplateChargeDO> areaTemplateChargeMap,
  71 + private void calculateDeliveryPrice(List<OrderItem> selectedSkus,
  72 + Map<Long, SpuDeliveryExpressTemplateRespBO> spuExpressTemplateMap,
105 73 TradePriceCalculateRespBO result) {
106   - // 过滤出已选中的商品SKU
107   - List<OrderItem> selectedItem = filterList(result.getItems(), OrderItem::getSelected);
108   - Set<Long> skuIds = convertSet(selectedItem, OrderItem::getSkuId);
  74 + Set<Long> skuIds = convertSet(selectedSkus, OrderItem::getSkuId);
109 75 // 得到SKU 详情。得到 重量体积
110 76 Map<Long, ProductSkuRespDTO> skuRespMap = convertMap(productSkuApi.getSkuList(skuIds), ProductSkuRespDTO::getId);
111   - // 一个 spuId 可能对应多条订单商品 SKU
112   - // TODO @jason:得确认下,按照 sku 算,还是 spu 算;
113   - Map<Long, List<OrderItem>> spuIdItemMap = convertMultiMap(selectedItem, OrderItem::getSpuId);
  77 + // 按spu 来计算商品的运费 一个 spuId 可能对应多条订单商品 SKU,
  78 + Map<Long, List<OrderItem>> spuIdItemMap = convertMultiMap(selectedSkus, OrderItem::getSpuId);
  79 +
114 80 // 依次计算每个 SPU 的快递运费
115 81 for (Map.Entry<Long, List<OrderItem>> entry : spuIdItemMap.entrySet()) {
  82 + Long spuId = entry.getKey();
116 83 List<OrderItem> orderItems = entry.getValue();
  84 + SpuDeliveryExpressTemplateRespBO templateBO = spuExpressTemplateMap.get(spuId);
  85 + if (templateBO == null) {
  86 + // 记录错误日志
  87 + continue;
  88 + }
117 89 // 总件数, 总金额, 总重量, 总体积
118 90 int totalCount = 0;
119 91 int totalPrice = 0;
... ... @@ -121,51 +93,67 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
121 93 double totalVolume = 0;
122 94 for (OrderItem orderItem : orderItems) {
123 95 totalCount += orderItem.getCount();
124   - totalPrice += orderItem.getPrice(); // TODO jason:应该按照 payPrice?
  96 + totalPrice += orderItem.getPayPrice(); // 先按应付总金额来算,后面确认一下
125 97 ProductSkuRespDTO skuResp = skuRespMap.get(orderItem.getSkuId());
126 98 if (skuResp != null) {
127   - totalWeight = totalWeight + skuResp.getWeight(); // TODO @jason:* 数量
128   - totalVolume = totalVolume + skuResp.getVolume();
  99 + totalWeight = totalWeight + skuResp.getWeight() * orderItem.getCount();
  100 + totalVolume = totalVolume + skuResp.getVolume() * orderItem.getCount();
129 101 }
130 102 }
131 103 // 优先判断是否包邮. 如果包邮不计算快递运费
132   - if (areaTemplateFreeMap.containsKey(receiverAreaId) &&
133   - checkExpressFree(chargeMode, totalCount, totalWeight,
134   - totalVolume, totalPrice, areaTemplateFreeMap.get(receiverAreaId))) {
  104 + if (checkExpressFree(templateBO.getChargeMode(), totalCount, totalWeight,
  105 + totalVolume, totalPrice, templateBO.getTemplateFree())) {
135 106 continue;
136 107 }
137   - // 计算快递运费
138   - // TODO @jason:貌似也可以抽成 checkExpressFree 类似方法
139   - if (areaTemplateChargeMap.containsKey(receiverAreaId)) {
140   - DeliveryExpressTemplateChargeDO templateCharge = areaTemplateChargeMap.get(receiverAreaId);
141   - DeliveryExpressChargeModeEnum chargeModeEnum = DeliveryExpressChargeModeEnum.valueOf(chargeMode);
142   - switch (chargeModeEnum) {
143   - case PIECE: {
144   - calculateExpressFeeBySpu(totalCount, templateCharge, orderItems);
145   - break;
146   - }
147   - case WEIGHT: {
148   - calculateExpressFeeBySpu(totalWeight, templateCharge, orderItems);
149   - break;
150   - }
151   - case VOLUME: {
152   - calculateExpressFeeBySpu(totalVolume, templateCharge, orderItems);
153   - break;
154   - }
155   - }
  108 + if (templateBO.getTemplateCharge() == null) {
  109 + continue;
156 110 }
  111 + // 计算快递运费
  112 + calculateExpressFeeByChargeMode(totalCount, totalWeight, totalVolume,
  113 + templateBO.getChargeMode(), templateBO.getTemplateCharge(), orderItems);
  114 +
157 115 }
158 116 TradePriceCalculatorHelper.recountAllPrice(result);
159 117 }
160 118  
161 119 /**
162   - * 按 spu 来计算快递费用
  120 + * 按配送方式来计算运费
  121 + *
  122 + * @param totalCount 总件数
  123 + * @param totalWeight 总重量
  124 + * @param totalVolume 总体积
  125 + * @param chargeMode 配送计费方式
  126 + * @param templateCharge 快递运费配置
  127 + * @param orderItems SKU 商品项目
  128 + */
  129 + private void calculateExpressFeeByChargeMode(double totalCount, double totalWeight, double totalVolume,
  130 + int chargeMode, DeliveryExpressTemplateChargeDO templateCharge,
  131 + List<OrderItem> orderItems) {
  132 + DeliveryExpressChargeModeEnum chargeModeEnum = DeliveryExpressChargeModeEnum.valueOf(chargeMode);
  133 + switch (chargeModeEnum) {
  134 + case PIECE: {
  135 + calculateExpressFee(totalCount, templateCharge, orderItems);
  136 + break;
  137 + }
  138 + case WEIGHT: {
  139 + calculateExpressFee(totalWeight, templateCharge, orderItems);
  140 + break;
  141 + }
  142 + case VOLUME: {
  143 + calculateExpressFee(totalVolume, templateCharge, orderItems);
  144 + break;
  145 + }
  146 + }
  147 + }
  148 +
  149 + /**
  150 + * 计算 SKU 商品快递费用
163 151 *
164 152 * @param total 总件数/总重量/总体积
165 153 * @param templateCharge 快递运费配置
166 154 * @param orderItems SKU 商品项目
167 155 */
168   - private void calculateExpressFeeBySpu(double total, DeliveryExpressTemplateChargeDO templateCharge, List<OrderItem> orderItems) {
  156 + private void calculateExpressFee(double total, DeliveryExpressTemplateChargeDO templateCharge, List<OrderItem> orderItems) {
169 157 int deliveryPrice;
170 158 if (total <= templateCharge.getStartCount()) {
171 159 deliveryPrice = templateCharge.getStartPrice();
... ... @@ -176,8 +164,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
176 164 int extraPrice = templateCharge.getExtraPrice() * extraNum;
177 165 deliveryPrice = templateCharge.getStartPrice() + extraPrice;
178 166 }
179   - // TODO @芋艿 分摊快递费用到 SKU. 是不是搞复杂了;
180   - // TODO @jason:因为退费的时候,可能按照 SKU 考虑退费金额
  167 + // 分摊快递费用到 SKU. 退费的时候,可能按照 SKU 考虑退费金额
181 168 divideDeliveryPrice(deliveryPrice, orderItems);
182 169 }
183 170  
... ... @@ -207,6 +194,9 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
207 194 */
208 195 private boolean checkExpressFree(Integer chargeMode, int totalCount, double totalWeight,
209 196 double totalVolume, int totalPrice, DeliveryExpressTemplateFreeDO templateFree) {
  197 + if (templateFree == null) {
  198 + return false;
  199 + }
210 200 DeliveryExpressChargeModeEnum chargeModeEnum = DeliveryExpressChargeModeEnum.valueOf(chargeMode);
211 201 switch (chargeModeEnum) {
212 202 case PIECE:
... ...