Commit e69e6d880b08e02b0d9c9ca9b8c166cc1ef0954b

Authored by jason
1 parent af0eeb6e

快递价格计算 review 修改

Showing 13 changed files with 153 additions and 164 deletions
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
... ... @@ -51,13 +51,12 @@ public interface ErrorCodeConstants {
51 51 ErrorCode EXPRESS_CODE_DUPLICATE = new ErrorCode(1011003001, "已经存在该编码的快递公司");
52 52 ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1011003002, "运费模板不存在");
53 53 ErrorCode EXPRESS_TEMPLATE_NAME_DUPLICATE = new ErrorCode(1011003003, "已经存在该运费模板名");
54   - ErrorCode DELIVERY_EXPRESS_USER_ADDRESS_IS_EMPTY = new ErrorCode(1011003004, "计算快递运费时,收件人地址编号为空"); // TODO @jaosn:这个错误码,放到 Price 这块
55   - ErrorCode PRODUCT_EXPRESS_TEMPLATE_NOT_FOUND = new ErrorCode(1011003005, "找不到到商品对应的运费模板"); // TODO @jaosn:这个错误码,放到 Price 这块
56 54 ErrorCode EXPRESS_API_QUERY_ERROR = new ErrorCode(1011003006, "快递查询接口异常");
57 55 ErrorCode EXPRESS_API_QUERY_FAILED = new ErrorCode(1011003007, "快递查询返回失败, 原因:{}");
58 56 ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1011003008, "自提门店不存在");
59 57  
60 58 // ========== Price 相关 1011004000 ============
61 59 ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011004000, "支付价格计算异常,原因:价格小于等于 0");
62   -
  60 + ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_USER_ADDR_IS_EMPTY = new ErrorCode(1011004001, "计算快递运费异常,收件人地址编号为空");
  61 + ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1011004002, "计算快递运费异常,找不到对应的运费模板");
63 62 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java
... ... @@ -6,8 +6,7 @@ import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplat
6 6 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO;
7 7 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO;
8 8 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateFreeDO;
9   -import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateChargeBO;
10   -import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateFreeBO;
  9 +import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateRespBO;
11 10 import org.mapstruct.Mapper;
12 11 import org.mapstruct.factory.Mappers;
13 12  
... ... @@ -49,7 +48,7 @@ public interface DeliveryExpressTemplateConvert {
49 48  
50 49 DeliveryExpressTemplateChargeDO convertTemplateCharge(DeliveryExpressTemplateUpdateReqVO.ExpressTemplateChargeUpdateVO vo);
51 50  
52   - DeliveryExpressTemplateChargeBO convertTemplateCharge(DeliveryExpressTemplateChargeDO bean);
  51 + DeliveryExpressTemplateRespBO.DeliveryExpressTemplateChargeBO convertTemplateCharge(DeliveryExpressTemplateChargeDO bean);
53 52  
54 53 default List<DeliveryExpressTemplateChargeDO> convertTemplateChargeList(Long templateId, Integer chargeMode, List<ExpressTemplateChargeBaseVO> list) {
55 54 return CollectionUtils.convertList(list, vo -> convertTemplateCharge(templateId, chargeMode, vo));
... ... @@ -61,7 +60,7 @@ public interface DeliveryExpressTemplateConvert {
61 60  
62 61 DeliveryExpressTemplateFreeDO convertTemplateFree(DeliveryExpressTemplateUpdateReqVO.ExpressTemplateFreeUpdateVO vo);
63 62  
64   - DeliveryExpressTemplateFreeBO convertTemplateFree(DeliveryExpressTemplateFreeDO bean);
  63 + DeliveryExpressTemplateRespBO.DeliveryExpressTemplateFreeBO convertTemplateFree(DeliveryExpressTemplateFreeDO bean);
65 64  
66 65 List<ExpressTemplateChargeBaseVO> convertTemplateChargeList(List<DeliveryExpressTemplateChargeDO> list);
67 66  
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateChargeMapper.java
... ... @@ -5,10 +5,9 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 6 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO;
7 7 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
8   -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
9 8 import org.apache.ibatis.annotations.Mapper;
10   -import org.springframework.stereotype.Repository;
11 9  
  10 +import java.util.Collection;
12 11 import java.util.List;
13 12  
14 13 @Mapper
... ... @@ -23,6 +22,11 @@ public interface DeliveryExpressTemplateChargeMapper extends BaseMapperX&lt;Deliver
23 22 return delete(new LambdaQueryWrapper<DeliveryExpressTemplateChargeDO>()
24 23 .eq(DeliveryExpressTemplateChargeDO::getTemplateId, templateId));
25 24 }
  25 +
  26 + default List<DeliveryExpressTemplateChargeDO> selectByTemplateIds(Collection<Long> templateIds) {
  27 + return selectList(new LambdaQueryWrapperX<DeliveryExpressTemplateChargeDO>()
  28 + .inIfPresent(DeliveryExpressTemplateChargeDO::getTemplateId, templateIds));
  29 + }
26 30 }
27 31  
28 32  
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateFreeMapper.java
... ... @@ -2,13 +2,11 @@ package cn.iocoder.yudao.module.trade.dal.mysql.delivery;
2 2  
3 3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
4 4 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
5   -import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO;
6 5 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateFreeDO;
7 6 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
8   -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
9 7 import org.apache.ibatis.annotations.Mapper;
10   -import org.springframework.stereotype.Repository;
11 8  
  9 +import java.util.Collection;
12 10 import java.util.List;
13 11  
14 12 @Mapper
... ... @@ -23,6 +21,11 @@ public interface DeliveryExpressTemplateFreeMapper extends BaseMapperX&lt;DeliveryE
23 21 return delete(new LambdaQueryWrapper<DeliveryExpressTemplateFreeDO>()
24 22 .eq(DeliveryExpressTemplateFreeDO::getTemplateId, templateId));
25 23 }
  24 +
  25 + default List<DeliveryExpressTemplateFreeDO> selectListByTemplateIds(Collection<Long> ids) {
  26 + return selectList(new LambdaQueryWrapperX<DeliveryExpressTemplateFreeDO>()
  27 + .inIfPresent(DeliveryExpressTemplateFreeDO::getTemplateId, ids));
  28 + }
26 29 }
27 30  
28 31  
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateService.java
... ... @@ -6,7 +6,7 @@ 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 +import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateRespBO;
10 10  
11 11 import javax.validation.Valid;
12 12 import java.util.Collection;
... ... @@ -83,14 +83,12 @@ public interface DeliveryExpressTemplateService {
83 83 */
84 84 DeliveryExpressTemplateDO validateDeliveryExpressTemplate(Long templateId);
85 85  
86   - // TODO @jason:可以把 spuIds 改成传递 ids 么?价格计算那,在 TradePriceCalculateRespBO 冗余好 templateId 字段。目的是,减少重复的查询
87 86 /**
88   - * 基于指定的 SPU 编号数组和收件人地址区域编号. 获取匹配运费模板
  87 + * 基于运费模板编号数组和收件人地址区域编号. 获取匹配运费模板
89 88 *
90   - * @param spuIds SPU 编号列表
  89 + * @param ids 编号列表
91 90 * @param areaId 区域编号
92   - * @return Map (spuId -> 运费模板设置)
  91 + * @return Map (templateId -> 运费模板设置)
93 92 */
94   - Map<Long, SpuDeliveryExpressTemplateRespBO> getExpressTemplateMapBySpuIdsAndArea(Collection<Long> spuIds, Integer areaId);
95   -
  93 + Map<Long, DeliveryExpressTemplateRespBO> getExpressTemplateMapByIdsAndArea(Collection<Long> ids, Integer areaId);
96 94 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateServiceImpl.java
... ... @@ -3,8 +3,6 @@ package cn.iocoder.yudao.module.trade.service.delivery;
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.lang.Assert;
5 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;
8 6 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateCreateReqVO;
9 7 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateDetailRespVO;
10 8 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplatePageReqVO;
... ... @@ -15,9 +13,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemp
15 13 import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateChargeMapper;
16 14 import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateFreeMapper;
17 15 import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateMapper;
18   -import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateChargeBO;
19   -import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateFreeBO;
20   -import cn.iocoder.yudao.module.trade.service.delivery.bo.SpuDeliveryExpressTemplateRespBO;
  16 +import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateRespBO;
21 17 import org.springframework.stereotype.Service;
22 18 import org.springframework.transaction.annotation.Transactional;
23 19 import org.springframework.validation.annotation.Validated;
... ... @@ -46,8 +42,6 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla
46 42 private DeliveryExpressTemplateChargeMapper expressTemplateChargeMapper;
47 43 @Resource
48 44 private DeliveryExpressTemplateFreeMapper expressTemplateFreeMapper;
49   - @Resource
50   - private ProductSpuApi productSpuApi;
51 45  
52 46 @Override
53 47 @Transactional(rollbackFor = Exception.class)
... ... @@ -228,41 +222,40 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla
228 222 }
229 223  
230 224 @Override
231   - public Map<Long, SpuDeliveryExpressTemplateRespBO> getExpressTemplateMapBySpuIdsAndArea(Collection<Long> spuIds, Integer areaId) {
  225 + public Map<Long, DeliveryExpressTemplateRespBO> getExpressTemplateMapByIdsAndArea(Collection<Long> ids, Integer areaId) {
232 226 Assert.notNull(areaId, "区域编号 {} 不能为空", areaId);
233   - List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(spuIds);
234   - if (CollUtil.isEmpty(spuList)) {
  227 + if (CollUtil.isEmpty(ids)) {
235 228 return Collections.emptyMap();
236 229 }
237   - Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getDeliveryTemplateId);
238   - List<DeliveryExpressTemplateDO> templateList = expressTemplateMapper.selectBatchIds(spuMap.keySet());
239   - Map<Long, SpuDeliveryExpressTemplateRespBO> result = new HashMap<>(templateList.size());
  230 + List<DeliveryExpressTemplateDO> templateList = expressTemplateMapper.selectBatchIds(ids);
  231 + // 查询 templateCharge
  232 + List<DeliveryExpressTemplateChargeDO> templeChargeList = expressTemplateChargeMapper.selectByTemplateIds(ids);
  233 + Map<Long, List<DeliveryExpressTemplateChargeDO>> templateChargeMap = convertMultiMap(templeChargeList,
  234 + DeliveryExpressTemplateChargeDO::getTemplateId);
  235 + // 查询 templateFree
  236 + List<DeliveryExpressTemplateFreeDO> templateFreeList = expressTemplateFreeMapper.selectListByTemplateIds(ids);
  237 + Map<Long, List<DeliveryExpressTemplateFreeDO>> templateFreeMap = convertMultiMap(templateFreeList,
  238 + DeliveryExpressTemplateFreeDO::getTemplateId);
  239 + // 组合运费模板配置 RespBO
  240 + Map<Long, DeliveryExpressTemplateRespBO> result = new HashMap<>(templateList.size());
240 241 templateList.forEach(item -> {
241   - ProductSpuRespDTO spu = spuMap.get(item.getId());
242   - if (spu == null) {
243   - return;
244   - }
245   - // TODO @jason:避免循环查询;最好类似 expressTemplateMapper.selectBatchIds(spuMap.keySet()); 批量查询,内存组合;
246   - SpuDeliveryExpressTemplateRespBO bo = new SpuDeliveryExpressTemplateRespBO()
  242 + DeliveryExpressTemplateRespBO bo = new DeliveryExpressTemplateRespBO()
247 243 .setChargeMode(item.getChargeMode())
248   - .setTemplateCharge(findMatchExpressTemplateCharge(item.getId(), areaId))
249   - .setTemplateFree(findMatchExpressTemplateFree(item.getId(), areaId));
250   - result.put(spu.getId(), bo);
  244 + .setTemplateCharge(findMatchExpressTemplateCharge(templateChargeMap.get(item.getId()), areaId))
  245 + .setTemplateFree(findMatchExpressTemplateFree(templateFreeMap.get(item.getId()), areaId));
  246 + result.put(item.getId(), bo);
251 247 });
252 248 return result;
253 249 }
254 250  
255   - private DeliveryExpressTemplateChargeBO findMatchExpressTemplateCharge(Long templateId, Integer areaId) {
256   - return INSTANCE.convertTemplateCharge(findFirst(
257   - expressTemplateChargeMapper.selectListByTemplateId(templateId), item -> item.getAreaIds().contains(areaId)
258   - )
259   - );
  251 + private DeliveryExpressTemplateRespBO.DeliveryExpressTemplateChargeBO findMatchExpressTemplateCharge(
  252 + List<DeliveryExpressTemplateChargeDO> templateChargeList, Integer areaId) {
  253 + return INSTANCE.convertTemplateCharge(findFirst(templateChargeList, item -> item.getAreaIds().contains(areaId)));
260 254 }
261 255  
262   - private DeliveryExpressTemplateFreeBO findMatchExpressTemplateFree(Long templateId, Integer areaId) {
263   - return INSTANCE.convertTemplateFree(findFirst(
264   - expressTemplateFreeMapper.selectListByTemplateId(templateId), item -> item.getAreaIds().contains(areaId)
265   - ));
  256 + private DeliveryExpressTemplateRespBO.DeliveryExpressTemplateFreeBO findMatchExpressTemplateFree(
  257 + List<DeliveryExpressTemplateFreeDO> templateFreeList, Integer areaId) {
  258 + return INSTANCE.convertTemplateFree(findFirst(templateFreeList, item -> item.getAreaIds().contains(areaId)));
266 259 }
267 260  
268 261 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/bo/DeliveryExpressTemplateFreeBO.java deleted
1   -package cn.iocoder.yudao.module.trade.service.delivery.bo;
2   -
3   -import lombok.Data;
4   -
5   -/**
6   - * 快递运费模板包邮配置 BO
7   - *
8   - * @author jason
9   - */
10   -@Data
11   -public class DeliveryExpressTemplateFreeBO {
12   -
13   - /**
14   - * 包邮金额,单位:分
15   - *
16   - * 订单总金额 > 包邮金额时,才免运费
17   - */
18   - private Integer freePrice;
19   -
20   - /**
21   - * 包邮件数
22   - *
23   - * 订单总件数 > 包邮件数时,才免运费
24   - */
25   - private Integer freeCount;
26   -}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/bo/DeliveryExpressTemplateChargeBO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/bo/DeliveryExpressTemplateRespBO.java
1 1 package cn.iocoder.yudao.module.trade.service.delivery.bo;
2 2  
  3 +import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
3 4 import lombok.Data;
4 5  
5 6 /**
6   - * 快递运费模板费用配置 BO
  7 + * 运费模板配置 Resp BO
7 8 *
8 9 * @author jason
9 10 */
10 11 @Data
11   -public class DeliveryExpressTemplateChargeBO {
  12 +public class DeliveryExpressTemplateRespBO {
12 13  
13 14 /**
14   - * 首件数量(件数,重量,或体积)
  15 + * 配送计费方式
  16 + *
  17 + * 枚举 {@link DeliveryExpressChargeModeEnum}
15 18 */
16   - private Double startCount;
  19 + private Integer chargeMode;
  20 +
17 21 /**
18   - * 起步价,单位:分
  22 + * 运费模板快递运费设置
19 23 */
20   - private Integer startPrice;
  24 + private DeliveryExpressTemplateChargeBO templateCharge;
  25 +
21 26 /**
22   - * 续件数量(件, 重量,或体积)
  27 + * 运费模板包邮设置
23 28 */
24   - private Double extraCount;
  29 + private DeliveryExpressTemplateFreeBO templateFree;
  30 +
25 31 /**
26   - * 额外价,单位:分
  32 + * 快递运费模板费用配置 BO
  33 + *
  34 + * @author jason
27 35 */
28   - private Integer extraPrice;
  36 + @Data
  37 + public static class DeliveryExpressTemplateChargeBO {
  38 +
  39 + /**
  40 + * 首件数量(件数,重量,或体积)
  41 + */
  42 + private Double startCount;
  43 + /**
  44 + * 起步价,单位:分
  45 + */
  46 + private Integer startPrice;
  47 + /**
  48 + * 续件数量(件, 重量,或体积)
  49 + */
  50 + private Double extraCount;
  51 + /**
  52 + * 额外价,单位:分
  53 + */
  54 + private Integer extraPrice;
  55 + }
  56 +
  57 + /**
  58 + * 快递运费模板包邮配置 BO
  59 + *
  60 + * @author jason
  61 + */
  62 + @Data
  63 + public static class DeliveryExpressTemplateFreeBO {
  64 +
  65 + /**
  66 + * 包邮金额,单位:分
  67 + *
  68 + * 订单总金额 > 包邮金额时,才免运费
  69 + */
  70 + private Integer freePrice;
  71 +
  72 + /**
  73 + * 包邮件数
  74 + *
  75 + * 订单总件数 > 包邮件数时,才免运费
  76 + */
  77 + private Integer freeCount;
  78 + }
29 79 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/bo/SpuDeliveryExpressTemplateRespBO.java deleted
1   -package cn.iocoder.yudao.module.trade.service.delivery.bo;
2   -
3   -import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
4   -import lombok.Data;
5   -
6   -/**
7   - * SPU 运费模板配置 Resp BO
8   - *
9   - * @author jason
10   - */
11   -@Data
12   -public class SpuDeliveryExpressTemplateRespBO {
13   -
14   - /**
15   - * 配送计费方式
16   - *
17   - * 枚举 {@link DeliveryExpressChargeModeEnum}
18   - */
19   - private Integer chargeMode;
20   -
21   - // TODO @jaosn:可以把 DeliveryExpressTemplateChargeBO 和 DeliveryExpressTemplateFreeBO 搞成内嵌的类。这样简洁一点
22   -
23   - /**
24   - * 运费模板快递运费设置
25   - */
26   - private DeliveryExpressTemplateChargeBO templateCharge;
27   -
28   - /**
29   - * 运费模板包邮设置
30   - */
31   - private DeliveryExpressTemplateFreeBO templateFree;
32   -
33   -}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java
... ... @@ -180,6 +180,11 @@ public class TradePriceCalculateRespBO {
180 180 */
181 181 private Long categoryId;
182 182  
  183 + /**
  184 + * 运费模板 Id
  185 + */
  186 + private Long deliveryTemplateId;
  187 +
183 188 // ========== 商品 SKU 信息 ==========
184 189 /**
185 190 * 商品重量,单位:kg 千克
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDeliveryPriceCalculator.java
... ... @@ -7,9 +7,7 @@ import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
7 7 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
8 8 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
9 9 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService;
10   -import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateChargeBO;
11   -import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateFreeBO;
12   -import cn.iocoder.yudao.module.trade.service.delivery.bo.SpuDeliveryExpressTemplateRespBO;
  10 +import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateRespBO;
13 11 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
14 12 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
15 13 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO.OrderItem;
... ... @@ -24,8 +22,8 @@ import java.util.Set;
24 22  
25 23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
26 24 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
27   -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.DELIVERY_EXPRESS_USER_ADDRESS_IS_EMPTY;
28   -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRODUCT_EXPRESS_TEMPLATE_NOT_FOUND;
  25 +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_DELIVERY_PRICE_USER_ADDR_IS_EMPTY;
  26 +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND;
29 27  
30 28 /**
31 29 * 运费的 {@link TradePriceCalculator} 实现类
... ... @@ -49,7 +47,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
49 47 return;
50 48 }
51 49 if (param.getAddressId() == null) {
52   - throw exception(DELIVERY_EXPRESS_USER_ADDRESS_IS_EMPTY);
  50 + throw exception(PRICE_CALCULATE_DELIVERY_PRICE_USER_ADDR_IS_EMPTY);
53 51 }
54 52 // 1.2 得到收件地址区域
55 53 AddressRespDTO address = addressApi.getAddress(param.getAddressId(), param.getUserId());
... ... @@ -57,29 +55,29 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
57 55  
58 56 // 2. 过滤出已选中的商品SKU
59 57 List<OrderItem> selectedItem = filterList(result.getItems(), OrderItem::getSelected);
60   - Set<Long> spuIds = convertSet(selectedItem, OrderItem::getSpuId);
61   - Map<Long, SpuDeliveryExpressTemplateRespBO> spuExpressTemplateMap =
62   - deliveryExpressTemplateService.getExpressTemplateMapBySpuIdsAndArea(spuIds, address.getAreaId());
  58 + Set<Long> deliveryTemplateIds = convertSet(selectedItem, OrderItem::getDeliveryTemplateId);
  59 + Map<Long, DeliveryExpressTemplateRespBO> expressTemplateMap =
  60 + deliveryExpressTemplateService.getExpressTemplateMapByIdsAndArea(deliveryTemplateIds, address.getAreaId());
63 61 // 3. 计算配送费用
64   - if (CollUtil.isEmpty(spuExpressTemplateMap)) {
65   - log.error("[calculate][找不到商品 spuId{} areaId{} 对应的运费模板]", spuIds, address.getAreaId());
66   - throw exception(PRODUCT_EXPRESS_TEMPLATE_NOT_FOUND);
  62 + if (CollUtil.isEmpty(expressTemplateMap)) {
  63 + log.error("[calculate][找不到商品 templateIds {} areaId{} 对应的运费模板]", deliveryTemplateIds, address.getAreaId());
  64 + throw exception(PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND);
67 65 }
68   - calculateDeliveryPrice(selectedItem, spuExpressTemplateMap, result);
  66 + calculateDeliveryPrice(selectedItem, expressTemplateMap, result);
69 67 }
70 68  
71 69 private void calculateDeliveryPrice(List<OrderItem> selectedSkus,
72   - Map<Long, SpuDeliveryExpressTemplateRespBO> spuExpressTemplateMap,
  70 + Map<Long, DeliveryExpressTemplateRespBO> expressTemplateMap,
73 71 TradePriceCalculateRespBO result) {
74   - // 按 SPU 来计算商品的运费:一个 spuId 可能对应多条订单商品 SKU
75   - Map<Long, List<OrderItem>> spuIdItemMap = convertMultiMap(selectedSkus, OrderItem::getSpuId);
76   - // 依次计算每个 SPU 的快递运费
77   - for (Map.Entry<Long, List<OrderItem>> entry : spuIdItemMap.entrySet()) {
78   - Long spuId = entry.getKey();
  72 + // 按商品运费模板来计算商品的运费:相同的运费模板可能对应多条订单商品 SKU
  73 + Map<Long, List<OrderItem>> tplIdItemMap = convertMultiMap(selectedSkus, OrderItem::getDeliveryTemplateId);
  74 + // 依次计算快递运费
  75 + for (Map.Entry<Long, List<OrderItem>> entry : tplIdItemMap.entrySet()) {
  76 + Long templateId = entry.getKey();
79 77 List<OrderItem> orderItems = entry.getValue();
80   - SpuDeliveryExpressTemplateRespBO templateBO = spuExpressTemplateMap.get(spuId);
  78 + DeliveryExpressTemplateRespBO templateBO = expressTemplateMap.get(templateId);
81 79 if (templateBO == null) {
82   - log.error("不能计算快递运费。不能找到 spuId : {}. 对应的运费模板配置 Resp BO", spuId);
  80 + log.error("不能计算快递运费。不能找到 templateId : {}. 对应的运费模板配置 Resp BO", templateId);
83 81 continue;
84 82 }
85 83 // 总件数, 总金额, 总重量, 总体积
... ... @@ -117,7 +115,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
117 115 * @param orderItems SKU 商品项目
118 116 */
119 117 private void calculateExpressFeeByChargeMode(double totalCount, double totalWeight, double totalVolume,
120   - int chargeMode, DeliveryExpressTemplateChargeBO templateCharge,
  118 + int chargeMode, DeliveryExpressTemplateRespBO.DeliveryExpressTemplateChargeBO templateCharge,
121 119 List<OrderItem> orderItems) {
122 120 if (templateCharge == null) {
123 121 log.error("计算快递运费时,不能找到对应的快递运费模板费用配置。无法计算以下商品 SKU 项目运费: {}", orderItems);
... ... @@ -147,7 +145,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
147 145 * @param templateCharge 快递运费配置
148 146 * @param orderItems SKU 商品项目
149 147 */
150   - private void calculateExpressFee(double total, DeliveryExpressTemplateChargeBO templateCharge, List<OrderItem> orderItems) {
  148 + private void calculateExpressFee(double total, DeliveryExpressTemplateRespBO.DeliveryExpressTemplateChargeBO templateCharge, List<OrderItem> orderItems) {
151 149 int deliveryPrice;
152 150 if (total <= templateCharge.getStartCount()) {
153 151 deliveryPrice = templateCharge.getStartPrice();
... ... @@ -192,7 +190,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
192 190 * @param templateFree 包邮配置
193 191 */
194 192 private boolean isExpressFree(Integer chargeMode, int totalCount, double totalWeight,
195   - double totalVolume, int totalPrice, DeliveryExpressTemplateFreeBO templateFree) {
  193 + double totalVolume, int totalPrice, DeliveryExpressTemplateRespBO.DeliveryExpressTemplateFreeBO templateFree) {
196 194 if (templateFree == null) {
197 195 return false;
198 196 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java
... ... @@ -56,7 +56,8 @@ public class TradePriceCalculatorHelper {
56 56 orderItem.setPicUrl(sku.getPicUrl()).setProperties(sku.getProperties())
57 57 .setWeight(sku.getWeight()).setVolume(sku.getVolume());
58 58 // spu 信息
59   - orderItem.setSpuName(spu.getName()).setCategoryId(spu.getCategoryId());
  59 + orderItem.setSpuName(spu.getName()).setCategoryId(spu.getCategoryId())
  60 + .setDeliveryTemplateId(spu.getDeliveryTemplateId());
60 61 if (orderItem.getPicUrl() == null) {
61 62 orderItem.setPicUrl(spu.getPicUrl());
62 63 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDeliveryPriceCalculatorTest.java
... ... @@ -4,9 +4,7 @@ import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
4 4 import cn.iocoder.yudao.module.member.api.address.AddressApi;
5 5 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
6 6 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService;
7   -import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateChargeBO;
8   -import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateFreeBO;
9   -import cn.iocoder.yudao.module.trade.service.delivery.bo.SpuDeliveryExpressTemplateRespBO;
  7 +import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateRespBO;
10 8 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
11 9 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
12 10 import org.junit.jupiter.api.BeforeEach;
... ... @@ -44,9 +42,9 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest {
44 42 private TradePriceCalculateReqBO reqBO;
45 43 private TradePriceCalculateRespBO resultBO;
46 44 private AddressRespDTO addressResp;
47   - private DeliveryExpressTemplateChargeBO chargeBO;
48   - private DeliveryExpressTemplateFreeBO freeBO;
49   - private SpuDeliveryExpressTemplateRespBO spuTemplateRespBO;
  45 + private DeliveryExpressTemplateRespBO.DeliveryExpressTemplateChargeBO chargeBO;
  46 + private DeliveryExpressTemplateRespBO.DeliveryExpressTemplateFreeBO freeBO;
  47 + private DeliveryExpressTemplateRespBO templateRespBO;
50 48  
51 49 @BeforeEach
52 50 public void init(){
... ... @@ -64,11 +62,11 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest {
64 62 .setPrice(new TradePriceCalculateRespBO.Price())
65 63 .setPromotions(new ArrayList<>())
66 64 .setItems(asList(
67   - new TradePriceCalculateRespBO.OrderItem().setSpuId(1L).setSkuId(10L).setCount(2).setSelected(true)
  65 + new TradePriceCalculateRespBO.OrderItem().setDeliveryTemplateId(1L).setSkuId(10L).setCount(2).setSelected(true)
68 66 .setWeight(10d).setVolume(10d).setPrice(100),
69   - new TradePriceCalculateRespBO.OrderItem().setSpuId(1L).setSkuId(20L).setCount(10).setSelected(true)
  67 + new TradePriceCalculateRespBO.OrderItem().setDeliveryTemplateId(1L).setSkuId(20L).setCount(10).setSelected(true)
70 68 .setWeight(10d).setVolume(10d).setPrice(200),
71   - new TradePriceCalculateRespBO.OrderItem().setSpuId(1L).setSkuId(30L).setCount(1).setSelected(false)
  69 + new TradePriceCalculateRespBO.OrderItem().setDeliveryTemplateId(1L).setSkuId(30L).setCount(1).setSelected(false)
72 70 .setWeight(10d).setVolume(10d).setPrice(300)
73 71 ));
74 72 // 保证价格被初始化上
... ... @@ -77,13 +75,13 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest {
77 75 // 准备收件地址数据
78 76 addressResp = randomPojo(AddressRespDTO.class, item -> item.setAreaId(10));
79 77 // 准备运费模板费用配置数据
80   - chargeBO = randomPojo(DeliveryExpressTemplateChargeBO.class,
  78 + chargeBO = randomPojo(DeliveryExpressTemplateRespBO.DeliveryExpressTemplateChargeBO.class,
81 79 item -> item.setStartCount(10D).setStartPrice(1000).setExtraCount(10D).setExtraPrice(2000));
82 80 // 准备运费模板包邮配置数据 订单总件数 < 包邮件数时 12 < 20
83   - freeBO = randomPojo(DeliveryExpressTemplateFreeBO.class,
  81 + freeBO = randomPojo(DeliveryExpressTemplateRespBO.DeliveryExpressTemplateFreeBO.class,
84 82 item -> item.setFreeCount(20).setFreePrice(100));
85 83 // 准备 SP 运费模板 数据
86   - spuTemplateRespBO = randomPojo(SpuDeliveryExpressTemplateRespBO.class,
  84 + templateRespBO = randomPojo(DeliveryExpressTemplateRespBO.class,
87 85 item -> item.setChargeMode(PIECE.getType())
88 86 .setTemplateCharge(chargeBO).setTemplateFree(freeBO));
89 87 }
... ... @@ -94,12 +92,12 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest {
94 92 // SKU 1 : 100 * 2 = 200
95 93 // SKU 2 :200 * 10 = 2000
96 94 // 运费 首件 1000 + 续件 2000 = 3000
97   - Map<Long, SpuDeliveryExpressTemplateRespBO> respMap = new HashMap<>();
98   - respMap.put(1L, spuTemplateRespBO);
  95 + Map<Long, DeliveryExpressTemplateRespBO> respMap = new HashMap<>();
  96 + respMap.put(1L, templateRespBO);
99 97  
100 98 // mock 方法
101 99 when(addressApi.getAddress(eq(10L), eq(1L))).thenReturn(addressResp);
102   - when(deliveryExpressTemplateService.getExpressTemplateMapBySpuIdsAndArea(eq(asSet(1L)), eq(10)))
  100 + when(deliveryExpressTemplateService.getExpressTemplateMapByIdsAndArea(eq(asSet(1L)), eq(10)))
103 101 .thenReturn(respMap);
104 102  
105 103 calculator.calculate(reqBO, resultBO);
... ... @@ -131,15 +129,15 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest {
131 129 // SKU 1 : 100 * 2 = 200
132 130 // SKU 2 :200 * 10 = 2000
133 131 // 运费 0
134   - Map<Long, SpuDeliveryExpressTemplateRespBO> respMap = new HashMap<>();
135   - respMap.put(1L, spuTemplateRespBO);
  132 + Map<Long, DeliveryExpressTemplateRespBO> respMap = new HashMap<>();
  133 + respMap.put(1L, templateRespBO);
136 134 // 准备运费模板包邮配置数据 包邮 订单总件数 > 包邮件数时 12 > 10
137   - freeBO = randomPojo(DeliveryExpressTemplateFreeBO.class,
  135 + freeBO = randomPojo(DeliveryExpressTemplateRespBO.DeliveryExpressTemplateFreeBO.class,
138 136 item -> item.setFreeCount(10).setFreePrice(1000));
139   - spuTemplateRespBO.setTemplateFree(freeBO);
  137 + templateRespBO.setTemplateFree(freeBO);
140 138 // mock 方法
141 139 when(addressApi.getAddress(eq(10L), eq(1L))).thenReturn(addressResp);
142   - when(deliveryExpressTemplateService.getExpressTemplateMapBySpuIdsAndArea(eq(asSet(1L)), eq(10)))
  140 + when(deliveryExpressTemplateService.getExpressTemplateMapByIdsAndArea(eq(asSet(1L)), eq(10)))
143 141 .thenReturn(respMap);
144 142  
145 143 calculator.calculate(reqBO, resultBO);
... ...