From 53e9be733f71019d97a91ef1cc87053e1031c575 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 24 May 2023 23:40:55 +0800 Subject: [PATCH 1/6] =?UTF-8?q?mall=EF=BC=9Areview=20+=20mall=EF=BC=9A?= =?UTF-8?q?=E5=BF=AB=E9=80=92=E5=85=AC=E5=8F=B8=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/optional/mall.sql | 40 +++++++++---------- .../delivery/DeliveryExpressController.java | 31 +++++++------- .../delivery/vo/DeliveryExpressBaseVO.java | 12 +++--- .../delivery/vo/DeliveryExpressExcelVO.java | 7 ++-- .../vo/DeliveryExpressExportReqVO.java | 2 +- .../delivery/vo/DeliveryExpressPageReqVO.java | 2 +- 6 files changed, 45 insertions(+), 49 deletions(-) diff --git a/sql/mysql/optional/mall.sql b/sql/mysql/optional/mall.sql index 83853b22b..ca9f584b2 100644 --- a/sql/mysql/optional/mall.sql +++ b/sql/mysql/optional/mall.sql @@ -330,9 +330,9 @@ CREATE TABLE `product_favorite` ( -- ---------------------------- DROP TABLE IF EXISTS `trade_delivery_express_template`; CREATE TABLE `trade_delivery_express_template` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号,自增', + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', `name` varchar(64) NOT NULL COMMENT '模板名称', - `charge_mode` tinyint NOT NULL DEFAULT 1 COMMENT '配送计费方式 1:按件 2:按重量 3:按体积', + `charge_mode` tinyint NOT NULL COMMENT '配送计费方式', `sort` int NOT NULL DEFAULT 0 COMMENT '排序', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', @@ -348,11 +348,11 @@ CREATE TABLE `trade_delivery_express_template` ( -- ---------------------------- DROP TABLE IF EXISTS `trade_delivery_express_template_free`; CREATE TABLE `trade_delivery_express_template_free` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号,自增', - `template_id` bigint NOT NULL COMMENT '配送模板编号, 对应delivery_template表id', - `area_id` int NOT NULL COMMENT '包邮区域id', - `free_price` int NOT NULL COMMENT '包邮金额(单位分) 订单总金额>包邮金额才免运费', - `free_count` int NOT NULL DEFAULT 0 COMMENT '包邮件数,订单总件数>包邮件数才免运费', + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', + `template_id` bigint NOT NULL COMMENT '快递运费模板编号', + `area_id` int NOT NULL COMMENT '包邮区域 id', + `free_price` int NOT NULL COMMENT '包邮金额,单位:分', + `free_count` int NOT NULL DEFAULT 0 COMMENT '包邮件数,', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', @@ -368,13 +368,13 @@ CREATE TABLE `trade_delivery_express_template_free` ( DROP TABLE IF EXISTS `trade_delivery_express_template_charge`; CREATE TABLE `trade_delivery_express_template_charge` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号,自增', - `template_id` bigint NOT NULL COMMENT '配送模板编号, 对应delivery_template表id', - `area_id` int NOT NULL COMMENT '配送区域id 1:适用于全国', - `charge_mode` tinyint NOT NULL COMMENT '配送计费方式 1:按件 2:按重量 3:按体积', - `start_count` double NOT NULL COMMENT '首件数量(件数,重量,或体积)', - `start_price` int NOT NULL COMMENT '起步价(单位分)', - `extra_count` double NOT NULL COMMENT '续件数量(件,重量,或体积)', - `extra_price` int NOT NULL COMMENT '额外价(单位分)', + `template_id` bigint NOT NULL COMMENT '快递运费模板编号', + `area_id` int NOT NULL COMMENT '配送区域 id', + `charge_mode` tinyint NOT NULL COMMENT '配送计费方式', + `start_count` double NOT NULL COMMENT '首件数量', + `start_price` int NOT NULL COMMENT '起步价,单位:分', + `extra_count` double NOT NULL COMMENT '续件数量', + `extra_price` int NOT NULL COMMENT '额外价,单位:分', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', @@ -417,7 +417,7 @@ DROP TABLE IF EXISTS `trade_delivery_pick_up_store_staff`; CREATE TABLE `trade_delivery_pick_up_store_staff` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号,自增', store_id bigint NOT NULL COMMENT '自提门店编号', - `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态(0正常 1停用)', + `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', @@ -451,12 +451,12 @@ CREATE TABLE `trade_delivery_pick_up_store_staff` ( -- ---------------------------- DROP TABLE IF EXISTS `trade_delivery_express`; CREATE TABLE `trade_delivery_express` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号,自增', - `code` varchar(64) NOT NULL COMMENT '快递公司编号', + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', + `code` varchar(64) NOT NULL COMMENT '快递公司编码', `name` varchar(64) NOT NULL COMMENT '快递公司名称', - `logo` varchar(256) COMMENT '快递公司logo', + `logo` varchar(256) COMMENT '快递公司 logo', `sort` int NOT NULL DEFAULT 0 COMMENT '排序', - `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态(0正常 1停用)', + `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', @@ -540,4 +540,4 @@ INSERT INTO `ruoyi-vue-pro`.`system_dict_type` (`id`, `name`, `type`, `status`, INSERT INTO `ruoyi-vue-pro`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1237, 2, '按体积', '3', 'trade_delivery_express_charge_mode', 0, '', '', '', '1', '2023-05-21 22:47:18', '1', '2023-05-21 22:47:18', b'0'); INSERT INTO `ruoyi-vue-pro`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1236, 1, '按重量', '2', 'trade_delivery_express_charge_mode', 0, '', '', '', '1', '2023-05-21 22:46:58', '1', '2023-05-21 22:46:58', b'0'); INSERT INTO `ruoyi-vue-pro`.`system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1235, 0, '按件', '1', 'trade_delivery_express_charge_mode', 0, '', '', '', '1', '2023-05-21 22:46:40', '1', '2023-05-21 22:46:40', b'0'); -COMMIT; \ No newline at end of file +COMMIT; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java index 98515935b..fde0b5d79 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java @@ -1,31 +1,28 @@ package cn.iocoder.yudao.module.trade.controller.admin.delivery; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.*; import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryExpressConvert; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; -import org.springframework.web.bind.annotation.*; -import javax.annotation.Resource; -import org.springframework.validation.annotation.Validated; -import org.springframework.security.access.prepost.PreAuthorize; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; -import javax.validation.constraints.*; -import javax.validation.*; -import javax.servlet.http.*; -import java.util.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; +import java.util.List; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; - -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; - -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Tag(name = "管理后台 - 快递公司") @RestController diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressBaseVO.java index ea1a10461..538027c81 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressBaseVO.java @@ -1,11 +1,9 @@ package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import java.util.*; -import java.time.LocalDateTime; -import java.time.LocalDateTime; -import javax.validation.constraints.*; +import lombok.Data; + +import javax.validation.constraints.NotNull; /** * 快递公司 Base VO,提供给添加、修改、详细的子 VO 使用 @@ -14,8 +12,8 @@ import javax.validation.constraints.*; @Data public class DeliveryExpressBaseVO { - @Schema(description = "快递公司编号", required = true) - @NotNull(message = "快递公司编号不能为空") + @Schema(description = "快递公司编码", required = true) + @NotNull(message = "快递公司编码不能为空") private String code; @Schema(description = "快递公司名称", required = true, example = "李四") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExcelVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExcelVO.java index ba7e646d5..45d92aa43 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExcelVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExcelVO.java @@ -16,19 +16,20 @@ public class DeliveryExpressExcelVO { @ExcelProperty("编号") private Long id; - @ExcelProperty("快递公司编号") + @ExcelProperty("快递公司编码") private String code; @ExcelProperty("快递公司名称") private String name; - @ExcelProperty("快递公司logo") + @ExcelProperty("快递公司 logo") private String logo; @ExcelProperty("排序") private Integer sort; - @ExcelProperty("状态(0正常 1停用)") + @ExcelProperty("状态") + // TODO @jason:可以使用 @DictFormat(DictTypeConstants.COMMON_STATUS) private Byte status; @ExcelProperty("创建时间") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExportReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExportReqVO.java index cb738a6db..6e44cc45f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExportReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExportReqVO.java @@ -12,7 +12,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @Data public class DeliveryExpressExportReqVO { - @Schema(description = "快递公司编号") + @Schema(description = "快递公司编码") private String code; @Schema(description = "快递公司名称", example = "李四") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressPageReqVO.java index 5425bf42a..50826ea36 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressPageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressPageReqVO.java @@ -15,7 +15,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @ToString(callSuper = true) public class DeliveryExpressPageReqVO extends PageParam { - @Schema(description = "快递公司编号") + @Schema(description = "快递公司编码") private String code; @Schema(description = "快递公司名称", example = "李四") From 0083d1240423338605ab8ec3ea03633d0f3d543c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 25 May 2023 22:51:38 +0800 Subject: [PATCH 2/6] =?UTF-8?q?mall=EF=BC=9Areview=20+=20mall=EF=BC=9A?= =?UTF-8?q?=E5=BF=AB=E9=80=92=E8=B4=B9=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../delivery/DeliveryExpressController.java | 1 + .../DeliveryExpressTemplateConvert.java | 57 +++++++++++-------- .../DeliveryExpressTemplateMapper.java | 4 +- .../DeliveryExpressTemplateServiceImpl.java | 13 +++-- .../controller/admin/ip/AreaController.java | 7 ++- .../admin/ip/vo/LazyAreaNodeRespVO.java | 3 + 6 files changed, 53 insertions(+), 32 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java index fde0b5d79..b245ec860 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java @@ -74,6 +74,7 @@ public class DeliveryExpressController { return success(DeliveryExpressConvert.INSTANCE.convertPage(pageResult)); } + // TODO @jason:运费模版,可以去掉哈,没啥用; @GetMapping("/export-excel") @Operation(summary = "导出快递公司 Excel") @PreAuthorize("@ss.hasPermission('trade:delivery:express:export')") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java index dbbb7ba83..d4d23cb0a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java @@ -1,10 +1,7 @@ package cn.iocoder.yudao.module.trade.convert.delivery; -import java.util.*; - import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; - import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.*; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; @@ -12,6 +9,10 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemp import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + /** * 快递运费模板 Convert * @@ -22,6 +23,8 @@ public interface DeliveryExpressTemplateConvert { DeliveryExpressTemplateConvert INSTANCE = Mappers.getMapper(DeliveryExpressTemplateConvert.class); + // ========== Template ========== + DeliveryExpressTemplateDO convert(DeliveryExpressTemplateCreateReqVO bean); DeliveryExpressTemplateDO convert(DeliveryExpressTemplateUpdateReqVO bean); @@ -36,10 +39,35 @@ public interface DeliveryExpressTemplateConvert { List convertList02(List list); + default DeliveryExpressTemplateRespVO convert(DeliveryExpressTemplateDO bean, + List chargeList, + List freeList){ + DeliveryExpressTemplateRespVO respVO = convert2(bean); + respVO.setTemplateCharge(convertTemplateChargeList(chargeList)); + respVO.setTemplateFree(convertTemplateFreeList(freeList)); + return respVO; + } + + // ========== Template Charge ========== + DeliveryExpressTemplateChargeDO convertTemplateCharge(Long templateId, Integer chargeMode, ExpressTemplateChargeBaseVO vo); DeliveryExpressTemplateChargeDO convertTemplateCharge(ExpressTemplateChargeUpdateVO vo); + default List convertTemplateChargeList(Long templateId, Integer chargeMode, List list) { + // TODO @jason:可以使用 CollectionUtils.convertList,本质上就是 stream convert list + if(CollUtil.isEmpty(list)){ + return Collections.emptyList(); + } + List templateChargeList = new ArrayList<>(list.size()); + for (ExpressTemplateChargeBaseVO item : list) { + templateChargeList.add(convertTemplateCharge(templateId, chargeMode, item)); + } + return templateChargeList; + } + + // ========== Template Free ========== + DeliveryExpressTemplateFreeDO convertTemplateFree(Long templateId, ExpressTemplateFreeBaseVO vo); DeliveryExpressTemplateFreeDO convertTemplateFree(ExpressTemplateFreeUpdateVO vo); @@ -48,20 +76,9 @@ public interface DeliveryExpressTemplateConvert { List convertTemplateFreeList(List list); - default List convertTemplateChargeList(Long templateId, Integer chargeMode, List list){ - if(CollUtil.isEmpty(list)){ - return Collections.emptyList(); - } - List templateChargeList = new ArrayList<>( list.size() ); - for (ExpressTemplateChargeBaseVO item : list) { - templateChargeList.add(convertTemplateCharge(templateId, chargeMode, item)); - } - return templateChargeList; - } - - - + // TODO @jason:, List,中间一个空格哈。代码的空格和空行要注意,嘿嘿~ default List convertTemplateFreeList(Long templateId, List list) { + // TODO @jason:可以使用 CollectionUtils.convertList,本质上就是 stream convert list if (CollUtil.isEmpty(list)) { return Collections.emptyList(); } @@ -72,12 +89,4 @@ public interface DeliveryExpressTemplateConvert { return templateFreeList; } - default DeliveryExpressTemplateRespVO convert(DeliveryExpressTemplateDO bean, - List chargeList, - List freeList){ - DeliveryExpressTemplateRespVO respVO = convert2(bean); - respVO.setTemplateCharge(convertTemplateChargeList(chargeList)); - respVO.setTemplateFree(convertTemplateFreeList(freeList)); - return respVO; - } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateMapper.java index 4f7460350..85b52851e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateMapper.java @@ -3,11 +3,9 @@ package cn.iocoder.yudao.module.trade.dal.mysql.delivery; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; - import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressTemplateExportReqVO; import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressTemplatePageReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; @@ -33,8 +31,10 @@ public interface DeliveryExpressTemplateMapper extends BaseMapperX() .eq(DeliveryExpressTemplateDO::getName, name)); } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateServiceImpl.java index 420e70687..76182eed7 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateServiceImpl.java @@ -36,6 +36,7 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla private DeliveryExpressTemplateChargeMapper expressTemplateChargeMapper; @Resource private DeliveryExpressTemplateFreeMapper expressTemplateFreeMapper; + // TODO @jason:应该不用 BatchInsertMapper 拉,直接走 expressTemplateChargeMapper.insertBatch @Resource private DeliveryExpressTemplateChargeMapper.BatchInsertMapper expressTemplateChargeBatchMapper; @Resource @@ -44,12 +45,15 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla @Override @Transactional(rollbackFor = Exception.class) public Long createDeliveryExpressTemplate(DeliveryExpressTemplateCreateReqVO createReqVO) { + // TODO @jason:中英文之间,要有空格哈。例如说, // 校验模板名是否唯一 //校验模板名是否唯一 validateTemplateNameUnique(createReqVO.getName(), null); + // 插入 DeliveryExpressTemplateDO deliveryExpressTemplate = INSTANCE.convert(createReqVO); expressTemplateMapper.insert(deliveryExpressTemplate); //插入运费模板计费表 + // TODO @jason:if (,中间要有空格 if(CollUtil.isNotEmpty(createReqVO.getTemplateCharge())) { expressTemplateChargeBatchMapper.saveBatch( INSTANCE.convertTemplateChargeList(deliveryExpressTemplate.getId(), createReqVO.getChargeMode(), createReqVO.getTemplateCharge()) @@ -121,7 +125,7 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla //更新运费区域列表 List updateList = new ArrayList<>(newChargeList.size()); for (ExpressTemplateChargeUpdateVO item : newChargeList) { - if (Objects.nonNull(item.getId())) { + if (Objects.nonNull(item.getId())) { // TODO @jason:null 的判断,还是用 item.getId() != null 好一点。一般数组用方法,主要考虑 null + length = 0; //计费模式以主表为准 item.setChargeMode(updateReqVO.getChargeMode()); updateList.add(INSTANCE.convertTemplateCharge(item)); @@ -131,7 +135,7 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla addList.add(INSTANCE.convertTemplateCharge(item)); } } - //删除的运费区域id + //删除的运费区域id TODO @jason:这块放到删除部分的那块逻辑会好点(149 - 152 行),主要变量要贴相应的逻辑近一点哈。 Set deleteChargeIds = CollectionUtils.convertSet(oldChargeList, DeliveryExpressTemplateChargeDO::getId); deleteChargeIds.removeAll(CollectionUtils.convertSet(updateList, DeliveryExpressTemplateChargeDO::getId)); //新增 @@ -153,6 +157,7 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla public void deleteDeliveryExpressTemplate(Long id) { // 校验存在 validateDeliveryExpressTemplateExists(id); + // 删除主表 expressTemplateMapper.deleteById(id); // 删除运费从表 @@ -162,9 +167,9 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla } /** - * 校验运费模板名是否唯一 + * 校验运费模板名是否唯一 // TODO @jason:方法注释,和参数,要空一行。 * @param name 模板名称 - * @param id 运费模板编号, 可以为null + * @param id 运费模板编号, 可以为null // TODO @jason:中英文之间,要空一行;其它地方也看看哈 */ private void validateTemplateNameUnique(String name, Long id) { DeliveryExpressTemplateDO template = expressTemplateMapper.selectByName(name); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java index 87e6e0bfd..0988cbe90 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java @@ -15,7 +15,6 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Set; @@ -35,6 +34,8 @@ public class AreaController { return success(AreaConvert.INSTANCE.convertList(area.getChildren())); } + // TODO @jason:1)url 使用中划线分隔哈,然后可以改成 children;2)id 需要添加 @RequestParam,因为可能会混淆编译; + // 3) swagger 注解要写下哈; @GetMapping("/getChildrenArea") @Operation(summary = "获得地区的下级区域") public CommonResult> getChildrenArea(Integer id) { @@ -43,8 +44,10 @@ public class AreaController { return success(AreaConvert.INSTANCE.convertList2(area.getChildren())); } + // TODO @jason:1)读请求,使用 get 哈。2)然后参数不应该使用 @RequestBody;3)areaIds 改成 ids 更合适; + // 4)方法改成 getAreaChildrenList 获得子节点们;5)url 可以已改成 children-list @PostMapping("/list") - @Operation(summary = "通过区域ids获得地区列表") + @Operation(summary = "通过区域 ids 获得地区列表") public CommonResult> list(@RequestBody Set areaIds) { List areaList = new ArrayList<>(areaIds.size()); for (Integer areaId : areaIds) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/LazyAreaNodeRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/LazyAreaNodeRespVO.java index fd184b307..e95defb1c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/LazyAreaNodeRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/LazyAreaNodeRespVO.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.controller.admin.ip.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +// TODO @jason:1)VO 不添加注释作者哈。2)是不是改成 AreaNodeSimpleRespVO,它其实是返回一个简洁的地区,懒加载只是它的使用场景; /** * @author jason */ @@ -16,6 +17,8 @@ public class LazyAreaNodeRespVO { @Schema(description = "名字", required = true, example = "北京") private String name; + // TODO @jason:1)不设置默认值,交给业务逻辑那写入;2)这个字段必须返回哇? @Schema(description = "是否叶子节点", required = true, example = "false") private Boolean leaf = Boolean.FALSE; + } From 02fa6fc5c6187bc1c731e11f574675d7aac410fc Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 26 May 2023 23:58:26 +0800 Subject: [PATCH 3/6] =?UTF-8?q?mall=20+=20trade=EF=BC=9A=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E4=BB=B7=E6=A0=BC=E5=AD=97=E6=AE=B5=EF=BC=8C=E6=9B=B4=E6=98=93?= =?UTF-8?q?=E6=87=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/price/dto/PriceCalculateRespDTO.java | 12 ++--- .../promotion/convert/price/PriceConvert.java | 6 +-- .../service/price/PriceServiceImpl.java | 7 ++- .../service/price/PriceServiceTest.java | 29 +++++----- .../admin/order/vo/TradeOrderBaseVO.java | 3 -- .../order/vo/AppTradeOrderDetailRespVO.java | 5 +- .../dal/dataobject/order/TradeOrderDO.java | 27 +++------- .../dataobject/order/TradeOrderItemDO.java | 53 ++++++++++--------- .../aftersale/TradeAfterSaleServiceImpl.java | 2 +- .../service/order/TradeOrderServiceTest.java | 7 +-- 10 files changed, 58 insertions(+), 93 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateRespDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateRespDTO.java index cda6d99d6..a067aa0b5 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateRespDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateRespDTO.java @@ -38,6 +38,7 @@ public class PriceCalculateRespDTO { */ private List promotions; + // TODO @芋艿:需要改造下,主要是价格字段 /** * 订单 */ @@ -51,14 +52,7 @@ public class PriceCalculateRespDTO { * * 对应 taobao 的 trade.total_fee 字段 */ - private Integer originalPrice; - /** - * 订单原价(总),单位:分 - * - * 基于 {@link OrderItem#getPayPrice()} 求和 - * 和 {@link #originalPrice} 的差异:去除商品级优惠 - */ - private Integer orderPrice; + private Integer totalPrice; /** * 订单优惠(总),单位:分 * @@ -207,7 +201,7 @@ public class PriceCalculateRespDTO { /** * 计算时的原价(总),单位:分 */ - private Integer originalPrice; + private Integer totalPrice; /** * 计算时的优惠(总),单位:分 */ diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/price/PriceConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/price/PriceConvert.java index 8e4b24666..e8649cb61 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/price/PriceConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/price/PriceConvert.java @@ -22,7 +22,7 @@ public interface PriceConvert { // 创建 PriceCalculateRespDTO 对象 PriceCalculateRespDTO priceCalculate = new PriceCalculateRespDTO(); // 创建它的 Order 属性 - PriceCalculateRespDTO.Order order = new PriceCalculateRespDTO.Order().setOriginalPrice(0).setDiscountPrice(0) + PriceCalculateRespDTO.Order order = new PriceCalculateRespDTO.Order().setTotalPrice(0).setDiscountPrice(0) .setCouponPrice(0).setPointPrice(0).setDeliveryPrice(0).setPayPrice(0) .setItems(new ArrayList<>()).setCouponId(calculateReqDTO.getCouponId()); priceCalculate.setOrder(order).setPromotions(new ArrayList<>()); @@ -38,8 +38,8 @@ public interface PriceConvert { orderItem.setPayPrice(orderItem.getOriginalPrice()).setOrderDividePrice(orderItem.getOriginalPrice()); priceCalculate.getOrder().getItems().add(orderItem); // 补充价格信息到 Order 中 - order.setOriginalPrice(order.getOriginalPrice() + orderItem.getOriginalPrice()) - .setOrderPrice(order.getOriginalPrice()).setPayPrice(order.getOriginalPrice()); + order.setTotalPrice(order.getTotalPrice() + orderItem.getOriginalPrice()) + .setPayPrice(order.getTotalPrice()); }); return priceCalculate; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java index 03abb061f..7aab0bee5 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java @@ -406,7 +406,7 @@ public class PriceServiceImpl implements PriceService { // 创建营销明细 PriceCalculateRespDTO.Promotion promotion = new PriceCalculateRespDTO.Promotion() .setId(id).setName(name).setType(type).setLevel(level) - .setOriginalPrice(promotionItem.getOriginalPrice()).setDiscountPrice(promotionItem.getDiscountPrice()) + .setTotalPrice(promotionItem.getOriginalPrice()).setDiscountPrice(promotionItem.getDiscountPrice()) .setItems(singletonList(promotionItem)).setMeet(meet).setMeetTip(meetTip); priceCalculate.getPromotions().add(promotion); } @@ -437,7 +437,7 @@ public class PriceServiceImpl implements PriceService { // 创建营销明细 PriceCalculateRespDTO.Promotion promotion = new PriceCalculateRespDTO.Promotion() .setId(id).setName(name).setType(type).setLevel(level) - .setOriginalPrice(getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum)) + .setTotalPrice(getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum)) .setDiscountPrice(getSumValue(discountPrices, value -> value, Integer::sum)) .setItems(promotionItems).setMeet(meet).setMeetTip(meetTip); priceCalculate.getPromotions().add(promotion); @@ -453,7 +453,7 @@ public class PriceServiceImpl implements PriceService { Integer originalPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum); PriceCalculateRespDTO.Promotion promotion = new PriceCalculateRespDTO.Promotion() .setId(id).setName(name).setType(type).setLevel(level) - .setOriginalPrice(originalPrice).setDiscountPrice(0) + .setTotalPrice(originalPrice).setDiscountPrice(0) .setItems(promotionItems).setMeet(false).setMeetTip(meetTip); priceCalculate.getPromotions().add(promotion); } @@ -476,7 +476,6 @@ public class PriceServiceImpl implements PriceService { // 设置 Order 相关相关字段 PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); order.setPayPrice(order.getPayPrice() - diffPayPrice); - order.setOrderPrice(order.getOrderPrice() - diffPayPrice); } /** diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java index 0c7b2d6ec..9e40ff67b 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java @@ -70,8 +70,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { PriceCalculateRespDTO priceCalculate = priceService.calculatePrice(calculateReqDTO); // 断言 Order 部分 PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); - assertEquals(order.getOriginalPrice(), 200); - assertEquals(order.getOrderPrice(), 180); + assertEquals(order.getTotalPrice(), 200); assertEquals(order.getDiscountPrice(), 0); assertEquals(order.getPointPrice(), 0); assertEquals(order.getDeliveryPrice(), 0); @@ -95,7 +94,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion.getName(), "会员折扣"); assertEquals(promotion.getType(), PromotionTypeEnum.MEMBER.getType()); assertEquals(promotion.getLevel(), PromotionLevelEnum.SKU.getLevel()); - assertEquals(promotion.getOriginalPrice(), 200); + assertEquals(promotion.getTotalPrice(), 200); assertEquals(promotion.getDiscountPrice(), 20); assertTrue(promotion.getMeet()); assertEquals(promotion.getMeetTip(), "会员折扣:省 0.20 元"); @@ -133,8 +132,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { PriceCalculateRespDTO priceCalculate = priceService.calculatePrice(calculateReqDTO); // 断言 Order 部分 PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); - assertEquals(order.getOriginalPrice(), 350); - assertEquals(order.getOrderPrice(), 210); + assertEquals(order.getTotalPrice(), 350); assertEquals(order.getDiscountPrice(), 0); assertEquals(order.getPointPrice(), 0); assertEquals(order.getDeliveryPrice(), 0); @@ -167,7 +165,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion01.getName(), "活动 1000 号"); assertEquals(promotion01.getType(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType()); assertEquals(promotion01.getLevel(), PromotionLevelEnum.SKU.getLevel()); - assertEquals(promotion01.getOriginalPrice(), 200); + assertEquals(promotion01.getTotalPrice(), 200); assertEquals(promotion01.getDiscountPrice(), 80); assertTrue(promotion01.getMeet()); assertEquals(promotion01.getMeetTip(), "限时折扣:省 0.80 元"); @@ -181,7 +179,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion02.getName(), "活动 2000 号"); assertEquals(promotion02.getType(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType()); assertEquals(promotion02.getLevel(), PromotionLevelEnum.SKU.getLevel()); - assertEquals(promotion02.getOriginalPrice(), 150); + assertEquals(promotion02.getTotalPrice(), 150); assertEquals(promotion02.getDiscountPrice(), 60); assertTrue(promotion02.getMeet()); assertEquals(promotion02.getMeetTip(), "限时折扣:省 0.60 元"); @@ -225,8 +223,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { PriceCalculateRespDTO priceCalculate = priceService.calculatePrice(calculateReqDTO); // 断言 Order 部分 PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); - assertEquals(order.getOriginalPrice(), 470); - assertEquals(order.getOrderPrice(), 470); + assertEquals(order.getTotalPrice(), 470); assertEquals(order.getDiscountPrice(), 130); assertEquals(order.getPointPrice(), 0); assertEquals(order.getDeliveryPrice(), 0); @@ -268,7 +265,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion01.getName(), "活动 1000 号"); assertEquals(promotion01.getType(), PromotionTypeEnum.REWARD_ACTIVITY.getType()); assertEquals(promotion01.getLevel(), PromotionLevelEnum.ORDER.getLevel()); - assertEquals(promotion01.getOriginalPrice(), 350); + assertEquals(promotion01.getTotalPrice(), 350); assertEquals(promotion01.getDiscountPrice(), 70); assertTrue(promotion01.getMeet()); assertEquals(promotion01.getMeetTip(), "满减送:省 0.70 元"); @@ -287,7 +284,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion02.getName(), "活动 2000 号"); assertEquals(promotion02.getType(), PromotionTypeEnum.REWARD_ACTIVITY.getType()); assertEquals(promotion02.getLevel(), PromotionLevelEnum.ORDER.getLevel()); - assertEquals(promotion02.getOriginalPrice(), 120); + assertEquals(promotion02.getTotalPrice(), 120); assertEquals(promotion02.getDiscountPrice(), 60); assertTrue(promotion02.getMeet()); assertEquals(promotion02.getMeetTip(), "满减送:省 0.60 元"); @@ -323,8 +320,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { PriceCalculateRespDTO priceCalculate = priceService.calculatePrice(calculateReqDTO); // 断言 Order 部分 PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); - assertEquals(order.getOriginalPrice(), 350); - assertEquals(order.getOrderPrice(), 350); + assertEquals(order.getTotalPrice(), 350); assertEquals(order.getDiscountPrice(), 0); assertEquals(order.getPointPrice(), 0); assertEquals(order.getDeliveryPrice(), 0); @@ -357,7 +353,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion01.getName(), "活动 1000 号"); assertEquals(promotion01.getType(), PromotionTypeEnum.REWARD_ACTIVITY.getType()); assertEquals(promotion01.getLevel(), PromotionLevelEnum.ORDER.getLevel()); - assertEquals(promotion01.getOriginalPrice(), 350); + assertEquals(promotion01.getTotalPrice(), 350); assertEquals(promotion01.getDiscountPrice(), 0); assertFalse(promotion01.getMeet()); assertEquals(promotion01.getMeetTip(), "TODO"); // TODO 芋艿:后面再想想 @@ -396,8 +392,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { PriceCalculateRespDTO priceCalculate = priceService.calculatePrice(calculateReqDTO); // 断言 Order 部分 PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); - assertEquals(order.getOriginalPrice(), 470); - assertEquals(order.getOrderPrice(), 470); + assertEquals(order.getTotalPrice(), 470); assertEquals(order.getDiscountPrice(), 0); assertEquals(order.getPointPrice(), 0); assertEquals(order.getDeliveryPrice(), 0); @@ -440,7 +435,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion01.getName(), "程序员节"); assertEquals(promotion01.getType(), PromotionTypeEnum.COUPON.getType()); assertEquals(promotion01.getLevel(), PromotionLevelEnum.COUPON.getLevel()); - assertEquals(promotion01.getOriginalPrice(), 350); + assertEquals(promotion01.getTotalPrice(), 350); assertEquals(promotion01.getDiscountPrice(), 70); assertTrue(promotion01.getMeet()); assertEquals(promotion01.getMeetTip(), "优惠劵:省 0.70 元"); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderBaseVO.java index a1428c436..3453a3c2e 100755 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderBaseVO.java @@ -73,9 +73,6 @@ public class TradeOrderBaseVO { @Schema(description = "商品原价(总)", required = true, example = "1000") private Integer originalPrice; - @Schema(description = "订单原价(总)", required = true, example = "1000") - private Integer orderPrice; - @Schema(description = "订单优惠(总)", required = true, example = "100") private Integer discountPrice; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java index fd54444db..647ea2638 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java @@ -59,10 +59,7 @@ public class AppTradeOrderDetailRespVO { private String payChannelCode; @Schema(description = "商品原价(总)", required = true, example = "1000") - private Integer originalPrice; - - @Schema(description = "订单原价(总)", required = true, example = "1000") - private Integer orderPrice; + private Integer totalPrice; @Schema(description = "订单优惠(总)", required = true, example = "100") private Integer discountPrice; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java index 0faa67db3..f4d27a3ae 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java @@ -2,13 +2,8 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.order; import cn.iocoder.yudao.framework.common.enums.TerminalEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO.OrderItem; import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderDeliveryStatusEnum; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; +import cn.iocoder.yudao.module.trade.enums.order.*; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; @@ -134,25 +129,15 @@ public class TradeOrderDO extends BaseDO { private String payChannelCode; /** - * 商品原价(总),单位:分 + * 商品原价,单位:分 * * totalPrice = {@link TradeOrderItemDO#getPrice()} * {@link TradeOrderItemDO#getCount()} 求和 * * 对应 taobao 的 trade.total_fee 字段 */ private Integer totalPrice; - // TODO 芋艿:是不是要删除这个字段? /** - * 订单原价(总),单位:分 - * - * 1. orderPrice = {@link OrderItem#getPayPrice()} 求和 - * 2. orderPrice = {@link #totalPrice} - 商品级优惠 - */ - private Integer orderPrice; - /** - * 订单优惠(总),单位:分 - * - * 订单级优惠:对主订单的优惠,常见如:订单满 200 元减 10 元;订单满 80 包邮。 + * 优惠金额,单位:分 * * 对应 taobao 的 order.discount_fee 字段 */ @@ -162,7 +147,7 @@ public class TradeOrderDO extends BaseDO { */ private Integer deliveryPrice; /** - * 订单调价(总),单位:分 + * 订单调价,单位:分 * * 正数,加价;负数,减价 */ @@ -170,11 +155,11 @@ public class TradeOrderDO extends BaseDO { /** * 应付金额(总),单位:分 * - * = {@link OrderItem#getPayPrice()} 求和 + * = {@link #totalPrice} * - {@link #couponPrice} * - {@link #pointPrice} - * + {@link #deliveryPrice} * - {@link #discountPrice} + * + {@link #deliveryPrice} * + {@link #adjustPrice} */ private Integer payPrice; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java index 42fc106f5..323389c94 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java @@ -102,44 +102,47 @@ public class TradeOrderItemDO extends BaseDO { */ private Integer price; /** - * 商品优惠(总),单位:分 - * - * 商品级优惠:对单个商品的,常见如:商品原价的 8 折;商品原价的减 50 元 + * 优惠金额(总),单位:分 * * 对应 taobao 的 order.discount_fee 字段 */ private Integer discountPrice; /** - * 子订单实付金额(总),不算主订单分摊金额,单位:分 + * 运费金额(总),单位:分 + */ + private Integer deliveryPrice; + /** + * 订单调价(总),单位:分 + * + * 正数,加价;负数,减价 + */ + private Integer adjustPrice; + /** + * 应付金额(总),单位:分 * * = {@link #price} * {@link #count} + * - {@link #couponPrice} + * - {@link #pointPrice} * - {@link #discountPrice} - * - * 对应 taobao 的 order.payment 字段 + * + {@link #deliveryPrice} + * + {@link #adjustPrice} */ private Integer payPrice; - /** - * 子订单分摊金额(总),单位:分 - * 需要分摊 {@link TradeOrderDO#getDiscountPrice()}、{@link TradeOrderDO#getCouponPrice()}、{@link TradeOrderDO#getPointPrice()} - * - * 对应 taobao 的 order.part_mjz_discount 字段 - * 淘宝说明:子订单分摊优惠基础逻辑:一般正常优惠券和满减优惠按照子订单的金额进行分摊,特殊情况如果优惠券是指定商品使用的,只会分摊到对应商品子订单上不分摊。 - */ - private Integer orderPartPrice; - /** - * 分摊后子订单实付金额(总),单位:分 - * - * = {@link #payPrice} - * - {@link #orderPartPrice} - * - * 对应 taobao 的 divide_order_fee 字段 - */ - private Integer orderDividePrice; - // ========== 营销基本信息 ========== - // TODO 芋艿:在捉摸一下 + /** + * 优惠劵减免金额,单位:分 + * + * 对应 taobao 的 trade.coupon_fee 字段 + */ + private Integer couponPrice; + /** + * 积分抵扣的金额,单位:分 + * + * 对应 taobao 的 trade.point_fee 字段 + */ + private Integer pointPrice; // ========== 售后基本信息 ========== /** diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java index 2da892d61..374af0a16 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java @@ -97,7 +97,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService { } // 申请的退款金额,不能超过商品的价格 - if (createReqVO.getRefundPrice() > orderItem.getOrderDividePrice()) { + if (createReqVO.getRefundPrice() > orderItem.getPayPrice()) { throw exception(AFTER_SALE_CREATE_FAIL_REFUND_PRICE_ERROR); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java index 0b4c3de2d..064ec336e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java @@ -124,7 +124,7 @@ public class TradeOrderServiceTest extends BaseDbUnitTest { .setSpuId(21L).setSkuId(2L).setCount(4).setOriginalPrice(80).setOriginalUnitPrice(20) .setDiscountPrice(40).setPayPrice(40).setOrderPartPrice(15).setOrderDividePrice(25); PriceCalculateRespDTO.Order priceOrder = new PriceCalculateRespDTO.Order() - .setOriginalPrice(230).setOrderPrice(100).setDiscountPrice(0).setCouponPrice(30) + .setTotalPrice(230).setDiscountPrice(0).setCouponPrice(30) .setPointPrice(10).setDeliveryPrice(20).setPayPrice(80).setCouponId(101L).setCouponPrice(30) .setItems(Arrays.asList(priceOrderItem01, priceOrderItem02)); when(priceApi.calculatePrice(argThat(priceCalculateReqDTO -> { @@ -170,7 +170,6 @@ public class TradeOrderServiceTest extends BaseDbUnitTest { assertFalse(tradeOrderDO.getPayed()); assertNull(tradeOrderDO.getPayTime()); assertEquals(tradeOrderDO.getTotalPrice(), 230); - assertEquals(tradeOrderDO.getOrderPrice(), 100); assertEquals(tradeOrderDO.getDiscountPrice(), 0); assertEquals(tradeOrderDO.getAdjustPrice(), 0); assertEquals(tradeOrderDO.getPayPrice(), 80); @@ -208,8 +207,6 @@ public class TradeOrderServiceTest extends BaseDbUnitTest { assertEquals(tradeOrderItemDO01.getPrice(), 50); assertEquals(tradeOrderItemDO01.getDiscountPrice(), 20); assertEquals(tradeOrderItemDO01.getPayPrice(), 130); - assertEquals(tradeOrderItemDO01.getOrderPartPrice(), 7); - assertEquals(tradeOrderItemDO01.getOrderDividePrice(), 35); assertEquals(tradeOrderItemDO01.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); // 断言 TradeOrderItemDO 订单(第 2 个) TradeOrderItemDO tradeOrderItemDO02 = tradeOrderItemDOs.get(1); @@ -228,8 +225,6 @@ public class TradeOrderServiceTest extends BaseDbUnitTest { assertEquals(tradeOrderItemDO02.getPrice(), 20); assertEquals(tradeOrderItemDO02.getDiscountPrice(), 40); assertEquals(tradeOrderItemDO02.getPayPrice(), 40); - assertEquals(tradeOrderItemDO02.getOrderPartPrice(), 15); - assertEquals(tradeOrderItemDO02.getOrderDividePrice(), 25); assertEquals(tradeOrderItemDO02.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); // 校验调用 verify(productSkuApi).updateSkuStock(argThat(updateStockReqDTO -> { From 55dbff7570caf069efe2495b6c048e90c12d51b0 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Sat, 27 May 2023 11:20:43 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E8=BF=90=E8=B4=B9=E6=A8=A1=E6=9D=BF=20revi?= =?UTF-8?q?ew=20=E4=BF=AE=E6=94=B9.=20=E8=BF=90=E8=B4=B9=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E9=80=89=E6=8B=A9=E5=A4=9A=E4=B8=AA=E5=8C=BA?= =?UTF-8?q?=E5=9F=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/optional/mall.sql | 6 +- .../common/util/string/StrUtils.java | 6 ++ .../mybatis/core/mapper/BaseMapperX.java | 10 ++ .../core/type/IntegerListTypeHandler.java | 56 ++++++++++ .../delivery/DeliveryExpressController.java | 2 +- .../DeliveryExpressTemplateController.java | 13 --- .../delivery/vo/DeliveryExpressExcelVO.java | 11 +- .../vo/DeliveryExpressTemplateExcelVO.java | 31 ------ .../DeliveryExpressTemplateExportReqVO.java | 26 ----- .../vo/ExpressTemplateChargeBaseVO.java | 10 +- .../vo/ExpressTemplateChargeUpdateVO.java | 4 +- .../vo/ExpressTemplateFreeBaseVO.java | 10 +- .../vo/ExpressTemplateFreeUpdateVO.java | 2 - .../delivery/DeliveryExpressConvert.java | 2 +- .../DeliveryExpressTemplateConvert.java | 28 +---- .../DeliveryExpressTemplateChargeDO.java | 11 +- .../DeliveryExpressTemplateFreeDO.java | 12 ++- .../DeliveryExpressTemplateChargeMapper.java | 4 - .../DeliveryExpressTemplateFreeMapper.java | 4 - .../DeliveryExpressTemplateMapper.java | 16 +-- .../DeliveryExpressTemplateService.java | 9 -- .../DeliveryExpressTemplateServiceImpl.java | 101 ++++++++---------- .../controller/admin/ip/AreaController.java | 22 ++-- .../admin/ip/vo/AreaNodeSimpleRespVO.java | 19 ++++ .../admin/ip/vo/LazyAreaNodeRespVO.java | 24 ----- .../module/system/convert/ip/AreaConvert.java | 8 +- 26 files changed, 193 insertions(+), 254 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/type/IntegerListTypeHandler.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateExcelVO.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateExportReqVO.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeSimpleRespVO.java delete mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/LazyAreaNodeRespVO.java diff --git a/sql/mysql/optional/mall.sql b/sql/mysql/optional/mall.sql index ca9f584b2..1cfda1722 100644 --- a/sql/mysql/optional/mall.sql +++ b/sql/mysql/optional/mall.sql @@ -350,7 +350,7 @@ DROP TABLE IF EXISTS `trade_delivery_express_template_free`; CREATE TABLE `trade_delivery_express_template_free` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', `template_id` bigint NOT NULL COMMENT '快递运费模板编号', - `area_id` int NOT NULL COMMENT '包邮区域 id', + `area_ids` varchar(100) NOT NULL COMMENT '包邮区域 ids', `free_price` int NOT NULL COMMENT '包邮金额,单位:分', `free_count` int NOT NULL DEFAULT 0 COMMENT '包邮件数,', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', @@ -369,7 +369,7 @@ DROP TABLE IF EXISTS `trade_delivery_express_template_charge`; CREATE TABLE `trade_delivery_express_template_charge` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号,自增', `template_id` bigint NOT NULL COMMENT '快递运费模板编号', - `area_id` int NOT NULL COMMENT '配送区域 id', + `area_ids` varchar(100) NOT NULL COMMENT '配送区域 ids', `charge_mode` tinyint NOT NULL COMMENT '配送计费方式', `start_count` double NOT NULL COMMENT '首件数量', `start_price` int NOT NULL COMMENT '起步价,单位:分', @@ -501,7 +501,7 @@ INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, ` INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `status`, `visible`, `keep_alive`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2029, 'Banner删除', 'market:banner:delete', 3, 4, 2025, '', '', '', 0, b'1', b'1', '', '2022-08-01 14:56:14', '', '2022-08-01 14:56:14', b'0'); INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2164, '配送管理', '', 1, 0, 2072, 'delivery', '', '', '', 0, b'1', b'1', b'1', '1', '2023-05-18 09:18:02', '1', '2023-05-18 09:48:48', b'0'); INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2165, '快递发货', '', 1, 0, 2164, 'express', '', '', '', 0, b'1', b'1', b'1', '1', '2023-05-18 09:22:06', '1', '2023-05-18 09:22:06', b'0'); -INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2166, '门店自提', '', 1, 1, 2164, 'pick-up-store', '', '', '', 0, b'1', b'1', b'1', '1', '2023-05-18 09:23:14', '1', '2023-05-18 09:23:14', b'0'); +INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2166, '门店自提', '', 1, 1, 2164, 'pick-up', '', '', '', 0, b'1', b'1', b'1', '1', '2023-05-18 09:23:14', '1', '2023-05-18 09:23:14', b'0'); INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2167, '快递公司', '', 2, 0, 2165, 'express', '', 'mall/trade/delivery/express/index', 'Express', 0, b'1', b'1', b'1', '1', '2023-05-18 09:27:21', '1', '2023-05-18 22:11:14', b'0'); INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2168, '快递公司查询', 'trade:delivery:express:query', 3, 1, 2167, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-18 09:37:53', '', '2023-05-18 09:37:53', b'0'); INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2169, '快递公司创建', 'trade:delivery:express:create', 3, 2, 2167, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-05-18 09:37:53', '', '2023-05-18 09:37:53', b'0'); diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java index 88ba22d87..2ac7278a4 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java @@ -45,4 +45,10 @@ public class StrUtils { return Arrays.stream(longs).boxed().collect(Collectors.toList()); } + public static List splitToInteger(String value, CharSequence separator) { + int[] integers = StrUtil.splitToInt(value, separator); + return Arrays.stream(integers).boxed().collect(Collectors.toList()); + } + + } diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java index 87cf0dddc..7788d2895 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java @@ -113,10 +113,20 @@ public interface BaseMapperX extends MPJBaseMapper { Db.saveBatch(entities, size); } + // @芋艿 是不是叫 updateByDo 或者 updateByEntity 更合适 default void updateBatch(T update) { update(update, new QueryWrapper<>()); } + /** + * 根据ID 批量更新,适合大量数据更新 + * + * @param entities 实体们 + */ + default void updateBatch(Collection entities) { + Db.updateBatchById(entities); + } + default void updateBatch(Collection entities, int size) { Db.updateBatchById(entities, size); } diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/type/IntegerListTypeHandler.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/type/IntegerListTypeHandler.java new file mode 100644 index 000000000..18455ba11 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/type/IntegerListTypeHandler.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.framework.mybatis.core.type; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.util.string.StrUtils; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; +import org.apache.ibatis.type.TypeHandler; + +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +/** + * List 的类型转换器实现类,对应数据库的 varchar 类型 + * + * @author jason + */ +@MappedJdbcTypes(JdbcType.VARCHAR) +@MappedTypes(List.class) +public class IntegerListTypeHandler implements TypeHandler> { + + private static final String COMMA = ","; + + @Override + public void setParameter(PreparedStatement ps, int i, List strings, JdbcType jdbcType) throws SQLException { + ps.setString(i, CollUtil.join(strings, COMMA)); + } + + @Override + public List getResult(ResultSet rs, String columnName) throws SQLException { + String value = rs.getString(columnName); + return getResult(value); + } + + @Override + public List getResult(ResultSet rs, int columnIndex) throws SQLException { + String value = rs.getString(columnIndex); + return getResult(value); + } + + @Override + public List getResult(CallableStatement cs, int columnIndex) throws SQLException { + String value = cs.getString(columnIndex); + return getResult(value); + } + + private List getResult(String value) { + if (value == null) { + return null; + } + return StrUtils.splitToInteger(value, COMMA); + } +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java index b245ec860..5b3a84284 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java @@ -74,7 +74,7 @@ public class DeliveryExpressController { return success(DeliveryExpressConvert.INSTANCE.convertPage(pageResult)); } - // TODO @jason:运费模版,可以去掉哈,没啥用; + // TODO @jason:运费模版,@芋艿 你的意思是运费模板导出没有必要吧。已经去掉了。这个是快递公司导出 @GetMapping("/export-excel") @Operation(summary = "导出快递公司 Excel") @PreAuthorize("@ss.hasPermission('trade:delivery:express:export')") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressTemplateController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressTemplateController.java index 9ea4c4d1b..3471b2233 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressTemplateController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressTemplateController.java @@ -84,17 +84,4 @@ public class DeliveryExpressTemplateController { PageResult pageResult = deliveryExpressTemplateService.getDeliveryExpressTemplatePage(pageVO); return success(DeliveryExpressTemplateConvert.INSTANCE.convertPage(pageResult)); } - - @GetMapping("/export-excel") - @Operation(summary = "导出快递运费模板 Excel") - @PreAuthorize("@ss.hasPermission('trade:delivery:express-template:export')") - @OperateLog(type = EXPORT) - public void exportDeliveryExpressTemplateExcel(@Valid DeliveryExpressTemplateExportReqVO exportReqVO, - HttpServletResponse response) throws IOException { - List list = deliveryExpressTemplateService.getDeliveryExpressTemplateList(exportReqVO); - // 导出 Excel - List datas = DeliveryExpressTemplateConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "快递运费模板.xls", "数据", DeliveryExpressTemplateExcelVO.class, datas); - } - } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExcelVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExcelVO.java index 45d92aa43..4df6c0d7d 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExcelVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExcelVO.java @@ -1,5 +1,8 @@ package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @@ -7,8 +10,6 @@ import java.time.LocalDateTime; /** * 快递公司 Excel VO - * - * @author jason */ @Data public class DeliveryExpressExcelVO { @@ -28,9 +29,9 @@ public class DeliveryExpressExcelVO { @ExcelProperty("排序") private Integer sort; - @ExcelProperty("状态") - // TODO @jason:可以使用 @DictFormat(DictTypeConstants.COMMON_STATUS) - private Byte status; + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; @ExcelProperty("创建时间") private LocalDateTime createTime; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateExcelVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateExcelVO.java deleted file mode 100644 index 60ae499f0..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateExcelVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; - -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 快递运费模板 Excel VO - * - * @author jason - */ -@Data -public class DeliveryExpressTemplateExcelVO { - - @ExcelProperty("编号,自增") - private Long id; - - @ExcelProperty("模板名称") - private String name; - - @ExcelProperty("配送计费方式 1:按件 2:按重量 3:按体积") - private Integer chargeMode; - - @ExcelProperty("排序") - private Integer sort; - - @ExcelProperty("创建时间") - private LocalDateTime createTime; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateExportReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateExportReqVO.java deleted file mode 100644 index c02133165..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateExportReqVO.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; - -import lombok.*; -import java.util.*; -import io.swagger.v3.oas.annotations.media.Schema; -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import java.time.LocalDateTime; -import org.springframework.format.annotation.DateTimeFormat; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 快递运费模板 Excel 导出 Request VO,参数和 DeliveryExpressTemplatePageReqVO 是一致的") -@Data -public class DeliveryExpressTemplateExportReqVO { - - @Schema(description = "模板名称", example = "王五") - private String name; - - @Schema(description = "配送计费方式 1:按件 2:按重量 3:按体积") - private Integer chargeMode; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateChargeBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateChargeBaseVO.java index 5da76845e..8bd2617b7 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateChargeBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateChargeBaseVO.java @@ -3,19 +3,19 @@ package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; +import java.util.List; /** * 快递运费模板运费设置 Base VO,提供给添加运费模板使用 - * - * @author jason */ @Data public class ExpressTemplateChargeBaseVO { - @Schema(description = "区域编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "区域编号不能为空") - private Integer areaId; + @Schema(description = "区域编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,120000]") + @NotEmpty(message = "区域编号列表不能为空") + private List areaIds; @Schema(description = "首件数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") @NotNull(message = "首件数量不能为空") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateChargeUpdateVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateChargeUpdateVO.java index a0fb2315c..995ea4a18 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateChargeUpdateVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateChargeUpdateVO.java @@ -3,9 +3,7 @@ package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -/** - * @author jason - */ + @Data public class ExpressTemplateChargeUpdateVO extends ExpressTemplateChargeBaseVO { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateFreeBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateFreeBaseVO.java index ff6dbbcaa..7523b0f53 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateFreeBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateFreeBaseVO.java @@ -3,19 +3,19 @@ package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; +import java.util.List; /** * 快递运费模板包邮 Base VO,提供给添加运费模板使用 - * - * @author jason */ @Data public class ExpressTemplateFreeBaseVO { - @Schema(description = "区域编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "区域编号不能为空") - private Integer areaId; + @Schema(description = "区域编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,120000]") + @NotEmpty(message = "区域编号列表不能为空") + private List areaIds; @Schema(description = "包邮金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "5000") @NotNull(message = "包邮金额不能为空") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateFreeUpdateVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateFreeUpdateVO.java index 56485b579..e0c7e47b0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateFreeUpdateVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateFreeUpdateVO.java @@ -5,8 +5,6 @@ import lombok.Data; /** * 快递运费模板包邮 更新 VO - * - * @author jason */ @Data public class ExpressTemplateFreeUpdateVO extends ExpressTemplateFreeBaseVO { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressConvert.java index 768530ace..e896962a2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressConvert.java @@ -16,7 +16,7 @@ import org.mapstruct.factory.Mappers; /** * 快递公司 Convert * - * @author 芋道源码 + * @author jason */ @Mapper public interface DeliveryExpressConvert { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java index d4d23cb0a..7e2a51cc1 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.trade.convert.delivery; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.*; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; @@ -16,7 +17,7 @@ import java.util.List; /** * 快递运费模板 Convert * - * @author 芋道源码 + * @author jason */ @Mapper public interface DeliveryExpressTemplateConvert { @@ -37,8 +38,6 @@ public interface DeliveryExpressTemplateConvert { PageResult convertPage(PageResult page); - List convertList02(List list); - default DeliveryExpressTemplateRespVO convert(DeliveryExpressTemplateDO bean, List chargeList, List freeList){ @@ -55,15 +54,7 @@ public interface DeliveryExpressTemplateConvert { DeliveryExpressTemplateChargeDO convertTemplateCharge(ExpressTemplateChargeUpdateVO vo); default List convertTemplateChargeList(Long templateId, Integer chargeMode, List list) { - // TODO @jason:可以使用 CollectionUtils.convertList,本质上就是 stream convert list - if(CollUtil.isEmpty(list)){ - return Collections.emptyList(); - } - List templateChargeList = new ArrayList<>(list.size()); - for (ExpressTemplateChargeBaseVO item : list) { - templateChargeList.add(convertTemplateCharge(templateId, chargeMode, item)); - } - return templateChargeList; + return CollectionUtils.convertList(list, vo -> convertTemplateCharge(templateId, chargeMode, vo)); } // ========== Template Free ========== @@ -76,17 +67,8 @@ public interface DeliveryExpressTemplateConvert { List convertTemplateFreeList(List list); - // TODO @jason:, List,中间一个空格哈。代码的空格和空行要注意,嘿嘿~ - default List convertTemplateFreeList(Long templateId, List list) { - // TODO @jason:可以使用 CollectionUtils.convertList,本质上就是 stream convert list - if (CollUtil.isEmpty(list)) { - return Collections.emptyList(); - } - List templateFreeList = new ArrayList<>(list.size()); - for (ExpressTemplateFreeBaseVO item : list) { - templateFreeList.add(convertTemplateFree(templateId, item)); - } - return templateFreeList; + default List convertTemplateFreeList(Long templateId, List list) { + return CollectionUtils.convertList(list, vo -> convertTemplateFree(templateId, vo)); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/delivery/DeliveryExpressTemplateChargeDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/delivery/DeliveryExpressTemplateChargeDO.java index 803576503..c3bb30e9a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/delivery/DeliveryExpressTemplateChargeDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/delivery/DeliveryExpressTemplateChargeDO.java @@ -1,17 +1,21 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.delivery; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.type.IntegerListTypeHandler; import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; +import java.util.List; + /** * 快递运费模板计费配置 DO * * @author jason */ -@TableName(value ="trade_delivery_express_template_charge") +@TableName(value ="trade_delivery_express_template_charge", autoResultMap = true) @KeySequence("trade_delivery_express_template_charge_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data public class DeliveryExpressTemplateChargeDO extends BaseDO { @@ -30,9 +34,10 @@ public class DeliveryExpressTemplateChargeDO extends BaseDO { private Long templateId; /** - * 配送区域 + * 配送区域编号列表 */ - private Integer areaId; + @TableField(typeHandler = IntegerListTypeHandler.class) + private List areaIds; /** * 配送计费方式 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/delivery/DeliveryExpressTemplateFreeDO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/delivery/DeliveryExpressTemplateFreeDO.java index 351a1dd24..07eef1be2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/delivery/DeliveryExpressTemplateFreeDO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/delivery/DeliveryExpressTemplateFreeDO.java @@ -1,17 +1,21 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.delivery; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.type.IntegerListTypeHandler; import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; +import java.util.List; + /** * 快递运费模板包邮配置 DO * * @author jason */ -@TableName(value ="trade_delivery_express_template_free") +@TableName(value ="trade_delivery_express_template_free", autoResultMap = true) @KeySequence("trade_delivery_express_template_free_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data public class DeliveryExpressTemplateFreeDO extends BaseDO { @@ -29,10 +33,12 @@ public class DeliveryExpressTemplateFreeDO extends BaseDO { */ private Long templateId; + /** - * 包邮区域id + * 配送区域编号列表 */ - private Integer areaId; + @TableField(typeHandler = IntegerListTypeHandler.class) + private List areaIds; /** * 包邮金额,单位:分 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateChargeMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateChargeMapper.java index ed0314018..dc96b24f2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateChargeMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateChargeMapper.java @@ -14,10 +14,6 @@ import java.util.List; @Mapper public interface DeliveryExpressTemplateChargeMapper extends BaseMapperX { - @Repository - class BatchInsertMapper extends ServiceImpl { - } - default List selectListByTemplateId(Long templateId){ return selectList(new LambdaQueryWrapper() .eq(DeliveryExpressTemplateChargeDO::getTemplateId, templateId)); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateFreeMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateFreeMapper.java index 97a4d31d3..58caaf9af 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateFreeMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateFreeMapper.java @@ -14,10 +14,6 @@ import java.util.List; @Mapper public interface DeliveryExpressTemplateFreeMapper extends BaseMapperX { - @Repository - class BatchInsertMapper extends ServiceImpl { - } - default List selectListByTemplateId(Long templateId) { return selectList(new LambdaQueryWrapper() .eq(DeliveryExpressTemplateFreeDO::getTemplateId, templateId)); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateMapper.java index 85b52851e..734298042 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateMapper.java @@ -4,14 +4,10 @@ package cn.iocoder.yudao.module.trade.dal.mysql.delivery; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressTemplateExportReqVO; import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressTemplatePageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; -import java.util.List; - @Mapper public interface DeliveryExpressTemplateMapper extends BaseMapperX { @@ -23,18 +19,8 @@ public interface DeliveryExpressTemplateMapper extends BaseMapperX selectList(DeliveryExpressTemplateExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(DeliveryExpressTemplateDO::getName, reqVO.getName()) - .eqIfPresent(DeliveryExpressTemplateDO::getChargeMode, reqVO.getChargeMode()) - .betweenIfPresent(DeliveryExpressTemplateDO::getCreateTime, reqVO.getCreateTime()) - .orderByAsc(DeliveryExpressTemplateDO::getSort)); - } - - // TODO @jason:可以用 selectOne(DeliveryExpressTemplateDO::getName, name),常用的我封装了哈。简洁一点~ default DeliveryExpressTemplateDO selectByName(String name) { - return selectOne(new LambdaQueryWrapper() - .eq(DeliveryExpressTemplateDO::getName, name)); + return selectOne(DeliveryExpressTemplateDO::getName,name); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateService.java index 30cb85b75..71721fec2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateService.java @@ -58,13 +58,4 @@ public interface DeliveryExpressTemplateService { * @return 快递运费模板分页 */ PageResult getDeliveryExpressTemplatePage(DeliveryExpressTemplatePageReqVO pageReqVO); - - /** - * 获得快递运费模板列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 快递运费模板列表 - */ - List getDeliveryExpressTemplateList(DeliveryExpressTemplateExportReqVO exportReqVO); - } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateServiceImpl.java index 76182eed7..2bda89a91 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateServiceImpl.java @@ -36,32 +36,24 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla private DeliveryExpressTemplateChargeMapper expressTemplateChargeMapper; @Resource private DeliveryExpressTemplateFreeMapper expressTemplateFreeMapper; - // TODO @jason:应该不用 BatchInsertMapper 拉,直接走 expressTemplateChargeMapper.insertBatch - @Resource - private DeliveryExpressTemplateChargeMapper.BatchInsertMapper expressTemplateChargeBatchMapper; - @Resource - private DeliveryExpressTemplateFreeMapper.BatchInsertMapper expressTemplateFreeBatchMapper; @Override @Transactional(rollbackFor = Exception.class) public Long createDeliveryExpressTemplate(DeliveryExpressTemplateCreateReqVO createReqVO) { - // TODO @jason:中英文之间,要有空格哈。例如说, // 校验模板名是否唯一 - //校验模板名是否唯一 + // 校验模板名是否唯一 validateTemplateNameUnique(createReqVO.getName(), null); - // 插入 DeliveryExpressTemplateDO deliveryExpressTemplate = INSTANCE.convert(createReqVO); expressTemplateMapper.insert(deliveryExpressTemplate); - //插入运费模板计费表 - // TODO @jason:if (,中间要有空格 - if(CollUtil.isNotEmpty(createReqVO.getTemplateCharge())) { - expressTemplateChargeBatchMapper.saveBatch( - INSTANCE.convertTemplateChargeList(deliveryExpressTemplate.getId(), createReqVO.getChargeMode(), createReqVO.getTemplateCharge()) + // 插入运费模板计费表 + if (CollUtil.isNotEmpty(createReqVO.getTemplateCharge())) { + expressTemplateChargeMapper.insertBatch( + INSTANCE.convertTemplateChargeList(deliveryExpressTemplate.getId(), createReqVO.getChargeMode(), createReqVO.getTemplateCharge()) ); } - //插入运费模板包邮表 - if(CollUtil.isNotEmpty(createReqVO.getTemplateFree())) { - expressTemplateFreeBatchMapper.saveBatch( + // 插入运费模板包邮表 + if (CollUtil.isNotEmpty(createReqVO.getTemplateFree())) { + expressTemplateFreeMapper.insertBatch( INSTANCE.convertTemplateFreeList(deliveryExpressTemplate.getId(), createReqVO.getTemplateFree()) ); } @@ -73,14 +65,13 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla public void updateDeliveryExpressTemplate(DeliveryExpressTemplateUpdateReqVO updateReqVO) { // 校验存在 validateDeliveryExpressTemplateExists(updateReqVO.getId()); - //校验模板名是否唯一 + // 校验模板名是否唯一 validateTemplateNameUnique(updateReqVO.getName(), updateReqVO.getId()); - - //更新运费从表 + // 更新运费从表 updateExpressTemplateCharge(updateReqVO); - //更新包邮从表 + // 更新包邮从表 updateExpressTemplateFree(updateReqVO); - //更新模板主表 + // 更新模板主表 DeliveryExpressTemplateDO updateObj = INSTANCE.convert(updateReqVO); expressTemplateMapper.updateById(updateObj); } @@ -88,29 +79,29 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla private void updateExpressTemplateFree(DeliveryExpressTemplateUpdateReqVO updateReqVO) { List oldFreeList = expressTemplateFreeMapper.selectListByTemplateId(updateReqVO.getId()); List newFreeList = updateReqVO.getTemplateFree(); - //新增包邮区域列表 + // 新增包邮区域列表 List addFreeList = new ArrayList<>(newFreeList.size()); - //更新包邮区域列表 + // 更新包邮区域列表 List updateFreeList = new ArrayList<>(newFreeList.size()); for (ExpressTemplateFreeUpdateVO item : newFreeList) { if (Objects.nonNull(item.getId())) { updateFreeList.add(INSTANCE.convertTemplateFree(item)); - }else{ + } else { item.setTemplateId(updateReqVO.getId()); addFreeList.add(INSTANCE.convertTemplateFree(item)); } } - //删除的包邮区域id + // 新增 + if (CollUtil.isNotEmpty(addFreeList)) { + expressTemplateFreeMapper.insertBatch(addFreeList); + } + // 修改 + if (CollUtil.isNotEmpty(updateFreeList)) { + expressTemplateFreeMapper.updateBatch(updateFreeList); + } + // 得到删除ids Set deleteFreeIds = CollectionUtils.convertSet(oldFreeList, DeliveryExpressTemplateFreeDO::getId); deleteFreeIds.removeAll(CollectionUtils.convertSet(updateFreeList, DeliveryExpressTemplateFreeDO::getId)); - //新增 - if (CollUtil.isNotEmpty(addFreeList)) { - expressTemplateFreeBatchMapper.saveBatch(addFreeList); - } - //修改 - if (CollUtil.isNotEmpty(updateFreeList)) { - expressTemplateFreeBatchMapper.saveOrUpdateBatch(updateFreeList); - } //删除 if (CollUtil.isNotEmpty(deleteFreeIds)) { expressTemplateFreeMapper.deleteBatchIds(deleteFreeIds); @@ -120,33 +111,33 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla private void updateExpressTemplateCharge(DeliveryExpressTemplateUpdateReqVO updateReqVO) { List oldChargeList = expressTemplateChargeMapper.selectListByTemplateId(updateReqVO.getId()); List newChargeList = updateReqVO.getTemplateCharge(); - //新增运费区域列表 + // 新增运费区域列表 List addList = new ArrayList<>(newChargeList.size()); - //更新运费区域列表 + // 更新运费区域列表 List updateList = new ArrayList<>(newChargeList.size()); for (ExpressTemplateChargeUpdateVO item : newChargeList) { - if (Objects.nonNull(item.getId())) { // TODO @jason:null 的判断,还是用 item.getId() != null 好一点。一般数组用方法,主要考虑 null + length = 0; - //计费模式以主表为准 + if (item.getId() != null) { + // 计费模式以主表为准 item.setChargeMode(updateReqVO.getChargeMode()); updateList.add(INSTANCE.convertTemplateCharge(item)); - }else{ + } else { item.setTemplateId(updateReqVO.getId()); item.setChargeMode(updateReqVO.getChargeMode()); addList.add(INSTANCE.convertTemplateCharge(item)); } } - //删除的运费区域id TODO @jason:这块放到删除部分的那块逻辑会好点(149 - 152 行),主要变量要贴相应的逻辑近一点哈。 + // 新增 + if (CollUtil.isNotEmpty(addList)) { + expressTemplateChargeMapper.insertBatch(addList); + } + // 修改 + if (CollUtil.isNotEmpty(updateList)) { + expressTemplateChargeMapper.updateBatch(updateList); + } + // 得到删除的ids Set deleteChargeIds = CollectionUtils.convertSet(oldChargeList, DeliveryExpressTemplateChargeDO::getId); deleteChargeIds.removeAll(CollectionUtils.convertSet(updateList, DeliveryExpressTemplateChargeDO::getId)); - //新增 - if (CollUtil.isNotEmpty(addList)) { - expressTemplateChargeBatchMapper.saveBatch(addList); - } - //修改 - if (CollUtil.isNotEmpty(updateList)) { - expressTemplateChargeBatchMapper.saveOrUpdateBatch(updateList); - } - //删除 + // 删除 if (CollUtil.isNotEmpty(deleteChargeIds)) { expressTemplateChargeMapper.deleteBatchIds(deleteChargeIds); } @@ -157,7 +148,6 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla public void deleteDeliveryExpressTemplate(Long id) { // 校验存在 validateDeliveryExpressTemplateExists(id); - // 删除主表 expressTemplateMapper.deleteById(id); // 删除运费从表 @@ -167,9 +157,10 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla } /** - * 校验运费模板名是否唯一 // TODO @jason:方法注释,和参数,要空一行。 + * 校验运费模板名是否唯一 + * * @param name 模板名称 - * @param id 运费模板编号, 可以为null // TODO @jason:中英文之间,要空一行;其它地方也看看哈 + * @param id 运费模板编号,可以为 null */ private void validateTemplateNameUnique(String name, Long id) { DeliveryExpressTemplateDO template = expressTemplateMapper.selectByName(name); @@ -196,7 +187,7 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla List chargeList = expressTemplateChargeMapper.selectListByTemplateId(id); List freeList = expressTemplateFreeMapper.selectListByTemplateId(id); DeliveryExpressTemplateDO template = expressTemplateMapper.selectById(id); - return INSTANCE.convert(template, chargeList,freeList); + return INSTANCE.convert(template, chargeList, freeList); } @Override @@ -208,10 +199,4 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla public PageResult getDeliveryExpressTemplatePage(DeliveryExpressTemplatePageReqVO pageReqVO) { return expressTemplateMapper.selectPage(pageReqVO); } - - @Override - public List getDeliveryExpressTemplateList(DeliveryExpressTemplateExportReqVO exportReqVO) { - return expressTemplateMapper.selectList(exportReqVO); - } - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java index 0988cbe90..b3bc0c03c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/AreaController.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.ip.core.Area; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.framework.ip.core.utils.IPUtils; import cn.iocoder.yudao.module.system.controller.admin.ip.vo.AreaNodeRespVO; -import cn.iocoder.yudao.module.system.controller.admin.ip.vo.LazyAreaNodeRespVO; +import cn.iocoder.yudao.module.system.controller.admin.ip.vo.AreaNodeSimpleRespVO; import cn.iocoder.yudao.module.system.convert.ip.AreaConvert; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -34,23 +34,23 @@ public class AreaController { return success(AreaConvert.INSTANCE.convertList(area.getChildren())); } - // TODO @jason:1)url 使用中划线分隔哈,然后可以改成 children;2)id 需要添加 @RequestParam,因为可能会混淆编译; - // 3) swagger 注解要写下哈; - @GetMapping("/getChildrenArea") + @GetMapping("/get-children") @Operation(summary = "获得地区的下级区域") - public CommonResult> getChildrenArea(Integer id) { + @Parameter(name = "id", description = "区域编号", required = true, example = "150000") + public CommonResult> getChildren(@RequestParam("id") Integer id) { Area area = AreaUtils.getArea(id); - Assert.notNull(area, String.format("获取不到 id : %d的区域", id)); + Assert.notNull(area, String.format("获取不到 id : %d 的区域", id)); return success(AreaConvert.INSTANCE.convertList2(area.getChildren())); } - // TODO @jason:1)读请求,使用 get 哈。2)然后参数不应该使用 @RequestBody;3)areaIds 改成 ids 更合适; // 4)方法改成 getAreaChildrenList 获得子节点们;5)url 可以已改成 children-list - @PostMapping("/list") + //@芋艿 是不是叫 getAreaListByIds 更合适。 因为不一定是子节点。 用于前端树选择获取缓存数据。 见 + @GetMapping("/get-by-ids") @Operation(summary = "通过区域 ids 获得地区列表") - public CommonResult> list(@RequestBody Set areaIds) { - List areaList = new ArrayList<>(areaIds.size()); - for (Integer areaId : areaIds) { + @Parameter(name = "ids", description = "区域编号 ids", required = true, example = "1,150000") + public CommonResult> getAreaListByIds(@RequestParam("ids") Set ids) { + List areaList = new ArrayList<>(ids.size()); + for (Integer areaId : ids) { areaList.add(AreaUtils.getArea(areaId)); } return success(AreaConvert.INSTANCE.convertList2(areaList)); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeSimpleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeSimpleRespVO.java new file mode 100644 index 000000000..a37430248 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeSimpleRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.system.controller.admin.ip.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 简洁的地区节点 Response VO") +@Data +public class AreaNodeSimpleRespVO { + + @Schema(description = "编号", required = true, example = "110000") + private Integer id; + + @Schema(description = "名字", required = true, example = "北京") + private String name; + + @Schema(description = "是否叶子节点", required = false, example = "false") + private Boolean leaf; + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/LazyAreaNodeRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/LazyAreaNodeRespVO.java deleted file mode 100644 index e95defb1c..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/LazyAreaNodeRespVO.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.ip.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -// TODO @jason:1)VO 不添加注释作者哈。2)是不是改成 AreaNodeSimpleRespVO,它其实是返回一个简洁的地区,懒加载只是它的使用场景; -/** - * @author jason - */ -@Schema(description = "管理后台 - 懒加载地区节点 Response VO") -@Data -public class LazyAreaNodeRespVO { - - @Schema(description = "编号", required = true, example = "110000") - private Integer id; - - @Schema(description = "名字", required = true, example = "北京") - private String name; - - // TODO @jason:1)不设置默认值,交给业务逻辑那写入;2)这个字段必须返回哇? - @Schema(description = "是否叶子节点", required = true, example = "false") - private Boolean leaf = Boolean.FALSE; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/ip/AreaConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/ip/AreaConvert.java index 540272e12..05d193717 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/ip/AreaConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/ip/AreaConvert.java @@ -3,12 +3,10 @@ package cn.iocoder.yudao.module.system.convert.ip; import cn.iocoder.yudao.framework.ip.core.Area; import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; import cn.iocoder.yudao.module.system.controller.admin.ip.vo.AreaNodeRespVO; -import cn.iocoder.yudao.module.system.controller.admin.ip.vo.LazyAreaNodeRespVO; +import cn.iocoder.yudao.module.system.controller.admin.ip.vo.AreaNodeSimpleRespVO; import org.mapstruct.Mapper; import org.mapstruct.Mapping; -import org.mapstruct.Named; import org.mapstruct.factory.Mappers; -import org.springframework.context.annotation.Lazy; import java.util.List; import java.util.Objects; @@ -20,10 +18,10 @@ public interface AreaConvert { List convertList(List list); - List convertList2(List list); + List convertList2(List list); @Mapping(source = "type", target = "leaf") - LazyAreaNodeRespVO convert(Area area); + AreaNodeSimpleRespVO convert(Area area); default Boolean convertAreaType(Integer type){ return Objects.equals(AreaTypeEnum.DISTRICT.getType(),type); From 6a9146ff8de5e7e1156d3ea3eaf02905b71636bd Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 28 May 2023 20:09:51 +0800 Subject: [PATCH 5/6] =?UTF-8?q?mall=20+=20trade=EF=BC=9A=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E4=BB=B7=E6=A0=BC=E8=AE=A1=E7=AE=97=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../promotion/api/coupon/CouponApi.java | 10 + .../api/coupon/dto/CouponRespDTO.java | 109 ++++ .../api/coupon/dto/CouponValidReqDTO.java | 27 + .../api/discount/DiscountActivityApi.java | 23 + .../discount/dto/DiscountProductRespDTO.java} | 18 +- .../module/promotion/api/package-info.java | 4 - .../api/price/dto/PriceCalculateReqDTO.java | 5 + .../api/price/dto/PriceCalculateRespDTO.java | 10 +- .../api/reward/RewardActivityApi.java | 24 + .../dto/RewardActivityMatchRespDTO.java | 77 +++ .../enums/common/PromotionLevelEnum.java | 40 -- .../enums/common/PromotionTypeEnum.java | 3 +- .../promotion/api/coupon/CouponApiImpl.java | 10 + .../api/discount/DiscountActivityApiImpl.java | 28 ++ .../promotion/api/discount/package-info.java | 1 - .../api/reward/RewardActivityApiImpl.java | 27 + .../convert/coupon/CouponConvert.java | 3 + .../discount/DiscountActivityConvert.java | 20 +- .../discount/DiscountActivityDO.java | 7 +- .../discount/DiscountProductDO.java | 3 + .../dataobject/reward/RewardActivityDO.java | 1 + .../discount/DiscountActivityService.java | 4 +- .../discount/DiscountActivityServiceImpl.java | 42 +- .../promotion/service/price/PriceService.java | 9 - .../service/price/PriceServiceImpl.java | 466 +----------------- .../service/reward/RewardActivityService.java | 9 +- .../reward/RewardActivityServiceImpl.java | 37 +- .../service/price/PriceServiceTest.java | 30 +- .../trade/enums/ErrorCodeConstants.java | 4 + .../service/price/TradePriceService.java | 21 + .../service/price/TradePriceServiceImpl.java | 73 +++ .../price/bo/TradePriceCalculateReqBO.java | 86 ++++ .../price/bo/TradePriceCalculateRespBO.java | 249 ++++++++++ .../TradeCouponPriceCalculator.java | 109 ++++ .../TradeDiscountActivityPriceCalculator.java | 80 +++ .../calculator/TradePriceCalculator.java | 19 + .../TradePriceCalculatorHelper.java | 221 +++++++++ .../TradeRewardActivityPriceCalculator.java | 133 +++++ .../app/address/AppAddressController.java | 8 +- .../convert/address/AddressConvert.java | 14 +- .../{AddressDO.java => MemberAddressDO.java} | 2 +- .../dal/mysql/address/AddressMapper.java | 14 +- .../service/address/AddressService.java | 8 +- .../service/address/AddressServiceImpl.java | 24 +- .../address/AddressServiceImplTest.java | 10 +- 45 files changed, 1465 insertions(+), 657 deletions(-) create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponRespDTO.java create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApi.java rename yudao-module-mall/{yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/bo/DiscountProductDetailBO.java => yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java} (72%) delete mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/package-info.java create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/dto/RewardActivityMatchRespDTO.java delete mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionLevelEnum.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java delete mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/package-info.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceService.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculator.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java rename yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/{AddressDO.java => MemberAddressDO.java} (95%) diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java index f99ff815f..ce7a712da 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.promotion.api.coupon; +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; import javax.validation.Valid; @@ -18,4 +20,12 @@ public interface CouponApi { */ void useCoupon(@Valid CouponUseReqDTO useReqDTO); + /** + * 校验优惠劵 + * + * @param validReqDTO 校验请求 + * @return 优惠劵 + */ + CouponRespDTO validateCoupon(@Valid CouponValidReqDTO validReqDTO); + } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponRespDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponRespDTO.java new file mode 100644 index 000000000..34031e604 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponRespDTO.java @@ -0,0 +1,109 @@ +package cn.iocoder.yudao.module.promotion.api.coupon.dto; + +import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 优惠劵 Response DTO + * + * @author 芋道源码 + */ +@Data +public class CouponRespDTO { + + // ========== 基本信息 BEGIN ========== + /** + * 优惠劵编号 + */ + private Long id; + /** + * 优惠劵模板编号 + */ + private Integer templateId; + /** + * 优惠劵名 + */ + private String name; + /** + * 优惠码状态 + * + * 枚举 {@link CouponStatusEnum} + */ + private Integer status; + + // ========== 基本信息 END ========== + + // ========== 领取情况 BEGIN ========== + /** + * 用户编号 + * + * 关联 MemberUserDO 的 id 字段 + */ + private Long userId; + /** + * 领取类型 + * + * 枚举 {@link CouponTakeTypeEnum} + */ + private Integer takeType; + // ========== 领取情况 END ========== + + // ========== 使用规则 BEGIN ========== + /** + * 是否设置满多少金额可用,单位:分 + */ + private Integer usePrice; + /** + * 生效开始时间 + */ + private LocalDateTime validStartTime; + /** + * 生效结束时间 + */ + private LocalDateTime validEndTime; + /** + * 商品范围 + */ + private Integer productScope; + /** + * 商品 SPU 编号的数组 + */ + private List productSpuIds; + // ========== 使用规则 END ========== + + // ========== 使用效果 BEGIN ========== + /** + * 折扣类型 + */ + private Integer discountType; + /** + * 折扣百分比 + */ + private Integer discountPercent; + /** + * 优惠金额,单位:分 + */ + private Integer discountPrice; + /** + * 折扣上限,仅在 {@link #discountType} 等于 {@link PromotionDiscountTypeEnum#PERCENT} 时生效 + */ + private Integer discountLimitPrice; + // ========== 使用效果 END ========== + + // ========== 使用情况 BEGIN ========== + /** + * 使用订单号 + */ + private Long useOrderId; + /** + * 使用时间 + */ + private LocalDateTime useTime; + + // ========== 使用情况 END ========== +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java new file mode 100644 index 000000000..dd25c6408 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.promotion.api.coupon.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 优惠劵使用 Request DTO + * + * @author 芋道源码 + */ +@Data +public class CouponValidReqDTO { + + /** + * 优惠劵编号 + */ + @NotNull(message = "优惠劵编号不能为空") + private Long id; + + /** + * 用户编号 + */ + @NotNull(message = "用户编号不能为空") + private Long userId; + +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApi.java new file mode 100644 index 000000000..b25f67d9f --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApi.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.promotion.api.discount; + +import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; + +import java.util.Collection; +import java.util.List; + +/** + * 限时折扣 API 接口 + * + * @author 芋道源码 + */ +public interface DiscountActivityApi { + + /** + * 获得商品匹配的的限时折扣信息 + * + * @param skuIds 商品 SKU 编号数组 + * @return 限时折扣信息 + */ + List getMatchDiscountProductList(Collection skuIds); + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/bo/DiscountProductDetailBO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java similarity index 72% rename from yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/bo/DiscountProductDetailBO.java rename to yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java index 7b8f4a20f..52dfdbe27 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/bo/DiscountProductDetailBO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java @@ -1,25 +1,19 @@ -package cn.iocoder.yudao.module.promotion.service.discount.bo; +package cn.iocoder.yudao.module.promotion.api.discount.dto; import lombok.Data; /** - * 限时折扣活动商品 BO + * 限时折扣活动商品 Response DTO * * @author 芋道源码 */ @Data -public class DiscountProductDetailBO { - - // ========== DiscountProductDO 字段 ========== +public class DiscountProductRespDTO { /** * 编号,主键自增 */ private Long id; - /** - * 限时折扣活动的编号 - */ - private Long activityId; /** * 商品 SPU 编号 */ @@ -41,7 +35,11 @@ public class DiscountProductDetailBO { */ private Integer discountPrice; - // ========== DiscountActivityDO 字段 ========== + // ========== 活动字段 ========== + /** + * 限时折扣活动的编号 + */ + private Long activityId; /** * 活动标题 */ diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/package-info.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/package-info.java deleted file mode 100644 index 08e1020a6..000000000 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 占位 - */ -package cn.iocoder.yudao.module.promotion.api; diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateReqDTO.java index 01f0ac220..ce53de50e 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateReqDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateReqDTO.java @@ -26,6 +26,11 @@ public class PriceCalculateReqDTO { */ private Long couponId; + /** + * 收货地址编号 + */ + private Long addressId; + /** * 商品 SKU 数组 */ diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateRespDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateRespDTO.java index a067aa0b5..9a98029b7 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateRespDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateRespDTO.java @@ -24,6 +24,7 @@ import java.util.List; * @author 芋道源码 */ @Data +@Deprecated public class PriceCalculateRespDTO { /** @@ -174,6 +175,7 @@ public class PriceCalculateRespDTO { * 营销明细 */ @Data + @Deprecated public static class Promotion { /** @@ -216,14 +218,14 @@ public class PriceCalculateRespDTO { /** * 是否满足优惠条件 */ - private Boolean meet; + private Boolean match; /** * 满足条件的提示 * - * 如果 {@link #meet} = true 满足,则提示“圣诞价:省 150.00 元” - * 如果 {@link #meet} = false 不满足,则提示“购满 85 元,可减 40 元” + * 如果 {@link #match} = true 满足,则提示“圣诞价:省 150.00 元” + * 如果 {@link #match} = false 不满足,则提示“购满 85 元,可减 40 元” */ - private String meetTip; + private String description; } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java new file mode 100644 index 000000000..efeddf3d5 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.promotion.api.reward; + +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; + +import java.util.Collection; +import java.util.List; + +/** + * 满减送活动 API 接口 + * + * @author 芋道源码 + */ +public interface RewardActivityApi { + + + /** + * 基于指定的 SPU 编号数组,获得它们匹配的满减送活动 + * + * @param spuIds SPU 编号数组 + * @return 满减送活动列表 + */ + List getMatchRewardActivityList(Collection spuIds); + +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/dto/RewardActivityMatchRespDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/dto/RewardActivityMatchRespDTO.java new file mode 100644 index 000000000..19f46a49a --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/dto/RewardActivityMatchRespDTO.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.promotion.api.reward.dto; + +import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum; +import lombok.Data; + +import java.util.List; + +/** + * 满减送活动的匹配 Response DTO + * + * @author 芋道源码 + */ +@Data +public class RewardActivityMatchRespDTO { + + /** + * 活动编号,主键自增 + */ + private Long id; + /** + * 活动标题 + */ + private String name; + /** + * 条件类型 + * + * 枚举 {@link PromotionConditionTypeEnum} + */ + private Integer conditionType; + /** + * 优惠规则的数组 + */ + private List rules; + + /** + * 商品 SPU 编号的数组 + */ + private List spuIds; + + // TODO 芋艿:后面 RewardActivityRespDTO 有了之后,Rule 可以放过去 + /** + * 优惠规则 + */ + @Data + public static class Rule { + + /** + * 优惠门槛 + * + * 1. 满 N 元,单位:分 + * 2. 满 N 件 + */ + private Integer limit; + /** + * 优惠价格,单位:分 + */ + private Integer discountPrice; + /** + * 是否包邮 + */ + private Boolean freeDelivery; + /** + * 赠送的积分 + */ + private Integer point; + /** + * 赠送的优惠劵编号的数组 + */ + private List couponIds; + /** + * 赠送的优惠卷数量的数组 + */ + private List couponCounts; + + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionLevelEnum.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionLevelEnum.java deleted file mode 100644 index ed0564a70..000000000 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionLevelEnum.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.yudao.module.promotion.enums.common; - -import cn.iocoder.yudao.framework.common.core.IntArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * 营销的级别枚举 - * - * 参考有赞:营销级别 - * - * @author 芋道源码 - */ -@Getter -@AllArgsConstructor -public enum PromotionLevelEnum implements IntArrayValuable { - - ORDER(1, "订单级"), // 多个商品,进行组合后优惠。例如说:满减送、打包一口价、第二件半价 - SKU(2, "商品级"), // 单个商品,直接优惠。例如说:限时折扣、会员折扣 - COUPON(3, "优惠劵"), // 多个商品,进行组合后优惠。例如说:优惠劵 - ; - - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionLevelEnum::getLevel).toArray(); - - /** - * 级别值 - */ - private final Integer level; - /** - * 类型名 - */ - private final String name; - - @Override - public int[] array() { - return ARRAYS; - } -} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionTypeEnum.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionTypeEnum.java index eea48f7dc..ee87306bf 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionTypeEnum.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionTypeEnum.java @@ -18,7 +18,7 @@ public enum PromotionTypeEnum implements IntArrayValuable { DISCOUNT_ACTIVITY(1, "限时折扣"), REWARD_ACTIVITY(2, "满减送"), - MEMBER(3, "会员折扣"), + MEMBER(3, "会员折扣"), // TODO 芋艿:待实现 StrUtil.format("会员折扣:省 {} 元", formatPrice(orderItem.getPayPrice() - memberPrice) COUPON(4, "优惠劵") ; @@ -37,4 +37,5 @@ public enum PromotionTypeEnum implements IntArrayValuable { public int[] array() { return ARRAYS; } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java index 349eba1ff..a06ab57cd 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java @@ -1,7 +1,11 @@ package cn.iocoder.yudao.module.promotion.api.coupon; +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; +import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; import org.springframework.stereotype.Service; @@ -24,4 +28,10 @@ public class CouponApiImpl implements CouponApi { useReqDTO.getOrderId()); } + @Override + public CouponRespDTO validateCoupon(CouponValidReqDTO validReqDTO) { + CouponDO coupon = couponService.validCoupon(validReqDTO.getId(), validReqDTO.getUserId()); + return CouponConvert.INSTANCE.convert(coupon); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java new file mode 100644 index 000000000..2227da43e --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.promotion.api.discount; + +import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; +import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert; +import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; + +/** + * 限时折扣 API 实现类 + * + * @author 芋道源码 + */ +@Service +public class DiscountActivityApiImpl implements DiscountActivityApi { + + @Resource + private DiscountActivityService discountActivityService; + + @Override + public List getMatchDiscountProductList(Collection skuIds) { + return DiscountActivityConvert.INSTANCE.convertList02(discountActivityService.getMatchDiscountProductList(skuIds)); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/package-info.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/package-info.java deleted file mode 100644 index 4e3ce77a8..000000000 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.promotion.api.discount; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java new file mode 100644 index 000000000..ee8bac7c9 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.promotion.api.reward; + +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; +import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; + +/** + * 满减送活动 API 实现类 + * + * @author 芋道源码 + */ +@Service +public class RewardActivityApiImpl implements RewardActivityApi { + + @Resource + private RewardActivityService rewardActivityService; + + @Override + public List getMatchRewardActivityList(Collection spuIds) { + return rewardActivityService.getMatchRewardActivityList(spuIds); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java index 281318f7d..7bfdca706 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.promotion.convert.coupon; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageItemRespVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; import org.mapstruct.Mapper; @@ -18,4 +19,6 @@ public interface CouponConvert { PageResult convertPage(PageResult page); + CouponRespDTO convert(CouponDO bean); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java index 07d2e03ab..ebf53ce8a 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java @@ -2,18 +2,15 @@ package cn.iocoder.yudao.module.promotion.convert.discount; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.*; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; -import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; import java.util.List; -import java.util.Map; /** * 限时折扣活动 Convert @@ -33,20 +30,10 @@ public interface DiscountActivityConvert { List convertList(List list); + List convertList02(List list); + PageResult convertPage(PageResult page); - DiscountProductDetailBO convert(DiscountProductDO product); - - default List convertList(List products, Map activityMap) { - return CollectionUtils.convertList(products, product -> { - DiscountProductDetailBO detail = convert(product); - MapUtils.findAndThen(activityMap, product.getActivityId(), activity -> { - detail.setActivityName(activity.getName()); - }); - return detail; - }); - } - DiscountProductDO convert(DiscountActivityBaseVO.Product bean); DiscountActivityDetailRespVO convert(DiscountActivityDO activity, List products); @@ -99,4 +86,5 @@ public interface DiscountActivityConvert { return true; } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountActivityDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountActivityDO.java index 91071f309..fd0726e39 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountActivityDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountActivityDO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.promotion.dal.dataobject.discount; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -33,10 +33,13 @@ public class DiscountActivityDO extends BaseDO { * 活动标题 */ private String name; + // TODO 芋艿:状态调整,只有开启和关闭; /** * 状态 * - * 枚举 {@link PromotionActivityStatusEnum} + * 枚举 {@link CommonStatusEnum} + * + * 活动被关闭后,不允许再次开启。 */ private Integer status; /** diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java index 55c924e4f..7f61f7f6d 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java @@ -24,12 +24,15 @@ public class DiscountProductDO extends BaseDO { */ @TableId private Long id; + + // TODO 芋艿:把 activity 所有的字段冗余过来 /** * 限时折扣活动的编号 * * 关联 {@link DiscountActivityDO#getId()} */ private Long activityId; + /** * 商品 SPU 编号 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/reward/RewardActivityDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/reward/RewardActivityDO.java index e825881d1..9d417d75f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/reward/RewardActivityDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/reward/RewardActivityDO.java @@ -38,6 +38,7 @@ public class RewardActivityDO extends BaseDO { * 活动标题 */ private String name; + // TODO @芋艿:改成开启、禁用两种状态 /** * 状态 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java index 8b6e5895b..7473f12cd 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java @@ -6,12 +6,10 @@ import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountAc import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; -import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO; import javax.validation.Valid; import java.util.Collection; import java.util.List; -import java.util.Map; /** * 限时折扣 Service 接口 @@ -28,7 +26,7 @@ public interface DiscountActivityService { * @param skuIds SKU 编号数组 * @return 匹配的限时折扣商品 */ - Map getMatchDiscountProducts(Collection skuIds); + List getMatchDiscountProductList(Collection skuIds); /** * 创建限时折扣活动 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java index df54d44f2..97d70491b 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.promotion.service.discount; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityBaseVO; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO; @@ -14,18 +13,17 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProduct import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountActivityMapper; import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper; import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; -import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO; import cn.iocoder.yudao.module.promotion.util.PromotionUtils; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.*; +import java.util.Collection; +import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; -import static java.util.Arrays.asList; /** * 限时折扣 Service 实现类 @@ -42,9 +40,9 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { private DiscountProductMapper discountProductMapper; @Override - public Map getMatchDiscountProducts(Collection skuIds) { - List discountProducts = getRewardProductListBySkuIds(skuIds, singleton(PromotionActivityStatusEnum.RUN.getStatus())); - return convertMap(discountProducts, DiscountProductDetailBO::getSkuId); + public List getMatchDiscountProductList(Collection skuIds) { + // TODO 芋艿:开启、满足 skuId、日期内 + return null; } @Override @@ -101,6 +99,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { } } + // TODO 芋艿:校验逻辑简化,只查询时间冲突的活动,开启状态的。 /** * 校验商品是否冲突 * @@ -112,9 +111,10 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { return; } // 查询商品参加的活动 - List discountActivityProductList = getRewardProductListBySkuIds( - convertSet(products, DiscountActivityBaseVO.Product::getSkuId), - asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus())); + List discountActivityProductList = null; +// getRewardProductListBySkuIds( +// convertSet(products, DiscountActivityBaseVO.Product::getSkuId), +// asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus())); if (id != null) { // 排除自己这个活动 discountActivityProductList.removeIf(product -> id.equals(product.getActivityId())); } @@ -124,24 +124,6 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { } } - private List getRewardProductListBySkuIds(Collection skuIds, - Collection statuses) { - // 查询商品 - List products = discountProductMapper.selectListBySkuId(skuIds); - if (CollUtil.isEmpty(products)) { - return new ArrayList<>(0); - } - - // 查询活动 - List activities = discountActivityMapper.selectBatchIds(skuIds); - activities.removeIf(activity -> !statuses.contains(activity.getStatus())); // 移除不满足 statuses 状态的 - Map activityMap = CollectionUtils.convertMap(activities, DiscountActivityDO::getId); - - // 移除不满足活动的商品 - products.removeIf(product -> !activityMap.containsKey(product.getActivityId())); - return DiscountActivityConvert.INSTANCE.convertList(products, activityMap); - } - @Override public void closeRewardActivity(Long id) { // 校验存在 @@ -153,7 +135,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { throw exception(DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_END); } - // 更新 + // 更新为关闭。 DiscountActivityDO updateObj = new DiscountActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus()); discountActivityMapper.updateById(updateObj); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceService.java index a7420e119..f402cb1be 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceService.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.service.price; import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO; import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO; -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; import java.util.List; @@ -13,14 +12,6 @@ import java.util.List; */ public interface PriceService { - /** - * 计算商品的价格 - * - * @param calculateReqDTO 价格请求 - * @return 价格响应 - */ - PriceCalculateRespDTO calculatePrice(PriceCalculateReqDTO calculateReqDTO); - /** * 获得优惠劵的匹配信息列表 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java index 7aab0bee5..439c03d37 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java @@ -1,39 +1,25 @@ package cn.iocoder.yudao.module.promotion.service.price; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO; import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO; import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; import cn.iocoder.yudao.module.promotion.convert.price.PriceConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; -import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; -import cn.iocoder.yudao.module.promotion.enums.common.*; import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; -import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService; -import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO; -import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService; -import com.google.common.base.Suppliers; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.*; -import java.util.function.Supplier; +import java.util.Collections; +import java.util.List; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; -import static java.util.Collections.singletonList; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_VALID_TIME_NOT_NOW; /** * 价格计算 Service 实现类 @@ -54,43 +40,14 @@ import static java.util.Collections.singletonList; @Slf4j public class PriceServiceImpl implements PriceService { - @Resource - private DiscountActivityService discountService; - @Resource - private RewardActivityService rewardActivityService; @Resource private CouponService couponService; - @Resource - private ProductSkuApi productSkuApi; - - @Override - public PriceCalculateRespDTO calculatePrice(PriceCalculateReqDTO calculateReqDTO) { - // 获得商品 SKU 数组 - List skuList = checkSkus(calculateReqDTO); - // 初始化 PriceCalculateRespDTO 对象 - PriceCalculateRespDTO priceCalculate = PriceConvert.INSTANCE.convert(calculateReqDTO, skuList); - - // 计算商品级别的价格 - calculatePriceForSkuLevel(calculateReqDTO.getUserId(), priceCalculate); - // 计算订单级别的价格 - calculatePriceForOrderLevel(calculateReqDTO.getUserId(), priceCalculate); - // 计算优惠劵级别的价格 - calculatePriceForCouponLevel(calculateReqDTO.getUserId(), calculateReqDTO.getCouponId(), priceCalculate); - - // 如果最终支付金额小于等于 0,则抛出业务异常 - if (priceCalculate.getOrder().getPayPrice() <= 0) { - log.error("[calculatePrice][价格计算不正确,请求 calculateReqDTO({}),结果 priceCalculate({})]", - calculateReqDTO, priceCalculate); - throw exception(PRICE_CALCULATE_PAY_PRICE_ILLEGAL); - } - return priceCalculate; - } - @Override public List getMeetCouponList(PriceCalculateReqDTO calculateReqDTO) { // 先计算一轮价格 - PriceCalculateRespDTO priceCalculate = calculatePrice(calculateReqDTO); +// PriceCalculateRespDTO priceCalculate = calculatePrice(calculateReqDTO); + PriceCalculateRespDTO priceCalculate = null; // 获得用户的待使用优惠劵 List couponList = couponService.getCouponList(calculateReqDTO.getUserId(), CouponStatusEnum.UNUSED.getStatus()); @@ -106,7 +63,9 @@ public class PriceServiceImpl implements PriceService { couponService.validCoupon(coupon); // 获得匹配的商品 SKU 数组 - List orderItems = getMatchCouponOrderItems(priceCalculate, coupon); + // TODO 芋艿:后续处理 +// List orderItems = getMatchCouponOrderItems(priceCalculate, coupon); + List orderItems = null; if (CollUtil.isEmpty(orderItems)) { return couponMeetRespDTO.setMeet(false).setMeetTip("所结算商品没有符合条件的商品"); } @@ -134,413 +93,4 @@ public class PriceServiceImpl implements PriceService { }); } - private List checkSkus(PriceCalculateReqDTO calculateReqDTO) { - // 获得商品 SKU 数组 - Map skuIdCountMap = CollectionUtils.convertMap(calculateReqDTO.getItems(), - PriceCalculateReqDTO.Item::getSkuId, PriceCalculateReqDTO.Item::getCount); - List skus = productSkuApi.getSkuList(skuIdCountMap.keySet()); - - // 校验商品 SKU - skus.forEach(sku -> { - Integer count = skuIdCountMap.get(sku.getId()); - if (count == null) { - throw exception(SKU_NOT_EXISTS); - } - // 不校验库存不足,避免购物车场景,商品无货的情况 - }); - return skus; - } - - // ========== 计算商品级别的价格 ========== - - /** - * 计算商品级别的价格,例如说: - * 1. 会员折扣 - * 2. 限时折扣 {@link cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO} - * - * 其中,会员折扣、限时折扣取最低价 - * - * @param userId 用户编号 - * @param priceCalculate 价格计算的结果 - */ - private void calculatePriceForSkuLevel(Long userId, PriceCalculateRespDTO priceCalculate) { - // 获取 SKU 级别的所有优惠信息 - Supplier memberDiscountPercentSupplier = getMemberDiscountPercentSupplier(userId); - Map discountProducts = discountService.getMatchDiscountProducts( - convertSet(priceCalculate.getOrder().getItems(), PriceCalculateRespDTO.OrderItem::getSkuId)); - - // 处理每个 SKU 的优惠 - priceCalculate.getOrder().getItems().forEach(orderItem -> { - // 获取该 SKU 的优惠信息 - Double memberDiscountPercent = memberDiscountPercentSupplier.get(); - DiscountProductDetailBO discountProduct = discountProducts.get(orderItem.getSkuId()); - if (memberDiscountPercent == null && discountProduct == null) { - return; - } - // 计算价格,判断选择哪个折扣 - Integer memberPrice = memberDiscountPercent != null ? (int) (orderItem.getPayPrice() * memberDiscountPercent / 100) : null; - Integer promotionPrice = discountProduct != null ? getDiscountProductPrice(discountProduct, orderItem) : null; - if (memberPrice == null) { - calculatePriceByDiscountActivity(priceCalculate, orderItem, discountProduct, promotionPrice); - } else if (promotionPrice == null) { - calculatePriceByMemberDiscount(priceCalculate, orderItem, memberPrice); - } else if (memberPrice < promotionPrice) { - calculatePriceByDiscountActivity(priceCalculate, orderItem, discountProduct, promotionPrice); - } else { - calculatePriceByMemberDiscount(priceCalculate, orderItem, memberPrice); - } - }); - } - - private Integer getDiscountProductPrice(DiscountProductDetailBO discountProduct, - PriceCalculateRespDTO.OrderItem orderItem) { - Integer price = orderItem.getPayPrice(); - if (PromotionDiscountTypeEnum.PRICE.getType().equals(discountProduct.getDiscountType())) { // 减价 - price -= discountProduct.getDiscountPrice() * orderItem.getCount(); - } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(discountProduct.getDiscountType())) { // 打折 - price = price * discountProduct.getDiscountPercent() / 100; - } else { - throw new IllegalArgumentException(String.format("优惠活动的商品(%s) 的优惠类型不正确", discountProduct)); - } - return price; - } - - private void calculatePriceByMemberDiscount(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem, - Integer memberPrice) { - // 记录优惠明细 - addPromotion(priceCalculate, orderItem, null, PromotionTypeEnum.MEMBER.getName(), - PromotionTypeEnum.MEMBER.getType(), PromotionLevelEnum.SKU.getLevel(), memberPrice, - true, StrUtil.format("会员折扣:省 {} 元", formatPrice(orderItem.getPayPrice() - memberPrice))); - // 修改 SKU 的优惠 - modifyOrderItemPayPrice(orderItem, memberPrice, priceCalculate); - } - - private void calculatePriceByDiscountActivity(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem, - DiscountProductDetailBO discountProduct, Integer promotionPrice) { - // 记录优惠明细 - addPromotion(priceCalculate, orderItem, discountProduct.getActivityId(), discountProduct.getActivityName(), - PromotionTypeEnum.DISCOUNT_ACTIVITY.getType(), PromotionLevelEnum.SKU.getLevel(), promotionPrice, - true, StrUtil.format("限时折扣:省 {} 元", formatPrice(orderItem.getPayPrice() - promotionPrice))); - // 修改 SKU 的优惠 - modifyOrderItemPayPrice(orderItem, promotionPrice, priceCalculate); - } - - // TODO 芋艿:提前实现 - private Supplier getMemberDiscountPercentSupplier(Long userId) { - return Suppliers.memoize(() -> { - if (userId == 1) { - return 90d; - } - if (userId == 2) { - return 80d; - } - return null; // 无优惠 - }); - } - - // ========== 计算商品级别的价格 ========== - - /** - * 计算订单级别的价格,例如说: - * 1. 满减送 {@link cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO} - * - * @param userId 用户编号 - * @param priceCalculate 价格计算的结果 - */ - @SuppressWarnings("unused") - private void calculatePriceForOrderLevel(Long userId, PriceCalculateRespDTO priceCalculate) { - // 获取 SKU 级别的所有优惠信息 - Set spuIds = convertSet(priceCalculate.getOrder().getItems(), PriceCalculateRespDTO.OrderItem::getSpuId); - Map> rewardActivities = rewardActivityService.getMatchRewardActivities(spuIds); - - // 处理满减送活动 - if (CollUtil.isNotEmpty(rewardActivities)) { - rewardActivities.forEach((rewardActivity, activitySpuIds) -> { - List orderItems = CollectionUtils.filterList(priceCalculate.getOrder().getItems(), - orderItem -> CollUtil.contains(activitySpuIds, orderItem.getSpuId())); - calculatePriceByRewardActivity(priceCalculate, orderItems, rewardActivity); - }); - } - } - - private void calculatePriceByRewardActivity(PriceCalculateRespDTO priceCalculate, List orderItems, - RewardActivityDO rewardActivity) { - // 获得最大匹配的满减送活动的规则 - RewardActivityDO.Rule rule = getLastMatchRewardActivityRule(rewardActivity, orderItems); - if (rule == null) { - // 获取不到的情况下,记录不满足的优惠明细 - addNotMeetPromotion(priceCalculate, orderItems, rewardActivity.getId(), rewardActivity.getName(), - PromotionTypeEnum.REWARD_ACTIVITY.getType(), PromotionLevelEnum.ORDER.getLevel(), - getRewardActivityNotMeetTip(rewardActivity)); - return; - } - - // 分摊金额 - List discountPartPrices = dividePrice(orderItems, rule.getDiscountPrice()); - // 记录优惠明细 - addPromotion(priceCalculate, orderItems, rewardActivity.getId(), rewardActivity.getName(), - PromotionTypeEnum.REWARD_ACTIVITY.getType(), PromotionLevelEnum.ORDER.getLevel(), discountPartPrices, - true, StrUtil.format("满减送:省 {} 元", formatPrice(rule.getDiscountPrice()))); - // 修改 SKU 的分摊 - for (int i = 0; i < orderItems.size(); i++) { - modifyOrderItemOrderPartPriceFromDiscountPrice(orderItems.get(i), discountPartPrices.get(i), priceCalculate); - } - } - - /** - * 获得最大匹配的满减送活动的规则 - * - * @param rewardActivity 满减送活动 - * @param orderItems 商品项 - * @return 匹配的活动规则 - */ - private RewardActivityDO.Rule getLastMatchRewardActivityRule(RewardActivityDO rewardActivity, - List orderItems) { - Integer count = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getCount, Integer::sum); - // price 的计算逻辑,使用 orderDividePrice 的原因,主要考虑分摊后,这个才是该 SKU 当前真实的支付总价 - Integer price = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum); - assert count != null && price != null; - for (int i = rewardActivity.getRules().size() - 1; i >= 0; i--) { - RewardActivityDO.Rule rule = rewardActivity.getRules().get(i); - if (PromotionConditionTypeEnum.PRICE.getType().equals(rewardActivity.getConditionType()) - && price >= rule.getLimit()) { - return rule; - } - if (PromotionConditionTypeEnum.COUNT.getType().equals(rewardActivity.getConditionType()) - && count >= rule.getLimit()) { - return rule; - } - } - return null; - } - - /** - * 获得满减送活动部匹配时的提示 - * - * @param rewardActivity 满减送活动 - * @return 提示 - */ - private String getRewardActivityNotMeetTip(RewardActivityDO rewardActivity) { - return "TODO"; // TODO 芋艿:后面再想想 - } - - // ========== 计算优惠劵级别的价格 ========== - - private void calculatePriceForCouponLevel(Long userId, Long couponId, PriceCalculateRespDTO priceCalculate) { - // 校验优惠劵 - if (couponId == null) { - return; - } - CouponDO coupon = couponService.validCoupon(couponId, userId); - - // 获得匹配的商品 SKU 数组 - List orderItems = getMatchCouponOrderItems(priceCalculate, coupon); - if (CollUtil.isEmpty(orderItems)) { - throw exception(COUPON_NO_MATCH_SPU); - } - - // 计算是否满足优惠劵的使用金额 - Integer originPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum); - assert originPrice != null; - if (originPrice < coupon.getUsePrice()) { - throw exception(COUPON_NO_MATCH_MIN_PRICE); - } - - // 计算可以优惠的金额 - priceCalculate.getOrder().setCouponId(couponId); - Integer couponPrice = getCouponPrice(coupon, originPrice); - // 分摊金额 - List couponPartPrices = dividePrice(orderItems, couponPrice); - // 记录优惠明细 - addPromotion(priceCalculate, orderItems, coupon.getId(), coupon.getName(), - PromotionTypeEnum.COUPON.getType(), PromotionLevelEnum.COUPON.getLevel(), couponPartPrices, - true, StrUtil.format("优惠劵:省 {} 元", formatPrice(couponPrice))); - // 修改 SKU 的分摊 - for (int i = 0; i < orderItems.size(); i++) { - modifyOrderItemOrderPartPriceFromCouponPrice(orderItems.get(i), couponPartPrices.get(i), priceCalculate); - } - } - - private List getMatchCouponOrderItems(PriceCalculateRespDTO priceCalculate, - CouponDO coupon) { - if (PromotionProductScopeEnum.ALL.getScope().equals(coupon.getProductScope())) { - return priceCalculate.getOrder().getItems(); - } - return CollectionUtils.filterList(priceCalculate.getOrder().getItems(), - orderItem -> coupon.getProductSpuIds().contains(orderItem.getSpuId())); - } - - private Integer getCouponPrice(CouponDO coupon, Integer originPrice) { - if (PromotionDiscountTypeEnum.PRICE.getType().equals(coupon.getDiscountType())) { // 减价 - return coupon.getDiscountPrice(); - } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(coupon.getDiscountType())) { // 打折 - int couponPrice = originPrice * coupon.getDiscountPercent() / 100; - return coupon.getDiscountLimitPrice() == null ? couponPrice - : Math.min(couponPrice, coupon.getDiscountLimitPrice()); // 优惠上限 - } - throw new IllegalArgumentException(String.format("优惠劵(%s) 的优惠类型不正确", coupon)); - } - - // ========== 其它相对通用的方法 ========== - - /** - * 添加单个 OrderItem 的营销明细 - * - * @param priceCalculate 价格计算结果 - * @param orderItem 单个订单商品 SKU - * @param id 营销编号 - * @param name 营销名字 - * @param type 营销类型 - * @param level 营销级别 - * @param newPayPrice 新的单实付金额(总) - * @param meet 是否满足优惠条件 - * @param meetTip 满足条件的提示 - */ - private void addPromotion(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem, - Long id, String name, Integer type, Integer level, - Integer newPayPrice, Boolean meet, String meetTip) { - // 创建营销明细 Item - // TODO 芋艿:orderItem.getPayPrice() 要不要改成 orderDividePrice;同时,newPayPrice 要不要改成直接传递 discountPrice - PriceCalculateRespDTO.PromotionItem promotionItem = new PriceCalculateRespDTO.PromotionItem().setSkuId(orderItem.getSkuId()) - .setOriginalPrice(orderItem.getPayPrice()).setDiscountPrice(orderItem.getPayPrice() - newPayPrice); - // 创建营销明细 - PriceCalculateRespDTO.Promotion promotion = new PriceCalculateRespDTO.Promotion() - .setId(id).setName(name).setType(type).setLevel(level) - .setTotalPrice(promotionItem.getOriginalPrice()).setDiscountPrice(promotionItem.getDiscountPrice()) - .setItems(singletonList(promotionItem)).setMeet(meet).setMeetTip(meetTip); - priceCalculate.getPromotions().add(promotion); - } - - /** - * 添加多个 OrderItem 的营销明细 - * - * @param priceCalculate 价格计算结果 - * @param orderItems 多个订单商品 SKU - * @param id 营销编号 - * @param name 营销名字 - * @param type 营销类型 - * @param level 营销级别 - * @param discountPrices 多个订单商品 SKU 的优惠价格(总),和 orderItems 一一对应 - * @param meet 是否满足优惠条件 - * @param meetTip 满足条件的提示 - */ - private void addPromotion(PriceCalculateRespDTO priceCalculate, List orderItems, - Long id, String name, Integer type, Integer level, - List discountPrices, Boolean meet, String meetTip) { - // 创建营销明细 Item - List promotionItems = new ArrayList<>(discountPrices.size()); - for (int i = 0; i < orderItems.size(); i++) { - PriceCalculateRespDTO.OrderItem orderItem = orderItems.get(i); - promotionItems.add(new PriceCalculateRespDTO.PromotionItem().setSkuId(orderItem.getSkuId()) - .setOriginalPrice(orderItem.getPayPrice()).setDiscountPrice(discountPrices.get(i))); - } - // 创建营销明细 - PriceCalculateRespDTO.Promotion promotion = new PriceCalculateRespDTO.Promotion() - .setId(id).setName(name).setType(type).setLevel(level) - .setTotalPrice(getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum)) - .setDiscountPrice(getSumValue(discountPrices, value -> value, Integer::sum)) - .setItems(promotionItems).setMeet(meet).setMeetTip(meetTip); - priceCalculate.getPromotions().add(promotion); - } - - private void addNotMeetPromotion(PriceCalculateRespDTO priceCalculate, List orderItems, - Long id, String name, Integer type, Integer level, String meetTip) { - // 创建营销明细 Item - List promotionItems = CollectionUtils.convertList(orderItems, - orderItem -> new PriceCalculateRespDTO.PromotionItem().setSkuId(orderItem.getSkuId()) - .setOriginalPrice(orderItem.getOrderDividePrice()).setDiscountPrice(0)); - // 创建营销明细 - Integer originalPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum); - PriceCalculateRespDTO.Promotion promotion = new PriceCalculateRespDTO.Promotion() - .setId(id).setName(name).setType(type).setLevel(level) - .setTotalPrice(originalPrice).setDiscountPrice(0) - .setItems(promotionItems).setMeet(false).setMeetTip(meetTip); - priceCalculate.getPromotions().add(promotion); - } - - /** - * 修改 OrderItem 的 payPrice 价格,同时会修改 Order 的 payPrice 价格 - * - * @param orderItem 订单商品 SKU - * @param newPayPrice 新的 payPrice 价格 - * @param priceCalculate 价格计算结果 - */ - private void modifyOrderItemPayPrice(PriceCalculateRespDTO.OrderItem orderItem, Integer newPayPrice, - PriceCalculateRespDTO priceCalculate) { - // diffPayPrice 等于额外增加的商品级的优惠 - int diffPayPrice = orderItem.getPayPrice() - newPayPrice; - // 设置 OrderItem 价格相关字段 - orderItem.setDiscountPrice(orderItem.getDiscountPrice() + diffPayPrice); - orderItem.setPayPrice(newPayPrice); - orderItem.setOrderDividePrice(orderItem.getPayPrice() - orderItem.getOrderPartPrice()); - // 设置 Order 相关相关字段 - PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); - order.setPayPrice(order.getPayPrice() - diffPayPrice); - } - - /** - * 修改 OrderItem 的 orderPartPrice 价格,同时会修改 Order 的 discountPrice 价格 - * - * 本质:分摊 Order 的 discountPrice 价格,到对应的 OrderItem 的 orderPartPrice 价格中 - * - * @param orderItem 订单商品 SKU - * @param addOrderPartPrice 新增的 discountPrice 价格 - * @param priceCalculate 价格计算结果 - */ - private void modifyOrderItemOrderPartPriceFromDiscountPrice(PriceCalculateRespDTO.OrderItem orderItem, Integer addOrderPartPrice, - PriceCalculateRespDTO priceCalculate) { - // 设置 OrderItem 价格相关字段 - orderItem.setOrderPartPrice(orderItem.getOrderPartPrice() + addOrderPartPrice); - orderItem.setOrderDividePrice(orderItem.getPayPrice() - orderItem.getOrderPartPrice()); - // 设置 Order 相关相关字段 - PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); - order.setDiscountPrice(order.getDiscountPrice() + addOrderPartPrice); - order.setPayPrice(order.getPayPrice() - addOrderPartPrice); - } - - /** - * 修改 OrderItem 的 orderPartPrice 价格,同时会修改 Order 的 couponPrice 价格 - * - * 本质:分摊 Order 的 couponPrice 价格,到对应的 OrderItem 的 orderPartPrice 价格中 - * - * @param orderItem 订单商品 SKU - * @param addOrderPartPrice 新增的 couponPrice 价格 - * @param priceCalculate 价格计算结果 - */ - private void modifyOrderItemOrderPartPriceFromCouponPrice(PriceCalculateRespDTO.OrderItem orderItem, Integer addOrderPartPrice, - PriceCalculateRespDTO priceCalculate) { - // 设置 OrderItem 价格相关字段 - orderItem.setOrderPartPrice(orderItem.getOrderPartPrice() + addOrderPartPrice); - orderItem.setOrderDividePrice(orderItem.getPayPrice() - orderItem.getOrderPartPrice()); - // 设置 Order 相关相关字段 - PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); - order.setCouponPrice(order.getCouponPrice() + addOrderPartPrice); - order.setPayPrice(order.getPayPrice() - addOrderPartPrice); - } - - private List dividePrice(List orderItems, Integer price) { - List prices = new ArrayList<>(orderItems.size()); - Integer total = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum); - assert total != null; - int remainPrice = price; - // 遍历每一个,进行分摊 - for (int i = 0; i < orderItems.size(); i++) { - PriceCalculateRespDTO.OrderItem orderItem = orderItems.get(i); - int partPrice; - if (i < orderItems.size() - 1) { // 减一的原因,是因为拆分时,如果按照比例,可能会出现.所以最后一个,使用反减 - partPrice = (int) (price * (1.0D * orderItem.getOrderDividePrice() / total)); - remainPrice -= partPrice; - } else { - partPrice = remainPrice; - } - Assert.isTrue(partPrice > 0, "分摊金额必须大于 0"); - prices.add(partPrice); - } - return prices; - } - - private String formatPrice(Integer price) { - return String.format("%.2f", price / 100d); - } - } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java index 40bcc2836..4dcdb0738 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java @@ -1,14 +1,15 @@ package cn.iocoder.yudao.module.promotion.service.reward; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; import javax.validation.Valid; -import java.util.Map; -import java.util.Set; +import java.util.Collection; +import java.util.List; /** * 满减送活动 Service 接口 @@ -66,8 +67,8 @@ public interface RewardActivityService { * 基于指定的 SPU 编号数组,获得它们匹配的满减送活动 * * @param spuIds SPU 编号数组 - * @return 满减送活动,与对应的 SPU 编号的映射。即,value 就是 SPU 编号的集合 + * @return 满减送活动列表 */ - Map> getMatchRewardActivities(Set spuIds); + List getMatchRewardActivityList(Collection spuIds); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java index 51d0ce626..cdb73853c 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.promotion.service.reward; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.map.MapUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO; @@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.promotion.convert.reward.RewardActivityConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; import cn.iocoder.yudao.module.promotion.dal.mysql.reward.RewardActivityMapper; import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; -import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; import cn.iocoder.yudao.module.promotion.util.PromotionUtils; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -18,15 +17,10 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.Collection; import java.util.List; -import java.util.Map; -import java.util.Set; -import static cn.hutool.core.collection.CollUtil.intersectionDistinct; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; import static java.util.Arrays.asList; -import static java.util.Collections.singleton; /** * 满减送活动 Service 实现类 @@ -105,6 +99,7 @@ public class RewardActivityServiceImpl implements RewardActivityService { return activity; } + // TODO @芋艿:逻辑有问题,需要优化;要分成全场、和指定来校验; /** * 校验商品参加的活动是否冲突 * @@ -151,19 +146,21 @@ public class RewardActivityServiceImpl implements RewardActivityService { } @Override - public Map> getMatchRewardActivities(Set spuIds) { - // 如果有全局活动,则直接选择它 - List allActivities = rewardActivityMapper.selectListByProductScopeAndStatus( - PromotionProductScopeEnum.ALL.getScope(), PromotionActivityStatusEnum.RUN.getStatus()); - if (CollUtil.isNotEmpty(allActivities)) { - return MapUtil.builder(allActivities.get(0), spuIds).build(); - } - - // 查询某个活动参加的活动 - List productActivityList = getRewardActivityListBySpuIds(spuIds, - singleton(PromotionActivityStatusEnum.RUN.getStatus())); - return convertMap(productActivityList, activity -> activity, - rewardActivityDO -> intersectionDistinct(rewardActivityDO.getProductSpuIds(), spuIds)); // 求交集返回 + public List getMatchRewardActivityList(Collection spuIds) { + // TODO 芋艿:待实现;先指定,然后再全局的; +// // 如果有全局活动,则直接选择它 +// List allActivities = rewardActivityMapper.selectListByProductScopeAndStatus( +// PromotionProductScopeEnum.ALL.getScope(), PromotionActivityStatusEnum.RUN.getStatus()); +// if (CollUtil.isNotEmpty(allActivities)) { +// return MapUtil.builder(allActivities.get(0), spuIds).build(); +// } +// +// // 查询某个活动参加的活动 +// List productActivityList = getRewardActivityListBySpuIds(spuIds, +// singleton(PromotionActivityStatusEnum.RUN.getStatus())); +// return convertMap(productActivityList, activity -> activity, +// rewardActivityDO -> intersectionDistinct(rewardActivityDO.getProductSpuIds(), spuIds)); // 求交集返回 + return null; } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java index 9e40ff67b..929727077 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java @@ -96,8 +96,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion.getLevel(), PromotionLevelEnum.SKU.getLevel()); assertEquals(promotion.getTotalPrice(), 200); assertEquals(promotion.getDiscountPrice(), 20); - assertTrue(promotion.getMeet()); - assertEquals(promotion.getMeetTip(), "会员折扣:省 0.20 元"); + assertTrue(promotion.getMatch()); + assertEquals(promotion.getDescription(), "会员折扣:省 0.20 元"); PriceCalculateRespDTO.PromotionItem promotionItem = promotion.getItems().get(0); assertEquals(promotion.getItems().size(), 1); assertEquals(promotionItem.getSkuId(), 10L); @@ -122,7 +122,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { DiscountProductDetailBO discountProduct02 = randomPojo(DiscountProductDetailBO.class, o -> o.setActivityId(2000L) .setActivityName("活动 2000 号").setSkuId(20L) .setDiscountType(PromotionDiscountTypeEnum.PERCENT.getType()).setDiscountPercent(60)); - when(discountService.getMatchDiscountProducts(eq(asSet(10L, 20L)))).thenReturn( + when(discountService.getMatchDiscountProductList(eq(asSet(10L, 20L)))).thenReturn( MapUtil.builder(10L, discountProduct01).put(20L, discountProduct02).map()); // 10L: 100 * 2 - 40 * 2 = 120 @@ -167,8 +167,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion01.getLevel(), PromotionLevelEnum.SKU.getLevel()); assertEquals(promotion01.getTotalPrice(), 200); assertEquals(promotion01.getDiscountPrice(), 80); - assertTrue(promotion01.getMeet()); - assertEquals(promotion01.getMeetTip(), "限时折扣:省 0.80 元"); + assertTrue(promotion01.getMatch()); + assertEquals(promotion01.getDescription(), "限时折扣:省 0.80 元"); PriceCalculateRespDTO.PromotionItem promotionItem01 = promotion01.getItems().get(0); assertEquals(promotion01.getItems().size(), 1); assertEquals(promotionItem01.getSkuId(), 10L); @@ -181,8 +181,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion02.getLevel(), PromotionLevelEnum.SKU.getLevel()); assertEquals(promotion02.getTotalPrice(), 150); assertEquals(promotion02.getDiscountPrice(), 60); - assertTrue(promotion02.getMeet()); - assertEquals(promotion02.getMeetTip(), "限时折扣:省 0.60 元"); + assertTrue(promotion02.getMatch()); + assertEquals(promotion02.getDescription(), "限时折扣:省 0.60 元"); PriceCalculateRespDTO.PromotionItem promotionItem02 = promotion02.getItems().get(0); assertEquals(promotion02.getItems().size(), 1); assertEquals(promotionItem02.getSkuId(), 20L); @@ -267,8 +267,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion01.getLevel(), PromotionLevelEnum.ORDER.getLevel()); assertEquals(promotion01.getTotalPrice(), 350); assertEquals(promotion01.getDiscountPrice(), 70); - assertTrue(promotion01.getMeet()); - assertEquals(promotion01.getMeetTip(), "满减送:省 0.70 元"); + assertTrue(promotion01.getMatch()); + assertEquals(promotion01.getDescription(), "满减送:省 0.70 元"); assertEquals(promotion01.getItems().size(), 2); PriceCalculateRespDTO.PromotionItem promotionItem011 = promotion01.getItems().get(0); assertEquals(promotionItem011.getSkuId(), 10L); @@ -286,8 +286,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion02.getLevel(), PromotionLevelEnum.ORDER.getLevel()); assertEquals(promotion02.getTotalPrice(), 120); assertEquals(promotion02.getDiscountPrice(), 60); - assertTrue(promotion02.getMeet()); - assertEquals(promotion02.getMeetTip(), "满减送:省 0.60 元"); + assertTrue(promotion02.getMatch()); + assertEquals(promotion02.getDescription(), "满减送:省 0.60 元"); PriceCalculateRespDTO.PromotionItem promotionItem02 = promotion02.getItems().get(0); assertEquals(promotion02.getItems().size(), 1); assertEquals(promotionItem02.getSkuId(), 30L); @@ -355,8 +355,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion01.getLevel(), PromotionLevelEnum.ORDER.getLevel()); assertEquals(promotion01.getTotalPrice(), 350); assertEquals(promotion01.getDiscountPrice(), 0); - assertFalse(promotion01.getMeet()); - assertEquals(promotion01.getMeetTip(), "TODO"); // TODO 芋艿:后面再想想 + assertFalse(promotion01.getMatch()); + assertEquals(promotion01.getDescription(), "TODO"); // TODO 芋艿:后面再想想 assertEquals(promotion01.getItems().size(), 2); PriceCalculateRespDTO.PromotionItem promotionItem011 = promotion01.getItems().get(0); assertEquals(promotionItem011.getSkuId(), 10L); @@ -437,8 +437,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion01.getLevel(), PromotionLevelEnum.COUPON.getLevel()); assertEquals(promotion01.getTotalPrice(), 350); assertEquals(promotion01.getDiscountPrice(), 70); - assertTrue(promotion01.getMeet()); - assertEquals(promotion01.getMeetTip(), "优惠劵:省 0.70 元"); + assertTrue(promotion01.getMatch()); + assertEquals(promotion01.getDescription(), "优惠劵:省 0.70 元"); assertEquals(promotion01.getItems().size(), 2); PriceCalculateRespDTO.PromotionItem promotionItem011 = promotion01.getItems().get(0); assertEquals(promotionItem011.getSkuId(), 10L); diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java index cb0ac8474..b887ae8c8 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java @@ -50,4 +50,8 @@ public interface ErrorCodeConstants { ErrorCode EXPRESS_CODE_DUPLICATE = new ErrorCode(1011003001, "已经存在该编码的快递公司"); ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1011003002, "运费模板不存在"); ErrorCode EXPRESS_TEMPLATE_NAME_DUPLICATE = new ErrorCode(1011003002, "已经存在该运费模板名"); + + // ========== Price 相关 1011004000 ============ + ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011004000, "支付价格计算异常,原因:价格小于等于 0"); + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceService.java new file mode 100644 index 000000000..2dd0c41ca --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceService.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.trade.service.price; + +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; + +/** + * 价格计算 Service 接口 + * + * @author 芋道源码 + */ +public interface TradePriceService { + + /** + * 价格计算 + * + * @param calculateReqDTO 计算信息 + * @return 计算结果 + */ + TradePriceCalculateRespBO calculatePrice(TradePriceCalculateReqBO calculateReqDTO); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java new file mode 100644 index 000000000..f0ebce5ba --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.trade.service.price; + +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.service.price.bo.TradePriceCalculateReqBO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; +import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculator; +import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_STOCK_NOT_ENOUGH; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.PRICE_CALCULATE_PAY_PRICE_ILLEGAL; + +/** + * 价格计算 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Slf4j +public class TradePriceServiceImpl implements TradePriceService { + + @Resource + private ProductSkuApi productSkuApi; + @Resource + private List priceCalculators; + + @Override + public TradePriceCalculateRespBO calculatePrice(TradePriceCalculateReqBO calculateReqBO) { + // 1. 获得商品 SKU 数组 + List skuList = checkSkus(calculateReqBO); + + // 2.1 计算价格 + TradePriceCalculateRespBO calculateRespBO = TradePriceCalculatorHelper + .buildCalculateResp(calculateReqBO, skuList); + priceCalculators.forEach(calculator -> calculator.calculate(calculateReqBO, calculateRespBO)); + // 2.2 如果最终支付金额小于等于 0,则抛出业务异常 + if (calculateRespBO.getPrice().getPayPrice() <= 0) { + log.error("[calculatePrice][价格计算不正确,请求 calculateReqDTO({}),结果 priceCalculate({})]", + calculateReqBO, calculateRespBO); + throw exception(PRICE_CALCULATE_PAY_PRICE_ILLEGAL); + } + return calculateRespBO; + } + + private List checkSkus(TradePriceCalculateReqBO reqBO) { + // 获得商品 SKU 数组 + Map skuIdCountMap = convertMap(reqBO.getItems(), + TradePriceCalculateReqBO.Item::getSkuId, TradePriceCalculateReqBO.Item::getCount); + List skus = productSkuApi.getSkuList(skuIdCountMap.keySet()); + + // 校验商品 SKU + skus.forEach(sku -> { + Integer count = skuIdCountMap.get(sku.getId()); + if (count == null) { + throw exception(SKU_NOT_EXISTS); + } + if (count > sku.getStock()) { + throw exception(SKU_STOCK_NOT_ENOUGH); + } + }); + return skus; + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java new file mode 100644 index 000000000..2a014c0e0 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.trade.service.price.bo; + +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; +import lombok.Data; + +import javax.validation.Valid; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * 价格计算 Request BO + * + * @author yudao源码 + */ +@Data +public class TradePriceCalculateReqBO { + + /** + * 订单类型 + * + * 枚举 {@link TradeOrderTypeEnum} + */ + private Integer orderType; + + /** + * 用户编号 + * + * 对应 MemberUserDO 的 id 编号 + */ + private Long userId; + + /** + * 优惠劵编号 + * + * 对应 CouponDO 的 id 编号 + */ + private Long couponId; + + /** + * 收货地址编号 + * + * 对应 MemberAddressDO 的 id 编号 + */ + private Long addressId; + + /** + * 商品 SKU 数组 + */ + @NotNull(message = "商品数组不能为空") + private List items; + + /** + * 商品 SKU + */ + @Data + @Valid + public static class Item { + + /** + * SKU 编号 + */ + @NotNull(message = "商品 SKU 编号不能为空") + private Long skuId; + + /** + * SKU 数量 + */ + @NotNull(message = "商品 SKU 数量不能为空") + @Min(value = 0L, message = "商品 SKU 数量必须大于等于 0") + private Integer count; + + /** + * 购物车项的编号 + */ + private Long cartId; + + /** + * 是否选中 + */ + @NotNull(message = "是否选中不能为空") + private Boolean selected; + + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java new file mode 100644 index 000000000..b30ba8855 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java @@ -0,0 +1,249 @@ +package cn.iocoder.yudao.module.trade.service.price.bo; + +import cn.iocoder.yudao.module.promotion.enums.common.PromotionLevelEnum; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; +import lombok.Data; + +import java.util.List; + +/** + * 价格计算 Response BO + * + * 整体设计,参考 taobao 的技术文档: + * 1. 订单管理 + * 2. 常用订单金额说明 + * + * @author 芋道源码 + */ +@Data +public class TradePriceCalculateRespBO { + + /** + * 订单类型 + * + * 枚举 {@link TradeOrderTypeEnum} + */ + private Integer orderType; + + /** + * 订单价格 + */ + private Price price; + + /** + * 订单项数组 + */ + private List items; + + /** + * 营销活动数组 + * + * 只对应 {@link Price#items} 商品匹配的活动 + */ + private List promotions; + + /** + * 优惠劵编号 + */ + private Long couponId; + + /** + * 订单价格 + */ + @Data + public static class Price { + + /** + * 商品原价(总),单位:分 + * + * 基于 {@link OrderItem#getPrice()} * {@link OrderItem#getCount()} 求和 + * + * 对应 taobao 的 trade.total_fee 字段 + */ + private Integer totalPrice; + /** + * 订单优惠(总),单位:分 + * + * 对应 taobao 的 order.discount_fee 字段 + */ + private Integer discountPrice; + /** + * 运费金额,单位:分 + */ + private Integer deliveryPrice; + /** + * 优惠劵减免金额(总),单位:分 + * + * 对应 taobao 的 trade.coupon_fee 字段 + */ + private Integer couponPrice; + /** + * 积分抵扣的金额,单位:分 + * + * 对应 taobao 的 trade.point_fee 字段 + */ + private Integer pointPrice; + /** + * 最终购买金额(总),单位:分 + * + * = {@link #totalPrice} + * - {@link #couponPrice} + * - {@link #pointPrice} + * - {@link #discountPrice} + * + {@link #deliveryPrice} + */ + private Integer payPrice; + + } + + /** + * 订单商品 SKU + */ + @Data + public static class OrderItem { + + /** + * SPU 编号 + */ + private Long spuId; + /** + * SKU 编号 + */ + private Long skuId; + /** + * 购买数量 + */ + private Integer count; + /** + * 购物车项的编号 + */ + private Long cartId; + /** + * 是否选中 + */ + private Boolean selected; + + /** + * 商品原价(单),单位:分 + * + * 对应 ProductSkuDO 的 price 字段 + * 对应 taobao 的 order.price 字段 + */ + private Integer price; + /** + * 优惠金额(总),单位:分 + * + * 对应 taobao 的 order.discount_fee 字段 + */ + private Integer discountPrice; + /** + * 运费金额(总),单位:分 + */ + private Integer deliveryPrice; + /** + * 优惠劵减免金额,单位:分 + * + * 对应 taobao 的 trade.coupon_fee 字段 + */ + private Integer couponPrice; + /** + * 积分抵扣的金额,单位:分 + * + * 对应 taobao 的 trade.point_fee 字段 + */ + private Integer pointPrice; + /** + * 应付金额(总),单位:分 + * + * = {@link #price} * {@link #count} + * - {@link #couponPrice} + * - {@link #pointPrice} + * - {@link #discountPrice} + * + {@link #deliveryPrice} + */ + private Integer payPrice; + + // TODO 芋艿:这里补充下基本信息,简单一点。 + + } + + /** + * 营销明细 + */ + @Data + public static class Promotion { + + /** + * 营销编号 + * + * 例如说:营销活动的编号、优惠劵的编号 + */ + private Long id; + /** + * 营销名字 + */ + private String name; + /** + * 营销类型 + * + * 枚举 {@link PromotionTypeEnum} + */ + private Integer type; + /** + * 营销级别 + * + * 枚举 {@link PromotionLevelEnum} + */ + private Integer level; + /** + * 计算时的原价(总),单位:分 + */ + private Integer totalPrice; + /** + * 计算时的优惠(总),单位:分 + */ + private Integer discountPrice; + /** + * 匹配的商品 SKU 数组 + */ + private List items; + + // ========== 匹配情况 ========== + + /** + * 是否满足优惠条件 + */ + private Boolean match; + /** + * 满足条件的提示 + * + * 如果 {@link #match} = true 满足,则提示“圣诞价:省 150.00 元” + * 如果 {@link #match} = false 不满足,则提示“购满 85 元,可减 40 元” + */ + private String description; + + } + + /** + * 营销匹配的商品 SKU + */ + @Data + public static class PromotionItem { + + /** + * 商品 SKU 编号 + */ + private Long skuId; + /** + * 计算时的原价(总),单位:分 + */ + private Integer totalPrice; + /** + * 计算时的优惠(总),单位:分 + */ + private Integer discountPrice; + + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java new file mode 100644 index 000000000..52ebf84a0 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java @@ -0,0 +1,109 @@ +package cn.iocoder.yudao.module.trade.service.price.calculator; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; +import java.util.function.Predicate; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_NO_MATCH_MIN_PRICE; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_NO_MATCH_SPU; + +/** + * 优惠劵的 {@link TradePriceCalculator} 实现类 + * + * @author 芋道源码 + */ +@Component +@Order(TradePriceCalculator.ORDER_COUPON) +public class TradeCouponPriceCalculator implements TradePriceCalculator { + + @Resource + private CouponApi couponApi; + + @Override + public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { + // 1.1 校验优惠劵 + if (param.getCouponId() == null) { + return; + } + CouponRespDTO coupon = couponApi.validateCoupon(new CouponValidReqDTO() + .setId(param.getCouponId()).setUserId(param.getUserId())); + Assert.notNull(coupon, "校验通过的优惠劵({}),不能为空", param.getCouponId()); + + // 2.1 获得匹配的商品 SKU 数组 + List orderItems = filterMatchCouponOrderItems(result, coupon); + if (CollUtil.isEmpty(orderItems)) { + throw exception(COUPON_NO_MATCH_SPU); + } + // 2.2 计算是否满足优惠劵的使用金额 + Integer totalPayPrice = TradePriceCalculatorHelper.calculateTotalPayPrice(orderItems); + if (totalPayPrice < coupon.getUsePrice()) { + throw exception(COUPON_NO_MATCH_MIN_PRICE); + } + + // 3.1 计算可以优惠的金额 + Integer couponPrice = getCouponPrice(coupon, totalPayPrice); + Assert.isTrue(couponPrice < totalPayPrice, + "优惠劵({}) 的优惠金额({}),不能大于订单总金额({})", coupon.getId(), couponPrice, totalPayPrice); + // 3.2 计算分摊的优惠金额 + List divideCouponPrices = TradePriceCalculatorHelper.dividePrice(orderItems, couponPrice); + + // 4.1 记录使用的优惠劵 + result.setCouponId(param.getCouponId()); + // 4.2 记录优惠明细 + TradePriceCalculatorHelper.addPromotion(result, orderItems, + param.getCouponId(), coupon.getName(), PromotionTypeEnum.COUPON.getType(), + StrUtil.format("优惠劵:省 {} 元", TradePriceCalculatorHelper.formatPrice(couponPrice)), + divideCouponPrices); + // 4.3 更新 SKU 优惠金额 + for (int i = 0; i < orderItems.size(); i++) { + TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i); + orderItem.setCouponPrice(divideCouponPrices.get(i)); + TradePriceCalculatorHelper.recountPayPrice(orderItem); + } + TradePriceCalculatorHelper.recountAllPrice(result); + } + + private Integer getCouponPrice(CouponRespDTO coupon, Integer totalPayPrice) { + if (PromotionDiscountTypeEnum.PRICE.getType().equals(coupon.getDiscountType())) { // 减价 + return coupon.getDiscountPrice(); + } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(coupon.getDiscountType())) { // 打折 + int couponPrice = totalPayPrice * coupon.getDiscountPercent() / 100; + return coupon.getDiscountLimitPrice() == null ? couponPrice + : Math.min(couponPrice, coupon.getDiscountLimitPrice()); // 优惠上限 + } + throw new IllegalArgumentException(String.format("优惠劵(%s) 的优惠类型不正确", coupon)); + } + + /** + * 获得优惠劵可使用的订单项(商品)列表 + * + * @param result 计算结果 + * @param coupon 优惠劵 + * @return 订单项(商品)列表 + */ + private List filterMatchCouponOrderItems(TradePriceCalculateRespBO result, + CouponRespDTO coupon) { + Predicate matchPredicate = TradePriceCalculateRespBO.OrderItem::getSelected; + if (PromotionProductScopeEnum.SPU.getScope().equals(coupon.getProductScope())) { + matchPredicate = orderItem -> coupon.getProductSpuIds().contains(orderItem.getSpuId()); + } + return filterList(result.getItems(), matchPredicate); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java new file mode 100644 index 000000000..7bcd8ffb7 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.trade.service.price.calculator; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.promotion.api.discount.DiscountActivityApi; +import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper.formatPrice; + +/** + * 限时折扣的 {@link TradePriceCalculator} 实现类 + * + * @author 芋道源码 + */ +@Component +@Order(TradePriceCalculator.ORDER_DISCOUNT_ACTIVITY) +public class TradeDiscountActivityPriceCalculator implements TradePriceCalculator { + + @Resource + private DiscountActivityApi discountActivityApi; + + @Override + public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { + // 获得 SKU 对应的限时折扣活动 + List discountProducts = discountActivityApi.getMatchDiscountProductList( + convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSkuId)); + if (CollUtil.isEmpty(discountProducts)) { + return; + } + Map discountProductMap = convertMap(discountProducts, DiscountProductRespDTO::getSkuId); + + // 处理每个 SKU 的限时折扣 + result.getItems().forEach(orderItem -> { + // 1. 获取该 SKU 的优惠信息 + DiscountProductRespDTO discountProduct = discountProductMap.get(orderItem.getSkuId()); + if (discountProduct == null) { + return; + } + // 2. 计算优惠金额 + Integer newPayPrice = calculatePayPrice(discountProduct, orderItem); + Integer newDiscountPrice = orderItem.getPayPrice() - newPayPrice; + + // 3.1 记录优惠明细 + TradePriceCalculatorHelper.addPromotion(result, orderItem, + discountProduct.getActivityId(), discountProduct.getActivityName(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType(), + StrUtil.format("限时折扣:省 {} 元", formatPrice(newDiscountPrice)), + newDiscountPrice); + // 3.2 更新 SKU 优惠金额 + orderItem.setDiscountPrice(orderItem.getDiscountPrice() + newDiscountPrice); + TradePriceCalculatorHelper.recountPayPrice(orderItem); + }); + TradePriceCalculatorHelper.recountAllPrice(result); + } + + private Integer calculatePayPrice(DiscountProductRespDTO discountProduct, + TradePriceCalculateRespBO.OrderItem orderItem) { + Integer price = orderItem.getPayPrice(); + if (PromotionDiscountTypeEnum.PRICE.getType().equals(discountProduct.getDiscountType())) { // 减价 + price -= discountProduct.getDiscountPrice() * orderItem.getCount(); + } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(discountProduct.getDiscountType())) { // 打折 + price = price * discountProduct.getDiscountPercent() / 100; + } else { + throw new IllegalArgumentException(String.format("优惠活动的商品(%s) 的优惠类型不正确", discountProduct)); + } + return price; + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculator.java new file mode 100644 index 000000000..1c9b4f988 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculator.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.trade.service.price.calculator; + +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; + +/** + * 价格计算的计算器接口 + * + * @author 芋道源码 + */ +public interface TradePriceCalculator { + + int ORDER_DISCOUNT_ACTIVITY = 10; + int ORDER_REWARD_ACTIVITY = 20; + int ORDER_COUPON = 30; + + void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java new file mode 100644 index 000000000..9ed94b692 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java @@ -0,0 +1,221 @@ +package cn.iocoder.yudao.module.trade.service.price.calculator; + +import cn.hutool.core.lang.Assert; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; +import static java.util.Collections.singletonList; + +/** + * {@link TradePriceCalculator} 的工具类 + * + * 主要实现对 {@link TradePriceCalculateRespBO} 计算结果的操作 + * + * @author 芋道源码 + */ +public class TradePriceCalculatorHelper { + + public static TradePriceCalculateRespBO buildCalculateResp(TradePriceCalculateReqBO param, + List skuList) { + // 创建 PriceCalculateRespDTO 对象 + TradePriceCalculateRespBO result = new TradePriceCalculateRespBO(); + result.setOrderType(param.getOrderType()); + // 创建它的 OrderItem 属性 + Map skuItemMap = convertMap(param.getItems(), + TradePriceCalculateReqBO.Item::getSkuId); + result.setItems(new ArrayList<>(skuItemMap.size())); + skuList.forEach(sku -> { + TradePriceCalculateReqBO.Item skuItem = skuItemMap.get(sku.getId()); + TradePriceCalculateRespBO.OrderItem orderItem = new TradePriceCalculateRespBO.OrderItem() + // SKU 字段 + .setSpuId(sku.getSpuId()).setSkuId(sku.getId()) + .setCount(skuItem.getCount()).setCartId(skuItem.getCartId()).setSelected(skuItem.getSelected()) + // 价格字段 + .setPrice(sku.getPrice()).setPayPrice(sku.getPrice() * skuItem.getCount()) + .setDiscountPrice(0).setDeliveryPrice(0).setCouponPrice(0).setPointPrice(0); + result.getItems().add(orderItem); + }); + // 创建它的 Price 属性 + result.setPrice(new TradePriceCalculateRespBO.Price()); + recountAllPrice(result); + return result; + } + + /** + * 基于订单项,重新计算 price 总价 + * + * @param result 计算结果 + */ + public static void recountAllPrice(TradePriceCalculateRespBO result) { + // 先重置 + TradePriceCalculateRespBO.Price price = result.getPrice(); + price.setTotalPrice(0).setDiscountPrice(0).setDeliveryPrice(0) + .setCouponPrice(0).setPointPrice(0).setPayPrice(0); + // 再合计 item + result.getItems().forEach(item -> { + if (!item.getSelected()) { + return; + } + price.setTotalPrice(price.getTotalPrice() + item.getPrice() * item.getCount()); + price.setDiscountPrice(price.getDiscountPrice() + item.getDiscountPrice()); + price.setDeliveryPrice(price.getDeliveryPrice() + item.getDeliveryPrice()); + price.setCouponPrice(price.getCouponPrice() + item.getCouponPrice()); + price.setPointPrice(price.getPointPrice() + item.getPointPrice()); + price.setPayPrice(price.getPayPrice() + item.getPayPrice()); + }); + } + + /** + * 重新计算单个订单项的支付金额 + * + * @param orderItem 订单项 + */ + public static void recountPayPrice(TradePriceCalculateRespBO.OrderItem orderItem) { + orderItem.setPayPrice(orderItem.getPrice()* orderItem.getCount() + - orderItem.getDiscountPrice() + + orderItem.getDeliveryPrice() + - orderItem.getCouponPrice() + - orderItem.getPointPrice()); + } + + /** + * 计算已选中的订单项,总支付金额 + * + * @param orderItems 订单项数组 + * @return 总支付金额 + */ + public static Integer calculateTotalPayPrice(List orderItems) { + return getSumValue(orderItems, + orderItem -> orderItem.getSelected() ? orderItem.getPayPrice() : 0, // 未选中的情况下,不计算支付金额 + Integer::sum); + } + + /** + * 计算已选中的订单项,总商品数 + * + * @param orderItems 订单项数组 + * @return 总商品数 + */ + public static Integer calculateTotalCount(List orderItems) { + return getSumValue(orderItems, + orderItem -> orderItem.getSelected() ? orderItem.getCount() : 0, // 未选中的情况下,不计算数量 + Integer::sum); + } + + /** + * 按照支付金额,返回每个订单项的分摊金额数组 + * + * @param orderItems 订单项数组 + * @param price 金额 + * @return 分摊金额数组,和传入的 orderItems 一一对应 + */ + public static List dividePrice(List orderItems, Integer price) { + Integer total = calculateTotalPayPrice(orderItems); + assert total != null; + // 遍历每一个,进行分摊 + List prices = new ArrayList<>(orderItems.size()); + int remainPrice = price; + for (int i = 0; i < orderItems.size(); i++) { + TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i); + // 1. 如果是未选中,则分摊为 0 + if (!orderItem.getSelected()) { + prices.add(0); + continue; + } + // 2. 如果选中,则按照百分比,进行分摊 + int partPrice; + if (i < orderItems.size() - 1) { // 减一的原因,是因为拆分时,如果按照比例,可能会出现.所以最后一个,使用反减 + partPrice = (int) (price * (1.0D * orderItem.getPayPrice() / total)); + remainPrice -= partPrice; + } else { + partPrice = remainPrice; + } + Assert.isTrue(partPrice >= 0, "分摊金额必须大于等于 0"); + prices.add(partPrice); + } + return prices; + } + + /** + * 添加【匹配】单个 OrderItem 的营销明细 + * + * @param result 价格计算结果 + * @param orderItem 单个订单商品 SKU + * @param id 营销编号 + * @param name 营销名字 + * @param description 满足条件的提示 + * @param type 营销类型 + * @param discountPrice 单个订单商品 SKU 的优惠价格(总) + */ + public static void addPromotion(TradePriceCalculateRespBO result, TradePriceCalculateRespBO.OrderItem orderItem, + Long id, String name, Integer type, String description, Integer discountPrice) { + addPromotion(result, singletonList(orderItem), id, name, type, description, singletonList(discountPrice)); + } + + /** + * 添加【匹配】多个 OrderItem 的营销明细 + * + * @param result 价格计算结果 + * @param orderItems 多个订单商品 SKU + * @param id 营销编号 + * @param name 营销名字 + * @param description 满足条件的提示 + * @param type 营销类型 + * @param discountPrices 多个订单商品 SKU 的优惠价格(总),和 orderItems 一一对应 + */ + public static void addPromotion(TradePriceCalculateRespBO result, List orderItems, + Long id, String name, Integer type, String description, List discountPrices) { + // 创建营销明细 Item + List promotionItems = new ArrayList<>(discountPrices.size()); + for (int i = 0; i < orderItems.size(); i++) { + TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i); + promotionItems.add(new TradePriceCalculateRespBO.PromotionItem().setSkuId(orderItem.getSkuId()) + .setTotalPrice(orderItem.getPayPrice()).setDiscountPrice(discountPrices.get(i))); + } + // 创建营销明细 + TradePriceCalculateRespBO.Promotion promotion = new TradePriceCalculateRespBO.Promotion() + .setId(id).setName(name).setType(type) + .setTotalPrice(calculateTotalPayPrice(orderItems)) + .setDiscountPrice(getSumValue(discountPrices, value -> value, Integer::sum)) + .setItems(promotionItems).setMatch(true).setDescription(description); + result.getPromotions().add(promotion); + } + + /** + * 添加【不匹配】多个 OrderItem 的营销明细 + * + * @param result 价格计算结果 + * @param orderItems 多个订单商品 SKU + * @param id 营销编号 + * @param name 营销名字 + * @param description 满足条件的提示 + * @param type 营销类型 + */ + public static void addNotMatchPromotion(TradePriceCalculateRespBO result, List orderItems, + Long id, String name, Integer type, String description) { + // 创建营销明细 Item + List promotionItems = CollectionUtils.convertList(orderItems, + orderItem -> new TradePriceCalculateRespBO.PromotionItem().setSkuId(orderItem.getSkuId()) + .setTotalPrice(orderItem.getPayPrice()).setDiscountPrice(0)); + // 创建营销明细 + TradePriceCalculateRespBO.Promotion promotion = new TradePriceCalculateRespBO.Promotion() + .setId(id).setName(name).setType(type) + .setTotalPrice(calculateTotalPayPrice(orderItems)) + .setDiscountPrice(0) + .setItems(promotionItems).setMatch(false).setDescription(description); + result.getPromotions().add(promotion); + } + + public static String formatPrice(Integer price) { + return String.format("%.2f", price / 100d); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java new file mode 100644 index 000000000..b0947fcc3 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java @@ -0,0 +1,133 @@ +package cn.iocoder.yudao.module.trade.service.price.calculator; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.promotion.api.reward.RewardActivityApi; +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; +import static cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper.formatPrice; + +/** + * 满减送活动的 {@link TradePriceCalculator} 实现类 + * + * @author 芋道源码 + */ +@Component +@Order(TradePriceCalculator.ORDER_REWARD_ACTIVITY) +public class TradeRewardActivityPriceCalculator implements TradePriceCalculator { + + @Resource + private RewardActivityApi rewardActivityApi; + + @Override + public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { + // 获得 SKU 对应的满减送活动 + List rewardActivities = rewardActivityApi.getMatchRewardActivityList( + convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSpuId)); + if (CollUtil.isEmpty(rewardActivities)) { + return; + } + + // 处理每个满减送活动 + rewardActivities.forEach(rewardActivity -> calculate(param, result, rewardActivity)); + } + + private void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result, + RewardActivityMatchRespDTO rewardActivity) { + // 1.1 获得满减送的订单项(商品)列表 + List orderItems = filterMatchCouponOrderItems(result, rewardActivity); + if (CollUtil.isEmpty(orderItems)) { + return; + } + // 1.2 获得最大匹配的满减送活动的规则 + RewardActivityMatchRespDTO.Rule rule = getMaxMatchRewardActivityRule(rewardActivity, orderItems); + if (rule == null) { + return; + } + + // 2.1 计算可以优惠的金额 + Integer newDiscountPrice = rule.getDiscountPrice(); + // 2.2 计算分摊的优惠金额 + List divideDiscountPrices = TradePriceCalculatorHelper.dividePrice(orderItems, newDiscountPrice); + + // 3.1 记录使用的优惠劵 + result.setCouponId(param.getCouponId()); + // 3.2 记录优惠明细 + TradePriceCalculatorHelper.addPromotion(result, orderItems, + rewardActivity.getId(), rewardActivity.getName(), PromotionTypeEnum.REWARD_ACTIVITY.getType(), + StrUtil.format("满减送:省 {} 元", formatPrice(rule.getDiscountPrice())), + divideDiscountPrices); + // 3.3 更新 SKU 优惠金额 + for (int i = 0; i < orderItems.size(); i++) { + TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i); + orderItem.setDiscountPrice(orderItem.getDiscountPrice() + divideDiscountPrices.get(i)); + TradePriceCalculatorHelper.recountPayPrice(orderItem); + } + TradePriceCalculatorHelper.recountAllPrice(result); + } + + /** + * 获得满减送的订单项(商品)列表 + * + * @param result 计算结果 + * @param rewardActivity 满减送活动 + * @return 订单项(商品)列表 + */ + private List filterMatchCouponOrderItems(TradePriceCalculateRespBO result, + RewardActivityMatchRespDTO rewardActivity) { + return filterList(result.getItems(), + orderItem -> CollUtil.contains(rewardActivity.getSpuIds(), orderItem.getSpuId())); + } + + /** + * 获得最大匹配的满减送活动的规则 + * + * @param rewardActivity 满减送活动 + * @param orderItems 商品项 + * @return 匹配的活动规则 + */ + private RewardActivityMatchRespDTO.Rule getMaxMatchRewardActivityRule(RewardActivityMatchRespDTO rewardActivity, + List orderItems) { + // 1. 计算数量和价格 + Integer count = TradePriceCalculatorHelper.calculateTotalCount(orderItems); + Integer price = TradePriceCalculatorHelper.calculateTotalPayPrice(orderItems); + assert count != null && price != null; + + // 2. 倒序找一个最大优惠的规则 + for (int i = rewardActivity.getRules().size() - 1; i >= 0; i--) { + RewardActivityMatchRespDTO.Rule rule = rewardActivity.getRules().get(i); + if (PromotionConditionTypeEnum.PRICE.getType().equals(rewardActivity.getConditionType()) + && price >= rule.getLimit()) { + return rule; + } + if (PromotionConditionTypeEnum.COUNT.getType().equals(rewardActivity.getConditionType()) + && count >= rule.getLimit()) { + return rule; + } + } + return null; + } + + /** + * 获得满减送活动部匹配时的提示 + * + * @param rewardActivity 满减送活动 + * @return 提示 + */ + private String getRewardActivityNotMeetTip(RewardActivityMatchRespDTO rewardActivity) { + // TODO 芋艿:后面再想想;应该找第一个规则,算下还差多少即可。 + return "TODO"; + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java index bd65bddfd..78f1c7902 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreate import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressRespVO; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; import cn.iocoder.yudao.module.member.convert.address.AddressConvert; -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; import cn.iocoder.yudao.module.member.service.address.AddressService; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Parameter; @@ -54,21 +54,21 @@ public class AppAddressController { @Operation(summary = "获得用户收件地址") @Parameter(name = "id", description = "编号", required = true, example = "1024") public CommonResult getAddress(@RequestParam("id") Long id) { - AddressDO address = addressService.getAddress(getLoginUserId(), id); + MemberAddressDO address = addressService.getAddress(getLoginUserId(), id); return success(AddressConvert.INSTANCE.convert(address)); } @GetMapping("/get-default") @Operation(summary = "获得默认的用户收件地址") public CommonResult getDefaultUserAddress() { - AddressDO address = addressService.getDefaultUserAddress(getLoginUserId()); + MemberAddressDO address = addressService.getDefaultUserAddress(getLoginUserId()); return success(AddressConvert.INSTANCE.convert(address)); } @GetMapping("/list") @Operation(summary = "获得用户收件地址列表") public CommonResult> getAddressList() { - List list = addressService.getAddressList(getLoginUserId()); + List list = addressService.getAddressList(getLoginUserId()); return success(AddressConvert.INSTANCE.convertList(list)); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/address/AddressConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/address/AddressConvert.java index 49a01805d..a93d79ec1 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/address/AddressConvert.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/address/AddressConvert.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressRespVO; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -21,16 +21,16 @@ public interface AddressConvert { AddressConvert INSTANCE = Mappers.getMapper(AddressConvert.class); - AddressDO convert(AppAddressCreateReqVO bean); + MemberAddressDO convert(AppAddressCreateReqVO bean); - AddressDO convert(AppAddressUpdateReqVO bean); + MemberAddressDO convert(AppAddressUpdateReqVO bean); - AppAddressRespVO convert(AddressDO bean); + AppAddressRespVO convert(MemberAddressDO bean); - List convertList(List list); + List convertList(List list); - PageResult convertPage(PageResult page); + PageResult convertPage(PageResult page); - AddressRespDTO convert02(AddressDO bean); + AddressRespDTO convert02(MemberAddressDO bean); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/AddressDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/MemberAddressDO.java similarity index 95% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/AddressDO.java rename to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/MemberAddressDO.java index 7d8a96250..560edbba9 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/AddressDO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/MemberAddressDO.java @@ -17,7 +17,7 @@ import lombok.*; @Builder @NoArgsConstructor @AllArgsConstructor -public class AddressDO extends BaseDO { +public class MemberAddressDO extends BaseDO { /** * 编号 diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/AddressMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/AddressMapper.java index 80f78d41f..13ca89ef9 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/AddressMapper.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/AddressMapper.java @@ -2,21 +2,21 @@ package cn.iocoder.yudao.module.member.dal.mysql.address; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper -public interface AddressMapper extends BaseMapperX { +public interface AddressMapper extends BaseMapperX { - default AddressDO selectByIdAndUserId(Long id, Long userId) { - return selectOne(AddressDO::getId, id, AddressDO::getUserId, userId); + default MemberAddressDO selectByIdAndUserId(Long id, Long userId) { + return selectOne(MemberAddressDO::getId, id, MemberAddressDO::getUserId, userId); } - default List selectListByUserIdAndDefaulted(Long userId, Boolean defaulted) { - return selectList(new LambdaQueryWrapperX().eq(AddressDO::getUserId, userId) - .eqIfPresent(AddressDO::getDefaulted, defaulted)); + default List selectListByUserIdAndDefaulted(Long userId, Boolean defaulted) { + return selectList(new LambdaQueryWrapperX().eq(MemberAddressDO::getUserId, userId) + .eqIfPresent(MemberAddressDO::getDefaulted, defaulted)); } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java index 456a3d8ac..099c49c42 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.member.service.address; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; import javax.validation.Valid; import java.util.List; @@ -46,7 +46,7 @@ public interface AddressService { * @param id 编号 * @return 用户收件地址 */ - AddressDO getAddress(Long userId, Long id); + MemberAddressDO getAddress(Long userId, Long id); /** * 获得用户收件地址列表 @@ -54,7 +54,7 @@ public interface AddressService { * @param userId 用户编号 * @return 用户收件地址列表 */ - List getAddressList(Long userId); + List getAddressList(Long userId); /** * 获得用户默认的收件地址 @@ -62,6 +62,6 @@ public interface AddressService { * @param userId 用户编号 * @return 用户收件地址 */ - AddressDO getDefaultUserAddress(Long userId); + MemberAddressDO getDefaultUserAddress(Long userId); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java index bbcbbe592..488e7d32c 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java @@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; import cn.iocoder.yudao.module.member.convert.address.AddressConvert; -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; import cn.iocoder.yudao.module.member.dal.mysql.address.AddressMapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -33,12 +33,12 @@ public class AddressServiceImpl implements AddressService { public Long createAddress(Long userId, AppAddressCreateReqVO createReqVO) { // 如果添加的是默认收件地址,则将原默认地址修改为非默认 if (Boolean.TRUE.equals(createReqVO.getDefaulted())) { - List addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); - addresses.forEach(address -> addressMapper.updateById(new AddressDO().setId(address.getId()).setDefaulted(false))); + List addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); + addresses.forEach(address -> addressMapper.updateById(new MemberAddressDO().setId(address.getId()).setDefaulted(false))); } // 插入 - AddressDO address = AddressConvert.INSTANCE.convert(createReqVO); + MemberAddressDO address = AddressConvert.INSTANCE.convert(createReqVO); address.setUserId(userId); addressMapper.insert(address); // 返回 @@ -53,13 +53,13 @@ public class AddressServiceImpl implements AddressService { // 如果修改的是默认收件地址,则将原默认地址修改为非默认 if (Boolean.TRUE.equals(updateReqVO.getDefaulted())) { - List addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); + List addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); addresses.stream().filter(u -> !u.getId().equals(updateReqVO.getId())) // 排除自己 - .forEach(address -> addressMapper.updateById(new AddressDO().setId(address.getId()).setDefaulted(false))); + .forEach(address -> addressMapper.updateById(new MemberAddressDO().setId(address.getId()).setDefaulted(false))); } // 更新 - AddressDO updateObj = AddressConvert.INSTANCE.convert(updateReqVO); + MemberAddressDO updateObj = AddressConvert.INSTANCE.convert(updateReqVO); addressMapper.updateById(updateObj); } @@ -72,25 +72,25 @@ public class AddressServiceImpl implements AddressService { } private void validAddressExists(Long userId, Long id) { - AddressDO addressDO = getAddress(userId, id); + MemberAddressDO addressDO = getAddress(userId, id); if (addressDO == null) { throw exception(ADDRESS_NOT_EXISTS); } } @Override - public AddressDO getAddress(Long userId, Long id) { + public MemberAddressDO getAddress(Long userId, Long id) { return addressMapper.selectByIdAndUserId(id, userId); } @Override - public List getAddressList(Long userId) { + public List getAddressList(Long userId) { return addressMapper.selectListByUserIdAndDefaulted(userId, null); } @Override - public AddressDO getDefaultUserAddress(Long userId) { - List addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); + public MemberAddressDO getDefaultUserAddress(Long userId) { + List addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); return CollUtil.getFirst(addresses); } diff --git a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java index 6ddf80a0e..77b40705e 100644 --- a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java +++ b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.member.service.address; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; import cn.iocoder.yudao.module.member.dal.mysql.address.AddressMapper; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; @@ -42,14 +42,14 @@ public class AddressServiceImplTest extends BaseDbUnitTest { // 断言 assertNotNull(addressId); // 校验记录的属性是否正确 - AddressDO address = addressMapper.selectById(addressId); + MemberAddressDO address = addressMapper.selectById(addressId); assertPojoEquals(reqVO, address); } @Test public void testUpdateAddress_success() { // mock 数据 - AddressDO dbAddress = randomPojo(AddressDO.class); + MemberAddressDO dbAddress = randomPojo(MemberAddressDO.class); addressMapper.insert(dbAddress);// @Sql: 先插入出一条存在的数据 // 准备参数 AppAddressUpdateReqVO reqVO = randomPojo(AppAddressUpdateReqVO.class, o -> { @@ -59,7 +59,7 @@ public class AddressServiceImplTest extends BaseDbUnitTest { // 调用 addressService.updateAddress(dbAddress.getUserId(), reqVO); // 校验是否更新正确 - AddressDO address = addressMapper.selectById(reqVO.getId()); // 获取最新的 + MemberAddressDO address = addressMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, address); } @@ -75,7 +75,7 @@ public class AddressServiceImplTest extends BaseDbUnitTest { @Test public void testDeleteAddress_success() { // mock 数据 - AddressDO dbAddress = randomPojo(AddressDO.class); + MemberAddressDO dbAddress = randomPojo(MemberAddressDO.class); addressMapper.insert(dbAddress);// @Sql: 先插入出一条存在的数据 // 准备参数 Long id = dbAddress.getId(); From 0631c51d93aec31c42533bf54b30b2dfc6f84d3e Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 28 May 2023 20:09:51 +0800 Subject: [PATCH 6/6] =?UTF-8?q?mall=20+=20trade=EF=BC=9Areview=20=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E7=AE=A1=E7=90=86=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/util/string/StrUtils.java | 5 +- .../mybatis/core/mapper/BaseMapperX.java | 2 +- .../promotion/api/coupon/CouponApi.java | 10 + .../api/coupon/dto/CouponRespDTO.java | 109 ++++ .../api/coupon/dto/CouponValidReqDTO.java | 27 + .../api/discount/DiscountActivityApi.java | 23 + .../discount/dto/DiscountProductRespDTO.java} | 18 +- .../module/promotion/api/package-info.java | 4 - .../api/price/dto/PriceCalculateReqDTO.java | 5 + .../api/price/dto/PriceCalculateRespDTO.java | 10 +- .../api/reward/RewardActivityApi.java | 24 + .../dto/RewardActivityMatchRespDTO.java | 77 +++ .../enums/common/PromotionLevelEnum.java | 40 -- .../enums/common/PromotionTypeEnum.java | 3 +- .../promotion/api/coupon/CouponApiImpl.java | 10 + .../api/discount/DiscountActivityApiImpl.java | 28 ++ .../promotion/api/discount/package-info.java | 1 - .../api/reward/RewardActivityApiImpl.java | 27 + .../convert/coupon/CouponConvert.java | 3 + .../discount/DiscountActivityConvert.java | 20 +- .../discount/DiscountActivityDO.java | 7 +- .../discount/DiscountProductDO.java | 3 + .../dataobject/reward/RewardActivityDO.java | 1 + .../discount/DiscountActivityService.java | 4 +- .../discount/DiscountActivityServiceImpl.java | 42 +- .../promotion/service/price/PriceService.java | 9 - .../service/price/PriceServiceImpl.java | 466 +----------------- .../service/reward/RewardActivityService.java | 9 +- .../reward/RewardActivityServiceImpl.java | 37 +- .../service/price/PriceServiceTest.java | 30 +- .../trade/enums/ErrorCodeConstants.java | 4 + .../delivery/DeliveryExpressController.java | 3 +- .../DeliveryExpressTemplateController.java | 31 +- .../{ => express}/DeliveryExpressBaseVO.java | 2 +- .../DeliveryExpressCreateReqVO.java | 4 +- .../{ => express}/DeliveryExpressExcelVO.java | 2 +- .../DeliveryExpressExportReqVO.java | 2 +- .../DeliveryExpressPageReqVO.java | 2 +- .../{ => express}/DeliveryExpressRespVO.java | 2 +- .../DeliveryExpressUpdateReqVO.java | 10 +- .../DeliveryExpressTemplateBaseVO.java | 2 +- .../DeliveryExpressTemplateCreateReqVO.java | 11 +- .../DeliveryExpressTemplatePageReqVO.java | 10 +- .../DeliveryExpressTemplateRespVO.java | 2 +- .../DeliveryExpressTemplateSimpleRespVO.java | 3 +- .../DeliveryExpressTemplateUpdateReqVO.java | 14 +- .../ExpressTemplateChargeBaseVO.java | 2 +- .../ExpressTemplateChargeUpdateVO.java | 8 +- .../ExpressTemplateFreeBaseVO.java | 3 +- .../ExpressTemplateFreeUpdateVO.java | 4 +- .../delivery/DeliveryExpressConvert.java | 8 +- .../DeliveryExpressTemplateConvert.java | 5 +- .../mysql/delivery/DeliveryExpressMapper.java | 4 +- .../DeliveryExpressTemplateMapper.java | 2 +- .../delivery/DeliveryExpressService.java | 8 +- .../delivery/DeliveryExpressServiceImpl.java | 8 +- .../DeliveryExpressTemplateService.java | 11 +- .../DeliveryExpressTemplateServiceImpl.java | 49 +- .../service/price/TradePriceService.java | 21 + .../service/price/TradePriceServiceImpl.java | 73 +++ .../price/bo/TradePriceCalculateReqBO.java | 86 ++++ .../price/bo/TradePriceCalculateRespBO.java | 249 ++++++++++ .../TradeCouponPriceCalculator.java | 109 ++++ .../TradeDiscountActivityPriceCalculator.java | 80 +++ .../calculator/TradePriceCalculator.java | 19 + .../TradePriceCalculatorHelper.java | 221 +++++++++ .../TradeRewardActivityPriceCalculator.java | 133 +++++ .../app/address/AppAddressController.java | 8 +- .../convert/address/AddressConvert.java | 14 +- .../{AddressDO.java => MemberAddressDO.java} | 2 +- .../dal/mysql/address/AddressMapper.java | 14 +- .../service/address/AddressService.java | 8 +- .../service/address/AddressServiceImpl.java | 24 +- .../address/AddressServiceImplTest.java | 10 +- .../module/system/convert/ip/AreaConvert.java | 5 +- 75 files changed, 1588 insertions(+), 758 deletions(-) create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponRespDTO.java create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApi.java rename yudao-module-mall/{yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/bo/DiscountProductDetailBO.java => yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java} (72%) delete mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/package-info.java create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/dto/RewardActivityMatchRespDTO.java delete mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionLevelEnum.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java delete mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/package-info.java create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => express}/DeliveryExpressBaseVO.java (98%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => express}/DeliveryExpressCreateReqVO.java (84%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => express}/DeliveryExpressExcelVO.java (98%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => express}/DeliveryExpressExportReqVO.java (98%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => express}/DeliveryExpressPageReqVO.java (98%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => express}/DeliveryExpressRespVO.java (97%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => express}/DeliveryExpressUpdateReqVO.java (77%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => expresstemplate}/DeliveryExpressTemplateBaseVO.java (97%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => expresstemplate}/DeliveryExpressTemplateCreateReqVO.java (77%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => expresstemplate}/DeliveryExpressTemplatePageReqVO.java (90%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => expresstemplate}/DeliveryExpressTemplateRespVO.java (97%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => expresstemplate}/DeliveryExpressTemplateSimpleRespVO.java (82%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => expresstemplate}/DeliveryExpressTemplateUpdateReqVO.java (77%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => expresstemplate}/ExpressTemplateChargeBaseVO.java (98%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => expresstemplate}/ExpressTemplateChargeUpdateVO.java (61%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => expresstemplate}/ExpressTemplateFreeBaseVO.java (97%) rename yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/{ => expresstemplate}/ExpressTemplateFreeUpdateVO.java (72%) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceService.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculator.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java rename yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/{AddressDO.java => MemberAddressDO.java} (95%) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java index 2ac7278a4..cd5db713c 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java @@ -40,15 +40,14 @@ public class StrUtils { return false; } - public static List splitToLong(String value, CharSequence separator) { + public static List splitToLong(String value, CharSequence separator) { long[] longs = StrUtil.splitToLong(value, separator); return Arrays.stream(longs).boxed().collect(Collectors.toList()); } - public static List splitToInteger(String value, CharSequence separator) { + public static List splitToInteger(String value, CharSequence separator) { int[] integers = StrUtil.splitToInt(value, separator); return Arrays.stream(integers).boxed().collect(Collectors.toList()); } - } diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java index 7788d2895..5dee2ba00 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java @@ -113,7 +113,7 @@ public interface BaseMapperX extends MPJBaseMapper { Db.saveBatch(entities, size); } - // @芋艿 是不是叫 updateByDo 或者 updateByEntity 更合适 + // @芋艿 是不是叫 updateByDo 或者 updateByEntity 更合适;回复:因为是使用实体作为条件去批量更新,所以没加 ByEntity,保持和 mybatis plus 风格一致 default void updateBatch(T update) { update(update, new QueryWrapper<>()); } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java index f99ff815f..ce7a712da 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.promotion.api.coupon; +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; import javax.validation.Valid; @@ -18,4 +20,12 @@ public interface CouponApi { */ void useCoupon(@Valid CouponUseReqDTO useReqDTO); + /** + * 校验优惠劵 + * + * @param validReqDTO 校验请求 + * @return 优惠劵 + */ + CouponRespDTO validateCoupon(@Valid CouponValidReqDTO validReqDTO); + } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponRespDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponRespDTO.java new file mode 100644 index 000000000..34031e604 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponRespDTO.java @@ -0,0 +1,109 @@ +package cn.iocoder.yudao.module.promotion.api.coupon.dto; + +import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 优惠劵 Response DTO + * + * @author 芋道源码 + */ +@Data +public class CouponRespDTO { + + // ========== 基本信息 BEGIN ========== + /** + * 优惠劵编号 + */ + private Long id; + /** + * 优惠劵模板编号 + */ + private Integer templateId; + /** + * 优惠劵名 + */ + private String name; + /** + * 优惠码状态 + * + * 枚举 {@link CouponStatusEnum} + */ + private Integer status; + + // ========== 基本信息 END ========== + + // ========== 领取情况 BEGIN ========== + /** + * 用户编号 + * + * 关联 MemberUserDO 的 id 字段 + */ + private Long userId; + /** + * 领取类型 + * + * 枚举 {@link CouponTakeTypeEnum} + */ + private Integer takeType; + // ========== 领取情况 END ========== + + // ========== 使用规则 BEGIN ========== + /** + * 是否设置满多少金额可用,单位:分 + */ + private Integer usePrice; + /** + * 生效开始时间 + */ + private LocalDateTime validStartTime; + /** + * 生效结束时间 + */ + private LocalDateTime validEndTime; + /** + * 商品范围 + */ + private Integer productScope; + /** + * 商品 SPU 编号的数组 + */ + private List productSpuIds; + // ========== 使用规则 END ========== + + // ========== 使用效果 BEGIN ========== + /** + * 折扣类型 + */ + private Integer discountType; + /** + * 折扣百分比 + */ + private Integer discountPercent; + /** + * 优惠金额,单位:分 + */ + private Integer discountPrice; + /** + * 折扣上限,仅在 {@link #discountType} 等于 {@link PromotionDiscountTypeEnum#PERCENT} 时生效 + */ + private Integer discountLimitPrice; + // ========== 使用效果 END ========== + + // ========== 使用情况 BEGIN ========== + /** + * 使用订单号 + */ + private Long useOrderId; + /** + * 使用时间 + */ + private LocalDateTime useTime; + + // ========== 使用情况 END ========== +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java new file mode 100644 index 000000000..dd25c6408 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.promotion.api.coupon.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 优惠劵使用 Request DTO + * + * @author 芋道源码 + */ +@Data +public class CouponValidReqDTO { + + /** + * 优惠劵编号 + */ + @NotNull(message = "优惠劵编号不能为空") + private Long id; + + /** + * 用户编号 + */ + @NotNull(message = "用户编号不能为空") + private Long userId; + +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApi.java new file mode 100644 index 000000000..b25f67d9f --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApi.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.promotion.api.discount; + +import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; + +import java.util.Collection; +import java.util.List; + +/** + * 限时折扣 API 接口 + * + * @author 芋道源码 + */ +public interface DiscountActivityApi { + + /** + * 获得商品匹配的的限时折扣信息 + * + * @param skuIds 商品 SKU 编号数组 + * @return 限时折扣信息 + */ + List getMatchDiscountProductList(Collection skuIds); + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/bo/DiscountProductDetailBO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java similarity index 72% rename from yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/bo/DiscountProductDetailBO.java rename to yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java index 7b8f4a20f..52dfdbe27 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/bo/DiscountProductDetailBO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java @@ -1,25 +1,19 @@ -package cn.iocoder.yudao.module.promotion.service.discount.bo; +package cn.iocoder.yudao.module.promotion.api.discount.dto; import lombok.Data; /** - * 限时折扣活动商品 BO + * 限时折扣活动商品 Response DTO * * @author 芋道源码 */ @Data -public class DiscountProductDetailBO { - - // ========== DiscountProductDO 字段 ========== +public class DiscountProductRespDTO { /** * 编号,主键自增 */ private Long id; - /** - * 限时折扣活动的编号 - */ - private Long activityId; /** * 商品 SPU 编号 */ @@ -41,7 +35,11 @@ public class DiscountProductDetailBO { */ private Integer discountPrice; - // ========== DiscountActivityDO 字段 ========== + // ========== 活动字段 ========== + /** + * 限时折扣活动的编号 + */ + private Long activityId; /** * 活动标题 */ diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/package-info.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/package-info.java deleted file mode 100644 index 08e1020a6..000000000 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 占位 - */ -package cn.iocoder.yudao.module.promotion.api; diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateReqDTO.java index 01f0ac220..ce53de50e 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateReqDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateReqDTO.java @@ -26,6 +26,11 @@ public class PriceCalculateReqDTO { */ private Long couponId; + /** + * 收货地址编号 + */ + private Long addressId; + /** * 商品 SKU 数组 */ diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateRespDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateRespDTO.java index a067aa0b5..9a98029b7 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateRespDTO.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateRespDTO.java @@ -24,6 +24,7 @@ import java.util.List; * @author 芋道源码 */ @Data +@Deprecated public class PriceCalculateRespDTO { /** @@ -174,6 +175,7 @@ public class PriceCalculateRespDTO { * 营销明细 */ @Data + @Deprecated public static class Promotion { /** @@ -216,14 +218,14 @@ public class PriceCalculateRespDTO { /** * 是否满足优惠条件 */ - private Boolean meet; + private Boolean match; /** * 满足条件的提示 * - * 如果 {@link #meet} = true 满足,则提示“圣诞价:省 150.00 元” - * 如果 {@link #meet} = false 不满足,则提示“购满 85 元,可减 40 元” + * 如果 {@link #match} = true 满足,则提示“圣诞价:省 150.00 元” + * 如果 {@link #match} = false 不满足,则提示“购满 85 元,可减 40 元” */ - private String meetTip; + private String description; } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java new file mode 100644 index 000000000..efeddf3d5 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.promotion.api.reward; + +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; + +import java.util.Collection; +import java.util.List; + +/** + * 满减送活动 API 接口 + * + * @author 芋道源码 + */ +public interface RewardActivityApi { + + + /** + * 基于指定的 SPU 编号数组,获得它们匹配的满减送活动 + * + * @param spuIds SPU 编号数组 + * @return 满减送活动列表 + */ + List getMatchRewardActivityList(Collection spuIds); + +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/dto/RewardActivityMatchRespDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/dto/RewardActivityMatchRespDTO.java new file mode 100644 index 000000000..19f46a49a --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/dto/RewardActivityMatchRespDTO.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.promotion.api.reward.dto; + +import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum; +import lombok.Data; + +import java.util.List; + +/** + * 满减送活动的匹配 Response DTO + * + * @author 芋道源码 + */ +@Data +public class RewardActivityMatchRespDTO { + + /** + * 活动编号,主键自增 + */ + private Long id; + /** + * 活动标题 + */ + private String name; + /** + * 条件类型 + * + * 枚举 {@link PromotionConditionTypeEnum} + */ + private Integer conditionType; + /** + * 优惠规则的数组 + */ + private List rules; + + /** + * 商品 SPU 编号的数组 + */ + private List spuIds; + + // TODO 芋艿:后面 RewardActivityRespDTO 有了之后,Rule 可以放过去 + /** + * 优惠规则 + */ + @Data + public static class Rule { + + /** + * 优惠门槛 + * + * 1. 满 N 元,单位:分 + * 2. 满 N 件 + */ + private Integer limit; + /** + * 优惠价格,单位:分 + */ + private Integer discountPrice; + /** + * 是否包邮 + */ + private Boolean freeDelivery; + /** + * 赠送的积分 + */ + private Integer point; + /** + * 赠送的优惠劵编号的数组 + */ + private List couponIds; + /** + * 赠送的优惠卷数量的数组 + */ + private List couponCounts; + + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionLevelEnum.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionLevelEnum.java deleted file mode 100644 index ed0564a70..000000000 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionLevelEnum.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.yudao.module.promotion.enums.common; - -import cn.iocoder.yudao.framework.common.core.IntArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * 营销的级别枚举 - * - * 参考有赞:营销级别 - * - * @author 芋道源码 - */ -@Getter -@AllArgsConstructor -public enum PromotionLevelEnum implements IntArrayValuable { - - ORDER(1, "订单级"), // 多个商品,进行组合后优惠。例如说:满减送、打包一口价、第二件半价 - SKU(2, "商品级"), // 单个商品,直接优惠。例如说:限时折扣、会员折扣 - COUPON(3, "优惠劵"), // 多个商品,进行组合后优惠。例如说:优惠劵 - ; - - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionLevelEnum::getLevel).toArray(); - - /** - * 级别值 - */ - private final Integer level; - /** - * 类型名 - */ - private final String name; - - @Override - public int[] array() { - return ARRAYS; - } -} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionTypeEnum.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionTypeEnum.java index eea48f7dc..ee87306bf 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionTypeEnum.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionTypeEnum.java @@ -18,7 +18,7 @@ public enum PromotionTypeEnum implements IntArrayValuable { DISCOUNT_ACTIVITY(1, "限时折扣"), REWARD_ACTIVITY(2, "满减送"), - MEMBER(3, "会员折扣"), + MEMBER(3, "会员折扣"), // TODO 芋艿:待实现 StrUtil.format("会员折扣:省 {} 元", formatPrice(orderItem.getPayPrice() - memberPrice) COUPON(4, "优惠劵") ; @@ -37,4 +37,5 @@ public enum PromotionTypeEnum implements IntArrayValuable { public int[] array() { return ARRAYS; } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java index 349eba1ff..a06ab57cd 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java @@ -1,7 +1,11 @@ package cn.iocoder.yudao.module.promotion.api.coupon; +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; +import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; import org.springframework.stereotype.Service; @@ -24,4 +28,10 @@ public class CouponApiImpl implements CouponApi { useReqDTO.getOrderId()); } + @Override + public CouponRespDTO validateCoupon(CouponValidReqDTO validReqDTO) { + CouponDO coupon = couponService.validCoupon(validReqDTO.getId(), validReqDTO.getUserId()); + return CouponConvert.INSTANCE.convert(coupon); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java new file mode 100644 index 000000000..2227da43e --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.promotion.api.discount; + +import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; +import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert; +import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; + +/** + * 限时折扣 API 实现类 + * + * @author 芋道源码 + */ +@Service +public class DiscountActivityApiImpl implements DiscountActivityApi { + + @Resource + private DiscountActivityService discountActivityService; + + @Override + public List getMatchDiscountProductList(Collection skuIds) { + return DiscountActivityConvert.INSTANCE.convertList02(discountActivityService.getMatchDiscountProductList(skuIds)); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/package-info.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/package-info.java deleted file mode 100644 index 4e3ce77a8..000000000 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.promotion.api.discount; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java new file mode 100644 index 000000000..ee8bac7c9 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.promotion.api.reward; + +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; +import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Collection; +import java.util.List; + +/** + * 满减送活动 API 实现类 + * + * @author 芋道源码 + */ +@Service +public class RewardActivityApiImpl implements RewardActivityApi { + + @Resource + private RewardActivityService rewardActivityService; + + @Override + public List getMatchRewardActivityList(Collection spuIds) { + return rewardActivityService.getMatchRewardActivityList(spuIds); + } + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java index 281318f7d..7bfdca706 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.promotion.convert.coupon; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageItemRespVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; import org.mapstruct.Mapper; @@ -18,4 +19,6 @@ public interface CouponConvert { PageResult convertPage(PageResult page); + CouponRespDTO convert(CouponDO bean); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java index 07d2e03ab..ebf53ce8a 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java @@ -2,18 +2,15 @@ package cn.iocoder.yudao.module.promotion.convert.discount; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.*; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; -import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; import java.util.List; -import java.util.Map; /** * 限时折扣活动 Convert @@ -33,20 +30,10 @@ public interface DiscountActivityConvert { List convertList(List list); + List convertList02(List list); + PageResult convertPage(PageResult page); - DiscountProductDetailBO convert(DiscountProductDO product); - - default List convertList(List products, Map activityMap) { - return CollectionUtils.convertList(products, product -> { - DiscountProductDetailBO detail = convert(product); - MapUtils.findAndThen(activityMap, product.getActivityId(), activity -> { - detail.setActivityName(activity.getName()); - }); - return detail; - }); - } - DiscountProductDO convert(DiscountActivityBaseVO.Product bean); DiscountActivityDetailRespVO convert(DiscountActivityDO activity, List products); @@ -99,4 +86,5 @@ public interface DiscountActivityConvert { return true; } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountActivityDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountActivityDO.java index 91071f309..fd0726e39 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountActivityDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountActivityDO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.promotion.dal.dataobject.discount; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -33,10 +33,13 @@ public class DiscountActivityDO extends BaseDO { * 活动标题 */ private String name; + // TODO 芋艿:状态调整,只有开启和关闭; /** * 状态 * - * 枚举 {@link PromotionActivityStatusEnum} + * 枚举 {@link CommonStatusEnum} + * + * 活动被关闭后,不允许再次开启。 */ private Integer status; /** diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java index 55c924e4f..7f61f7f6d 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountProductDO.java @@ -24,12 +24,15 @@ public class DiscountProductDO extends BaseDO { */ @TableId private Long id; + + // TODO 芋艿:把 activity 所有的字段冗余过来 /** * 限时折扣活动的编号 * * 关联 {@link DiscountActivityDO#getId()} */ private Long activityId; + /** * 商品 SPU 编号 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/reward/RewardActivityDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/reward/RewardActivityDO.java index e825881d1..9d417d75f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/reward/RewardActivityDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/reward/RewardActivityDO.java @@ -38,6 +38,7 @@ public class RewardActivityDO extends BaseDO { * 活动标题 */ private String name; + // TODO @芋艿:改成开启、禁用两种状态 /** * 状态 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java index 8b6e5895b..7473f12cd 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java @@ -6,12 +6,10 @@ import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountAc import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; -import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO; import javax.validation.Valid; import java.util.Collection; import java.util.List; -import java.util.Map; /** * 限时折扣 Service 接口 @@ -28,7 +26,7 @@ public interface DiscountActivityService { * @param skuIds SKU 编号数组 * @return 匹配的限时折扣商品 */ - Map getMatchDiscountProducts(Collection skuIds); + List getMatchDiscountProductList(Collection skuIds); /** * 创建限时折扣活动 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java index df54d44f2..97d70491b 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.promotion.service.discount; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityBaseVO; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO; @@ -14,18 +13,17 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProduct import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountActivityMapper; import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper; import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; -import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO; import cn.iocoder.yudao.module.promotion.util.PromotionUtils; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.*; +import java.util.Collection; +import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; -import static java.util.Arrays.asList; /** * 限时折扣 Service 实现类 @@ -42,9 +40,9 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { private DiscountProductMapper discountProductMapper; @Override - public Map getMatchDiscountProducts(Collection skuIds) { - List discountProducts = getRewardProductListBySkuIds(skuIds, singleton(PromotionActivityStatusEnum.RUN.getStatus())); - return convertMap(discountProducts, DiscountProductDetailBO::getSkuId); + public List getMatchDiscountProductList(Collection skuIds) { + // TODO 芋艿:开启、满足 skuId、日期内 + return null; } @Override @@ -101,6 +99,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { } } + // TODO 芋艿:校验逻辑简化,只查询时间冲突的活动,开启状态的。 /** * 校验商品是否冲突 * @@ -112,9 +111,10 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { return; } // 查询商品参加的活动 - List discountActivityProductList = getRewardProductListBySkuIds( - convertSet(products, DiscountActivityBaseVO.Product::getSkuId), - asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus())); + List discountActivityProductList = null; +// getRewardProductListBySkuIds( +// convertSet(products, DiscountActivityBaseVO.Product::getSkuId), +// asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus())); if (id != null) { // 排除自己这个活动 discountActivityProductList.removeIf(product -> id.equals(product.getActivityId())); } @@ -124,24 +124,6 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { } } - private List getRewardProductListBySkuIds(Collection skuIds, - Collection statuses) { - // 查询商品 - List products = discountProductMapper.selectListBySkuId(skuIds); - if (CollUtil.isEmpty(products)) { - return new ArrayList<>(0); - } - - // 查询活动 - List activities = discountActivityMapper.selectBatchIds(skuIds); - activities.removeIf(activity -> !statuses.contains(activity.getStatus())); // 移除不满足 statuses 状态的 - Map activityMap = CollectionUtils.convertMap(activities, DiscountActivityDO::getId); - - // 移除不满足活动的商品 - products.removeIf(product -> !activityMap.containsKey(product.getActivityId())); - return DiscountActivityConvert.INSTANCE.convertList(products, activityMap); - } - @Override public void closeRewardActivity(Long id) { // 校验存在 @@ -153,7 +135,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { throw exception(DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_END); } - // 更新 + // 更新为关闭。 DiscountActivityDO updateObj = new DiscountActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus()); discountActivityMapper.updateById(updateObj); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceService.java index a7420e119..f402cb1be 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceService.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.service.price; import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO; import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO; -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; import java.util.List; @@ -13,14 +12,6 @@ import java.util.List; */ public interface PriceService { - /** - * 计算商品的价格 - * - * @param calculateReqDTO 价格请求 - * @return 价格响应 - */ - PriceCalculateRespDTO calculatePrice(PriceCalculateReqDTO calculateReqDTO); - /** * 获得优惠劵的匹配信息列表 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java index 7aab0bee5..439c03d37 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java @@ -1,39 +1,25 @@ package cn.iocoder.yudao.module.promotion.service.price; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO; import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO; import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; import cn.iocoder.yudao.module.promotion.convert.price.PriceConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; -import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; -import cn.iocoder.yudao.module.promotion.enums.common.*; import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; -import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService; -import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO; -import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService; -import com.google.common.base.Suppliers; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.*; -import java.util.function.Supplier; +import java.util.Collections; +import java.util.List; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; -import static java.util.Collections.singletonList; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_VALID_TIME_NOT_NOW; /** * 价格计算 Service 实现类 @@ -54,43 +40,14 @@ import static java.util.Collections.singletonList; @Slf4j public class PriceServiceImpl implements PriceService { - @Resource - private DiscountActivityService discountService; - @Resource - private RewardActivityService rewardActivityService; @Resource private CouponService couponService; - @Resource - private ProductSkuApi productSkuApi; - - @Override - public PriceCalculateRespDTO calculatePrice(PriceCalculateReqDTO calculateReqDTO) { - // 获得商品 SKU 数组 - List skuList = checkSkus(calculateReqDTO); - // 初始化 PriceCalculateRespDTO 对象 - PriceCalculateRespDTO priceCalculate = PriceConvert.INSTANCE.convert(calculateReqDTO, skuList); - - // 计算商品级别的价格 - calculatePriceForSkuLevel(calculateReqDTO.getUserId(), priceCalculate); - // 计算订单级别的价格 - calculatePriceForOrderLevel(calculateReqDTO.getUserId(), priceCalculate); - // 计算优惠劵级别的价格 - calculatePriceForCouponLevel(calculateReqDTO.getUserId(), calculateReqDTO.getCouponId(), priceCalculate); - - // 如果最终支付金额小于等于 0,则抛出业务异常 - if (priceCalculate.getOrder().getPayPrice() <= 0) { - log.error("[calculatePrice][价格计算不正确,请求 calculateReqDTO({}),结果 priceCalculate({})]", - calculateReqDTO, priceCalculate); - throw exception(PRICE_CALCULATE_PAY_PRICE_ILLEGAL); - } - return priceCalculate; - } - @Override public List getMeetCouponList(PriceCalculateReqDTO calculateReqDTO) { // 先计算一轮价格 - PriceCalculateRespDTO priceCalculate = calculatePrice(calculateReqDTO); +// PriceCalculateRespDTO priceCalculate = calculatePrice(calculateReqDTO); + PriceCalculateRespDTO priceCalculate = null; // 获得用户的待使用优惠劵 List couponList = couponService.getCouponList(calculateReqDTO.getUserId(), CouponStatusEnum.UNUSED.getStatus()); @@ -106,7 +63,9 @@ public class PriceServiceImpl implements PriceService { couponService.validCoupon(coupon); // 获得匹配的商品 SKU 数组 - List orderItems = getMatchCouponOrderItems(priceCalculate, coupon); + // TODO 芋艿:后续处理 +// List orderItems = getMatchCouponOrderItems(priceCalculate, coupon); + List orderItems = null; if (CollUtil.isEmpty(orderItems)) { return couponMeetRespDTO.setMeet(false).setMeetTip("所结算商品没有符合条件的商品"); } @@ -134,413 +93,4 @@ public class PriceServiceImpl implements PriceService { }); } - private List checkSkus(PriceCalculateReqDTO calculateReqDTO) { - // 获得商品 SKU 数组 - Map skuIdCountMap = CollectionUtils.convertMap(calculateReqDTO.getItems(), - PriceCalculateReqDTO.Item::getSkuId, PriceCalculateReqDTO.Item::getCount); - List skus = productSkuApi.getSkuList(skuIdCountMap.keySet()); - - // 校验商品 SKU - skus.forEach(sku -> { - Integer count = skuIdCountMap.get(sku.getId()); - if (count == null) { - throw exception(SKU_NOT_EXISTS); - } - // 不校验库存不足,避免购物车场景,商品无货的情况 - }); - return skus; - } - - // ========== 计算商品级别的价格 ========== - - /** - * 计算商品级别的价格,例如说: - * 1. 会员折扣 - * 2. 限时折扣 {@link cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO} - * - * 其中,会员折扣、限时折扣取最低价 - * - * @param userId 用户编号 - * @param priceCalculate 价格计算的结果 - */ - private void calculatePriceForSkuLevel(Long userId, PriceCalculateRespDTO priceCalculate) { - // 获取 SKU 级别的所有优惠信息 - Supplier memberDiscountPercentSupplier = getMemberDiscountPercentSupplier(userId); - Map discountProducts = discountService.getMatchDiscountProducts( - convertSet(priceCalculate.getOrder().getItems(), PriceCalculateRespDTO.OrderItem::getSkuId)); - - // 处理每个 SKU 的优惠 - priceCalculate.getOrder().getItems().forEach(orderItem -> { - // 获取该 SKU 的优惠信息 - Double memberDiscountPercent = memberDiscountPercentSupplier.get(); - DiscountProductDetailBO discountProduct = discountProducts.get(orderItem.getSkuId()); - if (memberDiscountPercent == null && discountProduct == null) { - return; - } - // 计算价格,判断选择哪个折扣 - Integer memberPrice = memberDiscountPercent != null ? (int) (orderItem.getPayPrice() * memberDiscountPercent / 100) : null; - Integer promotionPrice = discountProduct != null ? getDiscountProductPrice(discountProduct, orderItem) : null; - if (memberPrice == null) { - calculatePriceByDiscountActivity(priceCalculate, orderItem, discountProduct, promotionPrice); - } else if (promotionPrice == null) { - calculatePriceByMemberDiscount(priceCalculate, orderItem, memberPrice); - } else if (memberPrice < promotionPrice) { - calculatePriceByDiscountActivity(priceCalculate, orderItem, discountProduct, promotionPrice); - } else { - calculatePriceByMemberDiscount(priceCalculate, orderItem, memberPrice); - } - }); - } - - private Integer getDiscountProductPrice(DiscountProductDetailBO discountProduct, - PriceCalculateRespDTO.OrderItem orderItem) { - Integer price = orderItem.getPayPrice(); - if (PromotionDiscountTypeEnum.PRICE.getType().equals(discountProduct.getDiscountType())) { // 减价 - price -= discountProduct.getDiscountPrice() * orderItem.getCount(); - } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(discountProduct.getDiscountType())) { // 打折 - price = price * discountProduct.getDiscountPercent() / 100; - } else { - throw new IllegalArgumentException(String.format("优惠活动的商品(%s) 的优惠类型不正确", discountProduct)); - } - return price; - } - - private void calculatePriceByMemberDiscount(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem, - Integer memberPrice) { - // 记录优惠明细 - addPromotion(priceCalculate, orderItem, null, PromotionTypeEnum.MEMBER.getName(), - PromotionTypeEnum.MEMBER.getType(), PromotionLevelEnum.SKU.getLevel(), memberPrice, - true, StrUtil.format("会员折扣:省 {} 元", formatPrice(orderItem.getPayPrice() - memberPrice))); - // 修改 SKU 的优惠 - modifyOrderItemPayPrice(orderItem, memberPrice, priceCalculate); - } - - private void calculatePriceByDiscountActivity(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem, - DiscountProductDetailBO discountProduct, Integer promotionPrice) { - // 记录优惠明细 - addPromotion(priceCalculate, orderItem, discountProduct.getActivityId(), discountProduct.getActivityName(), - PromotionTypeEnum.DISCOUNT_ACTIVITY.getType(), PromotionLevelEnum.SKU.getLevel(), promotionPrice, - true, StrUtil.format("限时折扣:省 {} 元", formatPrice(orderItem.getPayPrice() - promotionPrice))); - // 修改 SKU 的优惠 - modifyOrderItemPayPrice(orderItem, promotionPrice, priceCalculate); - } - - // TODO 芋艿:提前实现 - private Supplier getMemberDiscountPercentSupplier(Long userId) { - return Suppliers.memoize(() -> { - if (userId == 1) { - return 90d; - } - if (userId == 2) { - return 80d; - } - return null; // 无优惠 - }); - } - - // ========== 计算商品级别的价格 ========== - - /** - * 计算订单级别的价格,例如说: - * 1. 满减送 {@link cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO} - * - * @param userId 用户编号 - * @param priceCalculate 价格计算的结果 - */ - @SuppressWarnings("unused") - private void calculatePriceForOrderLevel(Long userId, PriceCalculateRespDTO priceCalculate) { - // 获取 SKU 级别的所有优惠信息 - Set spuIds = convertSet(priceCalculate.getOrder().getItems(), PriceCalculateRespDTO.OrderItem::getSpuId); - Map> rewardActivities = rewardActivityService.getMatchRewardActivities(spuIds); - - // 处理满减送活动 - if (CollUtil.isNotEmpty(rewardActivities)) { - rewardActivities.forEach((rewardActivity, activitySpuIds) -> { - List orderItems = CollectionUtils.filterList(priceCalculate.getOrder().getItems(), - orderItem -> CollUtil.contains(activitySpuIds, orderItem.getSpuId())); - calculatePriceByRewardActivity(priceCalculate, orderItems, rewardActivity); - }); - } - } - - private void calculatePriceByRewardActivity(PriceCalculateRespDTO priceCalculate, List orderItems, - RewardActivityDO rewardActivity) { - // 获得最大匹配的满减送活动的规则 - RewardActivityDO.Rule rule = getLastMatchRewardActivityRule(rewardActivity, orderItems); - if (rule == null) { - // 获取不到的情况下,记录不满足的优惠明细 - addNotMeetPromotion(priceCalculate, orderItems, rewardActivity.getId(), rewardActivity.getName(), - PromotionTypeEnum.REWARD_ACTIVITY.getType(), PromotionLevelEnum.ORDER.getLevel(), - getRewardActivityNotMeetTip(rewardActivity)); - return; - } - - // 分摊金额 - List discountPartPrices = dividePrice(orderItems, rule.getDiscountPrice()); - // 记录优惠明细 - addPromotion(priceCalculate, orderItems, rewardActivity.getId(), rewardActivity.getName(), - PromotionTypeEnum.REWARD_ACTIVITY.getType(), PromotionLevelEnum.ORDER.getLevel(), discountPartPrices, - true, StrUtil.format("满减送:省 {} 元", formatPrice(rule.getDiscountPrice()))); - // 修改 SKU 的分摊 - for (int i = 0; i < orderItems.size(); i++) { - modifyOrderItemOrderPartPriceFromDiscountPrice(orderItems.get(i), discountPartPrices.get(i), priceCalculate); - } - } - - /** - * 获得最大匹配的满减送活动的规则 - * - * @param rewardActivity 满减送活动 - * @param orderItems 商品项 - * @return 匹配的活动规则 - */ - private RewardActivityDO.Rule getLastMatchRewardActivityRule(RewardActivityDO rewardActivity, - List orderItems) { - Integer count = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getCount, Integer::sum); - // price 的计算逻辑,使用 orderDividePrice 的原因,主要考虑分摊后,这个才是该 SKU 当前真实的支付总价 - Integer price = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum); - assert count != null && price != null; - for (int i = rewardActivity.getRules().size() - 1; i >= 0; i--) { - RewardActivityDO.Rule rule = rewardActivity.getRules().get(i); - if (PromotionConditionTypeEnum.PRICE.getType().equals(rewardActivity.getConditionType()) - && price >= rule.getLimit()) { - return rule; - } - if (PromotionConditionTypeEnum.COUNT.getType().equals(rewardActivity.getConditionType()) - && count >= rule.getLimit()) { - return rule; - } - } - return null; - } - - /** - * 获得满减送活动部匹配时的提示 - * - * @param rewardActivity 满减送活动 - * @return 提示 - */ - private String getRewardActivityNotMeetTip(RewardActivityDO rewardActivity) { - return "TODO"; // TODO 芋艿:后面再想想 - } - - // ========== 计算优惠劵级别的价格 ========== - - private void calculatePriceForCouponLevel(Long userId, Long couponId, PriceCalculateRespDTO priceCalculate) { - // 校验优惠劵 - if (couponId == null) { - return; - } - CouponDO coupon = couponService.validCoupon(couponId, userId); - - // 获得匹配的商品 SKU 数组 - List orderItems = getMatchCouponOrderItems(priceCalculate, coupon); - if (CollUtil.isEmpty(orderItems)) { - throw exception(COUPON_NO_MATCH_SPU); - } - - // 计算是否满足优惠劵的使用金额 - Integer originPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum); - assert originPrice != null; - if (originPrice < coupon.getUsePrice()) { - throw exception(COUPON_NO_MATCH_MIN_PRICE); - } - - // 计算可以优惠的金额 - priceCalculate.getOrder().setCouponId(couponId); - Integer couponPrice = getCouponPrice(coupon, originPrice); - // 分摊金额 - List couponPartPrices = dividePrice(orderItems, couponPrice); - // 记录优惠明细 - addPromotion(priceCalculate, orderItems, coupon.getId(), coupon.getName(), - PromotionTypeEnum.COUPON.getType(), PromotionLevelEnum.COUPON.getLevel(), couponPartPrices, - true, StrUtil.format("优惠劵:省 {} 元", formatPrice(couponPrice))); - // 修改 SKU 的分摊 - for (int i = 0; i < orderItems.size(); i++) { - modifyOrderItemOrderPartPriceFromCouponPrice(orderItems.get(i), couponPartPrices.get(i), priceCalculate); - } - } - - private List getMatchCouponOrderItems(PriceCalculateRespDTO priceCalculate, - CouponDO coupon) { - if (PromotionProductScopeEnum.ALL.getScope().equals(coupon.getProductScope())) { - return priceCalculate.getOrder().getItems(); - } - return CollectionUtils.filterList(priceCalculate.getOrder().getItems(), - orderItem -> coupon.getProductSpuIds().contains(orderItem.getSpuId())); - } - - private Integer getCouponPrice(CouponDO coupon, Integer originPrice) { - if (PromotionDiscountTypeEnum.PRICE.getType().equals(coupon.getDiscountType())) { // 减价 - return coupon.getDiscountPrice(); - } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(coupon.getDiscountType())) { // 打折 - int couponPrice = originPrice * coupon.getDiscountPercent() / 100; - return coupon.getDiscountLimitPrice() == null ? couponPrice - : Math.min(couponPrice, coupon.getDiscountLimitPrice()); // 优惠上限 - } - throw new IllegalArgumentException(String.format("优惠劵(%s) 的优惠类型不正确", coupon)); - } - - // ========== 其它相对通用的方法 ========== - - /** - * 添加单个 OrderItem 的营销明细 - * - * @param priceCalculate 价格计算结果 - * @param orderItem 单个订单商品 SKU - * @param id 营销编号 - * @param name 营销名字 - * @param type 营销类型 - * @param level 营销级别 - * @param newPayPrice 新的单实付金额(总) - * @param meet 是否满足优惠条件 - * @param meetTip 满足条件的提示 - */ - private void addPromotion(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem, - Long id, String name, Integer type, Integer level, - Integer newPayPrice, Boolean meet, String meetTip) { - // 创建营销明细 Item - // TODO 芋艿:orderItem.getPayPrice() 要不要改成 orderDividePrice;同时,newPayPrice 要不要改成直接传递 discountPrice - PriceCalculateRespDTO.PromotionItem promotionItem = new PriceCalculateRespDTO.PromotionItem().setSkuId(orderItem.getSkuId()) - .setOriginalPrice(orderItem.getPayPrice()).setDiscountPrice(orderItem.getPayPrice() - newPayPrice); - // 创建营销明细 - PriceCalculateRespDTO.Promotion promotion = new PriceCalculateRespDTO.Promotion() - .setId(id).setName(name).setType(type).setLevel(level) - .setTotalPrice(promotionItem.getOriginalPrice()).setDiscountPrice(promotionItem.getDiscountPrice()) - .setItems(singletonList(promotionItem)).setMeet(meet).setMeetTip(meetTip); - priceCalculate.getPromotions().add(promotion); - } - - /** - * 添加多个 OrderItem 的营销明细 - * - * @param priceCalculate 价格计算结果 - * @param orderItems 多个订单商品 SKU - * @param id 营销编号 - * @param name 营销名字 - * @param type 营销类型 - * @param level 营销级别 - * @param discountPrices 多个订单商品 SKU 的优惠价格(总),和 orderItems 一一对应 - * @param meet 是否满足优惠条件 - * @param meetTip 满足条件的提示 - */ - private void addPromotion(PriceCalculateRespDTO priceCalculate, List orderItems, - Long id, String name, Integer type, Integer level, - List discountPrices, Boolean meet, String meetTip) { - // 创建营销明细 Item - List promotionItems = new ArrayList<>(discountPrices.size()); - for (int i = 0; i < orderItems.size(); i++) { - PriceCalculateRespDTO.OrderItem orderItem = orderItems.get(i); - promotionItems.add(new PriceCalculateRespDTO.PromotionItem().setSkuId(orderItem.getSkuId()) - .setOriginalPrice(orderItem.getPayPrice()).setDiscountPrice(discountPrices.get(i))); - } - // 创建营销明细 - PriceCalculateRespDTO.Promotion promotion = new PriceCalculateRespDTO.Promotion() - .setId(id).setName(name).setType(type).setLevel(level) - .setTotalPrice(getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum)) - .setDiscountPrice(getSumValue(discountPrices, value -> value, Integer::sum)) - .setItems(promotionItems).setMeet(meet).setMeetTip(meetTip); - priceCalculate.getPromotions().add(promotion); - } - - private void addNotMeetPromotion(PriceCalculateRespDTO priceCalculate, List orderItems, - Long id, String name, Integer type, Integer level, String meetTip) { - // 创建营销明细 Item - List promotionItems = CollectionUtils.convertList(orderItems, - orderItem -> new PriceCalculateRespDTO.PromotionItem().setSkuId(orderItem.getSkuId()) - .setOriginalPrice(orderItem.getOrderDividePrice()).setDiscountPrice(0)); - // 创建营销明细 - Integer originalPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum); - PriceCalculateRespDTO.Promotion promotion = new PriceCalculateRespDTO.Promotion() - .setId(id).setName(name).setType(type).setLevel(level) - .setTotalPrice(originalPrice).setDiscountPrice(0) - .setItems(promotionItems).setMeet(false).setMeetTip(meetTip); - priceCalculate.getPromotions().add(promotion); - } - - /** - * 修改 OrderItem 的 payPrice 价格,同时会修改 Order 的 payPrice 价格 - * - * @param orderItem 订单商品 SKU - * @param newPayPrice 新的 payPrice 价格 - * @param priceCalculate 价格计算结果 - */ - private void modifyOrderItemPayPrice(PriceCalculateRespDTO.OrderItem orderItem, Integer newPayPrice, - PriceCalculateRespDTO priceCalculate) { - // diffPayPrice 等于额外增加的商品级的优惠 - int diffPayPrice = orderItem.getPayPrice() - newPayPrice; - // 设置 OrderItem 价格相关字段 - orderItem.setDiscountPrice(orderItem.getDiscountPrice() + diffPayPrice); - orderItem.setPayPrice(newPayPrice); - orderItem.setOrderDividePrice(orderItem.getPayPrice() - orderItem.getOrderPartPrice()); - // 设置 Order 相关相关字段 - PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); - order.setPayPrice(order.getPayPrice() - diffPayPrice); - } - - /** - * 修改 OrderItem 的 orderPartPrice 价格,同时会修改 Order 的 discountPrice 价格 - * - * 本质:分摊 Order 的 discountPrice 价格,到对应的 OrderItem 的 orderPartPrice 价格中 - * - * @param orderItem 订单商品 SKU - * @param addOrderPartPrice 新增的 discountPrice 价格 - * @param priceCalculate 价格计算结果 - */ - private void modifyOrderItemOrderPartPriceFromDiscountPrice(PriceCalculateRespDTO.OrderItem orderItem, Integer addOrderPartPrice, - PriceCalculateRespDTO priceCalculate) { - // 设置 OrderItem 价格相关字段 - orderItem.setOrderPartPrice(orderItem.getOrderPartPrice() + addOrderPartPrice); - orderItem.setOrderDividePrice(orderItem.getPayPrice() - orderItem.getOrderPartPrice()); - // 设置 Order 相关相关字段 - PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); - order.setDiscountPrice(order.getDiscountPrice() + addOrderPartPrice); - order.setPayPrice(order.getPayPrice() - addOrderPartPrice); - } - - /** - * 修改 OrderItem 的 orderPartPrice 价格,同时会修改 Order 的 couponPrice 价格 - * - * 本质:分摊 Order 的 couponPrice 价格,到对应的 OrderItem 的 orderPartPrice 价格中 - * - * @param orderItem 订单商品 SKU - * @param addOrderPartPrice 新增的 couponPrice 价格 - * @param priceCalculate 价格计算结果 - */ - private void modifyOrderItemOrderPartPriceFromCouponPrice(PriceCalculateRespDTO.OrderItem orderItem, Integer addOrderPartPrice, - PriceCalculateRespDTO priceCalculate) { - // 设置 OrderItem 价格相关字段 - orderItem.setOrderPartPrice(orderItem.getOrderPartPrice() + addOrderPartPrice); - orderItem.setOrderDividePrice(orderItem.getPayPrice() - orderItem.getOrderPartPrice()); - // 设置 Order 相关相关字段 - PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); - order.setCouponPrice(order.getCouponPrice() + addOrderPartPrice); - order.setPayPrice(order.getPayPrice() - addOrderPartPrice); - } - - private List dividePrice(List orderItems, Integer price) { - List prices = new ArrayList<>(orderItems.size()); - Integer total = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum); - assert total != null; - int remainPrice = price; - // 遍历每一个,进行分摊 - for (int i = 0; i < orderItems.size(); i++) { - PriceCalculateRespDTO.OrderItem orderItem = orderItems.get(i); - int partPrice; - if (i < orderItems.size() - 1) { // 减一的原因,是因为拆分时,如果按照比例,可能会出现.所以最后一个,使用反减 - partPrice = (int) (price * (1.0D * orderItem.getOrderDividePrice() / total)); - remainPrice -= partPrice; - } else { - partPrice = remainPrice; - } - Assert.isTrue(partPrice > 0, "分摊金额必须大于 0"); - prices.add(partPrice); - } - return prices; - } - - private String formatPrice(Integer price) { - return String.format("%.2f", price / 100d); - } - } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java index 40bcc2836..4dcdb0738 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java @@ -1,14 +1,15 @@ package cn.iocoder.yudao.module.promotion.service.reward; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; import javax.validation.Valid; -import java.util.Map; -import java.util.Set; +import java.util.Collection; +import java.util.List; /** * 满减送活动 Service 接口 @@ -66,8 +67,8 @@ public interface RewardActivityService { * 基于指定的 SPU 编号数组,获得它们匹配的满减送活动 * * @param spuIds SPU 编号数组 - * @return 满减送活动,与对应的 SPU 编号的映射。即,value 就是 SPU 编号的集合 + * @return 满减送活动列表 */ - Map> getMatchRewardActivities(Set spuIds); + List getMatchRewardActivityList(Collection spuIds); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java index 51d0ce626..cdb73853c 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.promotion.service.reward; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.map.MapUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO; @@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.promotion.convert.reward.RewardActivityConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; import cn.iocoder.yudao.module.promotion.dal.mysql.reward.RewardActivityMapper; import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; -import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; import cn.iocoder.yudao.module.promotion.util.PromotionUtils; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -18,15 +17,10 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.Collection; import java.util.List; -import java.util.Map; -import java.util.Set; -import static cn.hutool.core.collection.CollUtil.intersectionDistinct; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; import static java.util.Arrays.asList; -import static java.util.Collections.singleton; /** * 满减送活动 Service 实现类 @@ -105,6 +99,7 @@ public class RewardActivityServiceImpl implements RewardActivityService { return activity; } + // TODO @芋艿:逻辑有问题,需要优化;要分成全场、和指定来校验; /** * 校验商品参加的活动是否冲突 * @@ -151,19 +146,21 @@ public class RewardActivityServiceImpl implements RewardActivityService { } @Override - public Map> getMatchRewardActivities(Set spuIds) { - // 如果有全局活动,则直接选择它 - List allActivities = rewardActivityMapper.selectListByProductScopeAndStatus( - PromotionProductScopeEnum.ALL.getScope(), PromotionActivityStatusEnum.RUN.getStatus()); - if (CollUtil.isNotEmpty(allActivities)) { - return MapUtil.builder(allActivities.get(0), spuIds).build(); - } - - // 查询某个活动参加的活动 - List productActivityList = getRewardActivityListBySpuIds(spuIds, - singleton(PromotionActivityStatusEnum.RUN.getStatus())); - return convertMap(productActivityList, activity -> activity, - rewardActivityDO -> intersectionDistinct(rewardActivityDO.getProductSpuIds(), spuIds)); // 求交集返回 + public List getMatchRewardActivityList(Collection spuIds) { + // TODO 芋艿:待实现;先指定,然后再全局的; +// // 如果有全局活动,则直接选择它 +// List allActivities = rewardActivityMapper.selectListByProductScopeAndStatus( +// PromotionProductScopeEnum.ALL.getScope(), PromotionActivityStatusEnum.RUN.getStatus()); +// if (CollUtil.isNotEmpty(allActivities)) { +// return MapUtil.builder(allActivities.get(0), spuIds).build(); +// } +// +// // 查询某个活动参加的活动 +// List productActivityList = getRewardActivityListBySpuIds(spuIds, +// singleton(PromotionActivityStatusEnum.RUN.getStatus())); +// return convertMap(productActivityList, activity -> activity, +// rewardActivityDO -> intersectionDistinct(rewardActivityDO.getProductSpuIds(), spuIds)); // 求交集返回 + return null; } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java index 9e40ff67b..929727077 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceTest.java @@ -96,8 +96,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion.getLevel(), PromotionLevelEnum.SKU.getLevel()); assertEquals(promotion.getTotalPrice(), 200); assertEquals(promotion.getDiscountPrice(), 20); - assertTrue(promotion.getMeet()); - assertEquals(promotion.getMeetTip(), "会员折扣:省 0.20 元"); + assertTrue(promotion.getMatch()); + assertEquals(promotion.getDescription(), "会员折扣:省 0.20 元"); PriceCalculateRespDTO.PromotionItem promotionItem = promotion.getItems().get(0); assertEquals(promotion.getItems().size(), 1); assertEquals(promotionItem.getSkuId(), 10L); @@ -122,7 +122,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { DiscountProductDetailBO discountProduct02 = randomPojo(DiscountProductDetailBO.class, o -> o.setActivityId(2000L) .setActivityName("活动 2000 号").setSkuId(20L) .setDiscountType(PromotionDiscountTypeEnum.PERCENT.getType()).setDiscountPercent(60)); - when(discountService.getMatchDiscountProducts(eq(asSet(10L, 20L)))).thenReturn( + when(discountService.getMatchDiscountProductList(eq(asSet(10L, 20L)))).thenReturn( MapUtil.builder(10L, discountProduct01).put(20L, discountProduct02).map()); // 10L: 100 * 2 - 40 * 2 = 120 @@ -167,8 +167,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion01.getLevel(), PromotionLevelEnum.SKU.getLevel()); assertEquals(promotion01.getTotalPrice(), 200); assertEquals(promotion01.getDiscountPrice(), 80); - assertTrue(promotion01.getMeet()); - assertEquals(promotion01.getMeetTip(), "限时折扣:省 0.80 元"); + assertTrue(promotion01.getMatch()); + assertEquals(promotion01.getDescription(), "限时折扣:省 0.80 元"); PriceCalculateRespDTO.PromotionItem promotionItem01 = promotion01.getItems().get(0); assertEquals(promotion01.getItems().size(), 1); assertEquals(promotionItem01.getSkuId(), 10L); @@ -181,8 +181,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion02.getLevel(), PromotionLevelEnum.SKU.getLevel()); assertEquals(promotion02.getTotalPrice(), 150); assertEquals(promotion02.getDiscountPrice(), 60); - assertTrue(promotion02.getMeet()); - assertEquals(promotion02.getMeetTip(), "限时折扣:省 0.60 元"); + assertTrue(promotion02.getMatch()); + assertEquals(promotion02.getDescription(), "限时折扣:省 0.60 元"); PriceCalculateRespDTO.PromotionItem promotionItem02 = promotion02.getItems().get(0); assertEquals(promotion02.getItems().size(), 1); assertEquals(promotionItem02.getSkuId(), 20L); @@ -267,8 +267,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion01.getLevel(), PromotionLevelEnum.ORDER.getLevel()); assertEquals(promotion01.getTotalPrice(), 350); assertEquals(promotion01.getDiscountPrice(), 70); - assertTrue(promotion01.getMeet()); - assertEquals(promotion01.getMeetTip(), "满减送:省 0.70 元"); + assertTrue(promotion01.getMatch()); + assertEquals(promotion01.getDescription(), "满减送:省 0.70 元"); assertEquals(promotion01.getItems().size(), 2); PriceCalculateRespDTO.PromotionItem promotionItem011 = promotion01.getItems().get(0); assertEquals(promotionItem011.getSkuId(), 10L); @@ -286,8 +286,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion02.getLevel(), PromotionLevelEnum.ORDER.getLevel()); assertEquals(promotion02.getTotalPrice(), 120); assertEquals(promotion02.getDiscountPrice(), 60); - assertTrue(promotion02.getMeet()); - assertEquals(promotion02.getMeetTip(), "满减送:省 0.60 元"); + assertTrue(promotion02.getMatch()); + assertEquals(promotion02.getDescription(), "满减送:省 0.60 元"); PriceCalculateRespDTO.PromotionItem promotionItem02 = promotion02.getItems().get(0); assertEquals(promotion02.getItems().size(), 1); assertEquals(promotionItem02.getSkuId(), 30L); @@ -355,8 +355,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion01.getLevel(), PromotionLevelEnum.ORDER.getLevel()); assertEquals(promotion01.getTotalPrice(), 350); assertEquals(promotion01.getDiscountPrice(), 0); - assertFalse(promotion01.getMeet()); - assertEquals(promotion01.getMeetTip(), "TODO"); // TODO 芋艿:后面再想想 + assertFalse(promotion01.getMatch()); + assertEquals(promotion01.getDescription(), "TODO"); // TODO 芋艿:后面再想想 assertEquals(promotion01.getItems().size(), 2); PriceCalculateRespDTO.PromotionItem promotionItem011 = promotion01.getItems().get(0); assertEquals(promotionItem011.getSkuId(), 10L); @@ -437,8 +437,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest { assertEquals(promotion01.getLevel(), PromotionLevelEnum.COUPON.getLevel()); assertEquals(promotion01.getTotalPrice(), 350); assertEquals(promotion01.getDiscountPrice(), 70); - assertTrue(promotion01.getMeet()); - assertEquals(promotion01.getMeetTip(), "优惠劵:省 0.70 元"); + assertTrue(promotion01.getMatch()); + assertEquals(promotion01.getDescription(), "优惠劵:省 0.70 元"); assertEquals(promotion01.getItems().size(), 2); PriceCalculateRespDTO.PromotionItem promotionItem011 = promotion01.getItems().get(0); assertEquals(promotionItem011.getSkuId(), 10L); diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java index cb0ac8474..b887ae8c8 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java @@ -50,4 +50,8 @@ public interface ErrorCodeConstants { ErrorCode EXPRESS_CODE_DUPLICATE = new ErrorCode(1011003001, "已经存在该编码的快递公司"); ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1011003002, "运费模板不存在"); ErrorCode EXPRESS_TEMPLATE_NAME_DUPLICATE = new ErrorCode(1011003002, "已经存在该运费模板名"); + + // ========== Price 相关 1011004000 ============ + ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011004000, "支付价格计算异常,原因:价格小于等于 0"); + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java index 5b3a84284..72b9e08d0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java @@ -4,7 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.*; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.*; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressUpdateReqVO; import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryExpressConvert; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressTemplateController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressTemplateController.java index 3471b2233..fed5ee13c 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressTemplateController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressTemplateController.java @@ -1,31 +1,25 @@ package cn.iocoder.yudao.module.trade.controller.admin.delivery; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.*; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.*; import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryExpressTemplateConvert; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService; -import org.springframework.web.bind.annotation.*; -import javax.annotation.Resource; -import org.springframework.validation.annotation.Validated; -import org.springframework.security.access.prepost.PreAuthorize; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; -import javax.validation.*; -import javax.servlet.http.*; -import java.util.*; -import java.io.IOException; +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; - -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*; - @Tag(name = "管理后台 - 快递运费模板") @RestController @@ -84,4 +78,5 @@ public class DeliveryExpressTemplateController { PageResult pageResult = deliveryExpressTemplateService.getDeliveryExpressTemplatePage(pageVO); return success(DeliveryExpressTemplateConvert.INSTANCE.convertPage(pageResult)); } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressBaseVO.java similarity index 98% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressBaseVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressBaseVO.java index 538027c81..c4f629cf6 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressCreateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressCreateReqVO.java similarity index 84% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressCreateReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressCreateReqVO.java index 2ef4e8070..a9ba8a7cb 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressCreateReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressCreateReqVO.java @@ -1,9 +1,7 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express; import lombok.*; -import java.util.*; import io.swagger.v3.oas.annotations.media.Schema; -import javax.validation.constraints.*; @Schema(description = "管理后台 - 快递公司创建 Request VO") @Data diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExcelVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressExcelVO.java similarity index 98% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExcelVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressExcelVO.java index 4df6c0d7d..c84a3a189 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExcelVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressExcelVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExportReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressExportReqVO.java similarity index 98% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExportReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressExportReqVO.java index 6e44cc45f..c601721e8 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExportReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressExportReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressPageReqVO.java similarity index 98% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressPageReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressPageReqVO.java index 50826ea36..4a000f319 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressPageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express; import lombok.*; import java.util.*; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressRespVO.java similarity index 97% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressRespVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressRespVO.java index 55d5578ad..34fd06a53 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressUpdateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressUpdateReqVO.java similarity index 77% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressUpdateReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressUpdateReqVO.java index 633736e34..f8bf33f5c 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressUpdateReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressUpdateReqVO.java @@ -1,9 +1,11 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import java.util.*; -import javax.validation.constraints.*; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; @Schema(description = "管理后台 - 快递公司更新 Request VO") @Data diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateBaseVO.java similarity index 97% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateBaseVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateBaseVO.java index cedb70888..7e84f962e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateCreateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateCreateReqVO.java similarity index 77% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateCreateReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateCreateReqVO.java index e575f1a91..ee51c5659 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateCreateReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateCreateReqVO.java @@ -1,10 +1,13 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; -import lombok.*; -import java.util.*; import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; import javax.validation.Valid; +import java.util.Collections; +import java.util.List; @Schema(description = "管理后台 - 快递运费模板创建 Request VO") @Data @@ -12,6 +15,8 @@ import javax.validation.Valid; @ToString(callSuper = true) public class DeliveryExpressTemplateCreateReqVO extends DeliveryExpressTemplateBaseVO { + // TODO @jason:不用给默认值哈 + @Schema(description = "区域运费列表") @Valid private List templateCharge = Collections.emptyList(); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplatePageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplatePageReqVO.java similarity index 90% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplatePageReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplatePageReqVO.java index c5fa5a6ca..ea1e4ab3e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplatePageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplatePageReqVO.java @@ -1,10 +1,12 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; -import lombok.*; -import java.util.*; -import io.swagger.v3.oas.annotations.media.Schema; import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; + import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateRespVO.java similarity index 97% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateRespVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateRespVO.java index 5e968f629..a03a8e61b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateSimpleRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateSimpleRespVO.java similarity index 82% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateSimpleRespVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateSimpleRespVO.java index 4cfc530ab..2f2c8280d 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateSimpleRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateSimpleRespVO.java @@ -1,9 +1,10 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.time.LocalDateTime; +// TODO @jason:simplae 是不是不用继承 DeliveryExpressTemplateBaseVO,直接 id name 属性就够了。 @Schema(description = "管理后台 - 快递运费模板 精简 Response VO") @Data @EqualsAndHashCode(callSuper = true) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateUpdateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateUpdateReqVO.java similarity index 77% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateUpdateReqVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateUpdateReqVO.java index 80ebee8b6..0f5c65221 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateUpdateReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateUpdateReqVO.java @@ -1,10 +1,14 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import java.util.*; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + import javax.validation.Valid; -import javax.validation.constraints.*; +import javax.validation.constraints.NotNull; +import java.util.Collections; +import java.util.List; @Schema(description = "管理后台 - 快递运费模板更新 Request VO") @Data @@ -16,6 +20,8 @@ public class DeliveryExpressTemplateUpdateReqVO extends DeliveryExpressTemplateB @NotNull(message = "编号不能为空") private Long id; + // TODO @jason:pojo 不给默认值哈 + @Schema(description = "区域运费列表") @Valid private List templateCharge = Collections.emptyList(); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateChargeBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/ExpressTemplateChargeBaseVO.java similarity index 98% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateChargeBaseVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/ExpressTemplateChargeBaseVO.java index 8bd2617b7..7fb1111d5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateChargeBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/ExpressTemplateChargeBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateChargeUpdateVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/ExpressTemplateChargeUpdateVO.java similarity index 61% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateChargeUpdateVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/ExpressTemplateChargeUpdateVO.java index 995ea4a18..e9fcb08f9 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateChargeUpdateVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/ExpressTemplateChargeUpdateVO.java @@ -1,18 +1,22 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; - +// TODO @jason:这个 vo 可以内嵌到 DeliveryExpressTemplateUpdateReqVO,避免 vo 过多,不好分辨 +@Schema(description = "管理后台 - 快递公司创建 Request VO") @Data public class ExpressTemplateChargeUpdateVO extends ExpressTemplateChargeBaseVO { @Schema(description = "编号", example = "6592") private Long id; + // TODO @jason:这几个字段,应该不通过前端传递,而是后端查询后去赋值的 + @Schema(description = "配送模板编号", example = "1") private Long templateId; @Schema(description = "配送计费方式", example = "1") private Integer chargeMode; + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateFreeBaseVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/ExpressTemplateFreeBaseVO.java similarity index 97% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateFreeBaseVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/ExpressTemplateFreeBaseVO.java index 7523b0f53..9334abf07 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateFreeBaseVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/ExpressTemplateFreeBaseVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -24,4 +24,5 @@ public class ExpressTemplateFreeBaseVO { @Schema(description = "包邮件数", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") @NotNull(message = "包邮件数不能为空") private Integer freeCount; + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateFreeUpdateVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/ExpressTemplateFreeUpdateVO.java similarity index 72% rename from yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateFreeUpdateVO.java rename to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/ExpressTemplateFreeUpdateVO.java index e0c7e47b0..e2c894456 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateFreeUpdateVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/ExpressTemplateFreeUpdateVO.java @@ -1,8 +1,10 @@ -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +// TODO @jason:这个 vo 可以内嵌到 DeliveryExpressTemplateUpdateReqVO,避免 vo 过多,不好分辨 +// TODO @jason:swagger 缺失 /** * 快递运费模板包邮 更新 VO */ diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressConvert.java index e896962a2..474881790 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressConvert.java @@ -4,10 +4,10 @@ import java.util.*; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressCreateReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressExcelVO; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressRespVO; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressUpdateReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressExcelVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressUpdateReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java index 7e2a51cc1..20e94cb25 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java @@ -1,17 +1,14 @@ package cn.iocoder.yudao.module.trade.convert.delivery; -import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.*; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.*; 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 org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; /** diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressMapper.java index 24b0b50e6..f74318e56 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressMapper.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.trade.dal.mysql.delivery; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressExportReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressPageReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressExportReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressPageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateMapper.java index 734298042..c93346894 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateMapper.java @@ -4,7 +4,7 @@ package cn.iocoder.yudao.module.trade.dal.mysql.delivery; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressTemplatePageReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplatePageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressService.java index ce4814dbd..b6fffa87a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressService.java @@ -4,10 +4,10 @@ import java.util.*; import javax.validation.*; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressCreateReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressExportReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressPageReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressUpdateReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressExportReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressPageReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressUpdateReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; /** diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressServiceImpl.java index dcbf08969..a396a389a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressServiceImpl.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.trade.service.delivery; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressCreateReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressExportReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressPageReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressUpdateReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressExportReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressPageReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressUpdateReqVO; import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryExpressConvert; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressMapper; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateService.java index 71721fec2..20a0a1b62 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateService.java @@ -1,11 +1,16 @@ package cn.iocoder.yudao.module.trade.service.delivery; -import java.util.*; -import javax.validation.*; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.*; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplatePageReqVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateRespVO; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateUpdateReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + /** * 快递运费模板 Service 接口 * diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateServiceImpl.java index 2bda89a91..d7bf96978 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateServiceImpl.java @@ -2,8 +2,7 @@ package cn.iocoder.yudao.module.trade.service.delivery; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.*; +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.*; 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; @@ -18,8 +17,10 @@ import javax.annotation.Resource; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.trade.convert.delivery.DeliveryExpressTemplateConvert.INSTANCE; -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_TEMPLATE_NAME_DUPLICATE; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_TEMPLATE_NOT_EXISTS; /** * 快递运费模板 Service 实现类 @@ -42,6 +43,7 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla public Long createDeliveryExpressTemplate(DeliveryExpressTemplateCreateReqVO createReqVO) { // 校验模板名是否唯一 validateTemplateNameUnique(createReqVO.getName(), null); + // 插入 DeliveryExpressTemplateDO deliveryExpressTemplate = INSTANCE.convert(createReqVO); expressTemplateMapper.insert(deliveryExpressTemplate); @@ -67,6 +69,7 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla validateDeliveryExpressTemplateExists(updateReqVO.getId()); // 校验模板名是否唯一 validateTemplateNameUnique(updateReqVO.getName(), updateReqVO.getId()); + // 更新运费从表 updateExpressTemplateCharge(updateReqVO); // 更新包邮从表 @@ -77,12 +80,11 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla } private void updateExpressTemplateFree(DeliveryExpressTemplateUpdateReqVO updateReqVO) { + // 1.1 获得新增/修改的区域列表 List oldFreeList = expressTemplateFreeMapper.selectListByTemplateId(updateReqVO.getId()); List newFreeList = updateReqVO.getTemplateFree(); - // 新增包邮区域列表 - List addFreeList = new ArrayList<>(newFreeList.size()); - // 更新包邮区域列表 - List updateFreeList = new ArrayList<>(newFreeList.size()); + List addFreeList = new ArrayList<>(newFreeList.size()); // 新增包邮区域列表 + List updateFreeList = new ArrayList<>(newFreeList.size()); // 更新包邮区域列表 for (ExpressTemplateFreeUpdateVO item : newFreeList) { if (Objects.nonNull(item.getId())) { updateFreeList.add(INSTANCE.convertTemplateFree(item)); @@ -91,30 +93,29 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla addFreeList.add(INSTANCE.convertTemplateFree(item)); } } - // 新增 + // 1.2 新增 if (CollUtil.isNotEmpty(addFreeList)) { expressTemplateFreeMapper.insertBatch(addFreeList); } - // 修改 + // 1.3 修改 if (CollUtil.isNotEmpty(updateFreeList)) { expressTemplateFreeMapper.updateBatch(updateFreeList); } - // 得到删除ids - Set deleteFreeIds = CollectionUtils.convertSet(oldFreeList, DeliveryExpressTemplateFreeDO::getId); - deleteFreeIds.removeAll(CollectionUtils.convertSet(updateFreeList, DeliveryExpressTemplateFreeDO::getId)); - //删除 + + // 2. 删除 + Set deleteFreeIds = convertSet(oldFreeList, DeliveryExpressTemplateFreeDO::getId); + deleteFreeIds.removeAll(convertSet(updateFreeList, DeliveryExpressTemplateFreeDO::getId)); if (CollUtil.isNotEmpty(deleteFreeIds)) { expressTemplateFreeMapper.deleteBatchIds(deleteFreeIds); } } private void updateExpressTemplateCharge(DeliveryExpressTemplateUpdateReqVO updateReqVO) { + // 1.1 获得新增/修改的区域列表 List oldChargeList = expressTemplateChargeMapper.selectListByTemplateId(updateReqVO.getId()); List newChargeList = updateReqVO.getTemplateCharge(); - // 新增运费区域列表 - List addList = new ArrayList<>(newChargeList.size()); - // 更新运费区域列表 - List updateList = new ArrayList<>(newChargeList.size()); + List addList = new ArrayList<>(newChargeList.size()); // 新增运费区域列表 + List updateList = new ArrayList<>(newChargeList.size()); // 更新运费区域列表 for (ExpressTemplateChargeUpdateVO item : newChargeList) { if (item.getId() != null) { // 计费模式以主表为准 @@ -126,18 +127,18 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla addList.add(INSTANCE.convertTemplateCharge(item)); } } - // 新增 + // 1.2 新增 if (CollUtil.isNotEmpty(addList)) { expressTemplateChargeMapper.insertBatch(addList); } - // 修改 + // 1.3 修改 if (CollUtil.isNotEmpty(updateList)) { expressTemplateChargeMapper.updateBatch(updateList); } - // 得到删除的ids - Set deleteChargeIds = CollectionUtils.convertSet(oldChargeList, DeliveryExpressTemplateChargeDO::getId); - deleteChargeIds.removeAll(CollectionUtils.convertSet(updateList, DeliveryExpressTemplateChargeDO::getId)); - // 删除 + + // 2. 删除 + Set deleteChargeIds = convertSet(oldChargeList, DeliveryExpressTemplateChargeDO::getId); + deleteChargeIds.removeAll(convertSet(updateList, DeliveryExpressTemplateChargeDO::getId)); if (CollUtil.isNotEmpty(deleteChargeIds)) { expressTemplateChargeMapper.deleteBatchIds(deleteChargeIds); } @@ -148,6 +149,7 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla public void deleteDeliveryExpressTemplate(Long id) { // 校验存在 validateDeliveryExpressTemplateExists(id); + // 删除主表 expressTemplateMapper.deleteById(id); // 删除运费从表 @@ -199,4 +201,5 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla public PageResult getDeliveryExpressTemplatePage(DeliveryExpressTemplatePageReqVO pageReqVO) { return expressTemplateMapper.selectPage(pageReqVO); } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceService.java new file mode 100644 index 000000000..2dd0c41ca --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceService.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.trade.service.price; + +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; + +/** + * 价格计算 Service 接口 + * + * @author 芋道源码 + */ +public interface TradePriceService { + + /** + * 价格计算 + * + * @param calculateReqDTO 计算信息 + * @return 计算结果 + */ + TradePriceCalculateRespBO calculatePrice(TradePriceCalculateReqBO calculateReqDTO); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java new file mode 100644 index 000000000..f0ebce5ba --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.trade.service.price; + +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.service.price.bo.TradePriceCalculateReqBO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; +import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculator; +import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_STOCK_NOT_ENOUGH; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.PRICE_CALCULATE_PAY_PRICE_ILLEGAL; + +/** + * 价格计算 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Slf4j +public class TradePriceServiceImpl implements TradePriceService { + + @Resource + private ProductSkuApi productSkuApi; + @Resource + private List priceCalculators; + + @Override + public TradePriceCalculateRespBO calculatePrice(TradePriceCalculateReqBO calculateReqBO) { + // 1. 获得商品 SKU 数组 + List skuList = checkSkus(calculateReqBO); + + // 2.1 计算价格 + TradePriceCalculateRespBO calculateRespBO = TradePriceCalculatorHelper + .buildCalculateResp(calculateReqBO, skuList); + priceCalculators.forEach(calculator -> calculator.calculate(calculateReqBO, calculateRespBO)); + // 2.2 如果最终支付金额小于等于 0,则抛出业务异常 + if (calculateRespBO.getPrice().getPayPrice() <= 0) { + log.error("[calculatePrice][价格计算不正确,请求 calculateReqDTO({}),结果 priceCalculate({})]", + calculateReqBO, calculateRespBO); + throw exception(PRICE_CALCULATE_PAY_PRICE_ILLEGAL); + } + return calculateRespBO; + } + + private List checkSkus(TradePriceCalculateReqBO reqBO) { + // 获得商品 SKU 数组 + Map skuIdCountMap = convertMap(reqBO.getItems(), + TradePriceCalculateReqBO.Item::getSkuId, TradePriceCalculateReqBO.Item::getCount); + List skus = productSkuApi.getSkuList(skuIdCountMap.keySet()); + + // 校验商品 SKU + skus.forEach(sku -> { + Integer count = skuIdCountMap.get(sku.getId()); + if (count == null) { + throw exception(SKU_NOT_EXISTS); + } + if (count > sku.getStock()) { + throw exception(SKU_STOCK_NOT_ENOUGH); + } + }); + return skus; + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java new file mode 100644 index 000000000..2a014c0e0 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.trade.service.price.bo; + +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; +import lombok.Data; + +import javax.validation.Valid; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * 价格计算 Request BO + * + * @author yudao源码 + */ +@Data +public class TradePriceCalculateReqBO { + + /** + * 订单类型 + * + * 枚举 {@link TradeOrderTypeEnum} + */ + private Integer orderType; + + /** + * 用户编号 + * + * 对应 MemberUserDO 的 id 编号 + */ + private Long userId; + + /** + * 优惠劵编号 + * + * 对应 CouponDO 的 id 编号 + */ + private Long couponId; + + /** + * 收货地址编号 + * + * 对应 MemberAddressDO 的 id 编号 + */ + private Long addressId; + + /** + * 商品 SKU 数组 + */ + @NotNull(message = "商品数组不能为空") + private List items; + + /** + * 商品 SKU + */ + @Data + @Valid + public static class Item { + + /** + * SKU 编号 + */ + @NotNull(message = "商品 SKU 编号不能为空") + private Long skuId; + + /** + * SKU 数量 + */ + @NotNull(message = "商品 SKU 数量不能为空") + @Min(value = 0L, message = "商品 SKU 数量必须大于等于 0") + private Integer count; + + /** + * 购物车项的编号 + */ + private Long cartId; + + /** + * 是否选中 + */ + @NotNull(message = "是否选中不能为空") + private Boolean selected; + + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java new file mode 100644 index 000000000..b30ba8855 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java @@ -0,0 +1,249 @@ +package cn.iocoder.yudao.module.trade.service.price.bo; + +import cn.iocoder.yudao.module.promotion.enums.common.PromotionLevelEnum; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; +import lombok.Data; + +import java.util.List; + +/** + * 价格计算 Response BO + * + * 整体设计,参考 taobao 的技术文档: + * 1. 订单管理 + * 2. 常用订单金额说明 + * + * @author 芋道源码 + */ +@Data +public class TradePriceCalculateRespBO { + + /** + * 订单类型 + * + * 枚举 {@link TradeOrderTypeEnum} + */ + private Integer orderType; + + /** + * 订单价格 + */ + private Price price; + + /** + * 订单项数组 + */ + private List items; + + /** + * 营销活动数组 + * + * 只对应 {@link Price#items} 商品匹配的活动 + */ + private List promotions; + + /** + * 优惠劵编号 + */ + private Long couponId; + + /** + * 订单价格 + */ + @Data + public static class Price { + + /** + * 商品原价(总),单位:分 + * + * 基于 {@link OrderItem#getPrice()} * {@link OrderItem#getCount()} 求和 + * + * 对应 taobao 的 trade.total_fee 字段 + */ + private Integer totalPrice; + /** + * 订单优惠(总),单位:分 + * + * 对应 taobao 的 order.discount_fee 字段 + */ + private Integer discountPrice; + /** + * 运费金额,单位:分 + */ + private Integer deliveryPrice; + /** + * 优惠劵减免金额(总),单位:分 + * + * 对应 taobao 的 trade.coupon_fee 字段 + */ + private Integer couponPrice; + /** + * 积分抵扣的金额,单位:分 + * + * 对应 taobao 的 trade.point_fee 字段 + */ + private Integer pointPrice; + /** + * 最终购买金额(总),单位:分 + * + * = {@link #totalPrice} + * - {@link #couponPrice} + * - {@link #pointPrice} + * - {@link #discountPrice} + * + {@link #deliveryPrice} + */ + private Integer payPrice; + + } + + /** + * 订单商品 SKU + */ + @Data + public static class OrderItem { + + /** + * SPU 编号 + */ + private Long spuId; + /** + * SKU 编号 + */ + private Long skuId; + /** + * 购买数量 + */ + private Integer count; + /** + * 购物车项的编号 + */ + private Long cartId; + /** + * 是否选中 + */ + private Boolean selected; + + /** + * 商品原价(单),单位:分 + * + * 对应 ProductSkuDO 的 price 字段 + * 对应 taobao 的 order.price 字段 + */ + private Integer price; + /** + * 优惠金额(总),单位:分 + * + * 对应 taobao 的 order.discount_fee 字段 + */ + private Integer discountPrice; + /** + * 运费金额(总),单位:分 + */ + private Integer deliveryPrice; + /** + * 优惠劵减免金额,单位:分 + * + * 对应 taobao 的 trade.coupon_fee 字段 + */ + private Integer couponPrice; + /** + * 积分抵扣的金额,单位:分 + * + * 对应 taobao 的 trade.point_fee 字段 + */ + private Integer pointPrice; + /** + * 应付金额(总),单位:分 + * + * = {@link #price} * {@link #count} + * - {@link #couponPrice} + * - {@link #pointPrice} + * - {@link #discountPrice} + * + {@link #deliveryPrice} + */ + private Integer payPrice; + + // TODO 芋艿:这里补充下基本信息,简单一点。 + + } + + /** + * 营销明细 + */ + @Data + public static class Promotion { + + /** + * 营销编号 + * + * 例如说:营销活动的编号、优惠劵的编号 + */ + private Long id; + /** + * 营销名字 + */ + private String name; + /** + * 营销类型 + * + * 枚举 {@link PromotionTypeEnum} + */ + private Integer type; + /** + * 营销级别 + * + * 枚举 {@link PromotionLevelEnum} + */ + private Integer level; + /** + * 计算时的原价(总),单位:分 + */ + private Integer totalPrice; + /** + * 计算时的优惠(总),单位:分 + */ + private Integer discountPrice; + /** + * 匹配的商品 SKU 数组 + */ + private List items; + + // ========== 匹配情况 ========== + + /** + * 是否满足优惠条件 + */ + private Boolean match; + /** + * 满足条件的提示 + * + * 如果 {@link #match} = true 满足,则提示“圣诞价:省 150.00 元” + * 如果 {@link #match} = false 不满足,则提示“购满 85 元,可减 40 元” + */ + private String description; + + } + + /** + * 营销匹配的商品 SKU + */ + @Data + public static class PromotionItem { + + /** + * 商品 SKU 编号 + */ + private Long skuId; + /** + * 计算时的原价(总),单位:分 + */ + private Integer totalPrice; + /** + * 计算时的优惠(总),单位:分 + */ + private Integer discountPrice; + + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java new file mode 100644 index 000000000..52ebf84a0 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java @@ -0,0 +1,109 @@ +package cn.iocoder.yudao.module.trade.service.price.calculator; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; +import java.util.function.Predicate; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_NO_MATCH_MIN_PRICE; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_NO_MATCH_SPU; + +/** + * 优惠劵的 {@link TradePriceCalculator} 实现类 + * + * @author 芋道源码 + */ +@Component +@Order(TradePriceCalculator.ORDER_COUPON) +public class TradeCouponPriceCalculator implements TradePriceCalculator { + + @Resource + private CouponApi couponApi; + + @Override + public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { + // 1.1 校验优惠劵 + if (param.getCouponId() == null) { + return; + } + CouponRespDTO coupon = couponApi.validateCoupon(new CouponValidReqDTO() + .setId(param.getCouponId()).setUserId(param.getUserId())); + Assert.notNull(coupon, "校验通过的优惠劵({}),不能为空", param.getCouponId()); + + // 2.1 获得匹配的商品 SKU 数组 + List orderItems = filterMatchCouponOrderItems(result, coupon); + if (CollUtil.isEmpty(orderItems)) { + throw exception(COUPON_NO_MATCH_SPU); + } + // 2.2 计算是否满足优惠劵的使用金额 + Integer totalPayPrice = TradePriceCalculatorHelper.calculateTotalPayPrice(orderItems); + if (totalPayPrice < coupon.getUsePrice()) { + throw exception(COUPON_NO_MATCH_MIN_PRICE); + } + + // 3.1 计算可以优惠的金额 + Integer couponPrice = getCouponPrice(coupon, totalPayPrice); + Assert.isTrue(couponPrice < totalPayPrice, + "优惠劵({}) 的优惠金额({}),不能大于订单总金额({})", coupon.getId(), couponPrice, totalPayPrice); + // 3.2 计算分摊的优惠金额 + List divideCouponPrices = TradePriceCalculatorHelper.dividePrice(orderItems, couponPrice); + + // 4.1 记录使用的优惠劵 + result.setCouponId(param.getCouponId()); + // 4.2 记录优惠明细 + TradePriceCalculatorHelper.addPromotion(result, orderItems, + param.getCouponId(), coupon.getName(), PromotionTypeEnum.COUPON.getType(), + StrUtil.format("优惠劵:省 {} 元", TradePriceCalculatorHelper.formatPrice(couponPrice)), + divideCouponPrices); + // 4.3 更新 SKU 优惠金额 + for (int i = 0; i < orderItems.size(); i++) { + TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i); + orderItem.setCouponPrice(divideCouponPrices.get(i)); + TradePriceCalculatorHelper.recountPayPrice(orderItem); + } + TradePriceCalculatorHelper.recountAllPrice(result); + } + + private Integer getCouponPrice(CouponRespDTO coupon, Integer totalPayPrice) { + if (PromotionDiscountTypeEnum.PRICE.getType().equals(coupon.getDiscountType())) { // 减价 + return coupon.getDiscountPrice(); + } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(coupon.getDiscountType())) { // 打折 + int couponPrice = totalPayPrice * coupon.getDiscountPercent() / 100; + return coupon.getDiscountLimitPrice() == null ? couponPrice + : Math.min(couponPrice, coupon.getDiscountLimitPrice()); // 优惠上限 + } + throw new IllegalArgumentException(String.format("优惠劵(%s) 的优惠类型不正确", coupon)); + } + + /** + * 获得优惠劵可使用的订单项(商品)列表 + * + * @param result 计算结果 + * @param coupon 优惠劵 + * @return 订单项(商品)列表 + */ + private List filterMatchCouponOrderItems(TradePriceCalculateRespBO result, + CouponRespDTO coupon) { + Predicate matchPredicate = TradePriceCalculateRespBO.OrderItem::getSelected; + if (PromotionProductScopeEnum.SPU.getScope().equals(coupon.getProductScope())) { + matchPredicate = orderItem -> coupon.getProductSpuIds().contains(orderItem.getSpuId()); + } + return filterList(result.getItems(), matchPredicate); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java new file mode 100644 index 000000000..7bcd8ffb7 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.trade.service.price.calculator; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.promotion.api.discount.DiscountActivityApi; +import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper.formatPrice; + +/** + * 限时折扣的 {@link TradePriceCalculator} 实现类 + * + * @author 芋道源码 + */ +@Component +@Order(TradePriceCalculator.ORDER_DISCOUNT_ACTIVITY) +public class TradeDiscountActivityPriceCalculator implements TradePriceCalculator { + + @Resource + private DiscountActivityApi discountActivityApi; + + @Override + public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { + // 获得 SKU 对应的限时折扣活动 + List discountProducts = discountActivityApi.getMatchDiscountProductList( + convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSkuId)); + if (CollUtil.isEmpty(discountProducts)) { + return; + } + Map discountProductMap = convertMap(discountProducts, DiscountProductRespDTO::getSkuId); + + // 处理每个 SKU 的限时折扣 + result.getItems().forEach(orderItem -> { + // 1. 获取该 SKU 的优惠信息 + DiscountProductRespDTO discountProduct = discountProductMap.get(orderItem.getSkuId()); + if (discountProduct == null) { + return; + } + // 2. 计算优惠金额 + Integer newPayPrice = calculatePayPrice(discountProduct, orderItem); + Integer newDiscountPrice = orderItem.getPayPrice() - newPayPrice; + + // 3.1 记录优惠明细 + TradePriceCalculatorHelper.addPromotion(result, orderItem, + discountProduct.getActivityId(), discountProduct.getActivityName(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType(), + StrUtil.format("限时折扣:省 {} 元", formatPrice(newDiscountPrice)), + newDiscountPrice); + // 3.2 更新 SKU 优惠金额 + orderItem.setDiscountPrice(orderItem.getDiscountPrice() + newDiscountPrice); + TradePriceCalculatorHelper.recountPayPrice(orderItem); + }); + TradePriceCalculatorHelper.recountAllPrice(result); + } + + private Integer calculatePayPrice(DiscountProductRespDTO discountProduct, + TradePriceCalculateRespBO.OrderItem orderItem) { + Integer price = orderItem.getPayPrice(); + if (PromotionDiscountTypeEnum.PRICE.getType().equals(discountProduct.getDiscountType())) { // 减价 + price -= discountProduct.getDiscountPrice() * orderItem.getCount(); + } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(discountProduct.getDiscountType())) { // 打折 + price = price * discountProduct.getDiscountPercent() / 100; + } else { + throw new IllegalArgumentException(String.format("优惠活动的商品(%s) 的优惠类型不正确", discountProduct)); + } + return price; + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculator.java new file mode 100644 index 000000000..1c9b4f988 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculator.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.trade.service.price.calculator; + +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; + +/** + * 价格计算的计算器接口 + * + * @author 芋道源码 + */ +public interface TradePriceCalculator { + + int ORDER_DISCOUNT_ACTIVITY = 10; + int ORDER_REWARD_ACTIVITY = 20; + int ORDER_COUPON = 30; + + void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java new file mode 100644 index 000000000..9ed94b692 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java @@ -0,0 +1,221 @@ +package cn.iocoder.yudao.module.trade.service.price.calculator; + +import cn.hutool.core.lang.Assert; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; +import static java.util.Collections.singletonList; + +/** + * {@link TradePriceCalculator} 的工具类 + * + * 主要实现对 {@link TradePriceCalculateRespBO} 计算结果的操作 + * + * @author 芋道源码 + */ +public class TradePriceCalculatorHelper { + + public static TradePriceCalculateRespBO buildCalculateResp(TradePriceCalculateReqBO param, + List skuList) { + // 创建 PriceCalculateRespDTO 对象 + TradePriceCalculateRespBO result = new TradePriceCalculateRespBO(); + result.setOrderType(param.getOrderType()); + // 创建它的 OrderItem 属性 + Map skuItemMap = convertMap(param.getItems(), + TradePriceCalculateReqBO.Item::getSkuId); + result.setItems(new ArrayList<>(skuItemMap.size())); + skuList.forEach(sku -> { + TradePriceCalculateReqBO.Item skuItem = skuItemMap.get(sku.getId()); + TradePriceCalculateRespBO.OrderItem orderItem = new TradePriceCalculateRespBO.OrderItem() + // SKU 字段 + .setSpuId(sku.getSpuId()).setSkuId(sku.getId()) + .setCount(skuItem.getCount()).setCartId(skuItem.getCartId()).setSelected(skuItem.getSelected()) + // 价格字段 + .setPrice(sku.getPrice()).setPayPrice(sku.getPrice() * skuItem.getCount()) + .setDiscountPrice(0).setDeliveryPrice(0).setCouponPrice(0).setPointPrice(0); + result.getItems().add(orderItem); + }); + // 创建它的 Price 属性 + result.setPrice(new TradePriceCalculateRespBO.Price()); + recountAllPrice(result); + return result; + } + + /** + * 基于订单项,重新计算 price 总价 + * + * @param result 计算结果 + */ + public static void recountAllPrice(TradePriceCalculateRespBO result) { + // 先重置 + TradePriceCalculateRespBO.Price price = result.getPrice(); + price.setTotalPrice(0).setDiscountPrice(0).setDeliveryPrice(0) + .setCouponPrice(0).setPointPrice(0).setPayPrice(0); + // 再合计 item + result.getItems().forEach(item -> { + if (!item.getSelected()) { + return; + } + price.setTotalPrice(price.getTotalPrice() + item.getPrice() * item.getCount()); + price.setDiscountPrice(price.getDiscountPrice() + item.getDiscountPrice()); + price.setDeliveryPrice(price.getDeliveryPrice() + item.getDeliveryPrice()); + price.setCouponPrice(price.getCouponPrice() + item.getCouponPrice()); + price.setPointPrice(price.getPointPrice() + item.getPointPrice()); + price.setPayPrice(price.getPayPrice() + item.getPayPrice()); + }); + } + + /** + * 重新计算单个订单项的支付金额 + * + * @param orderItem 订单项 + */ + public static void recountPayPrice(TradePriceCalculateRespBO.OrderItem orderItem) { + orderItem.setPayPrice(orderItem.getPrice()* orderItem.getCount() + - orderItem.getDiscountPrice() + + orderItem.getDeliveryPrice() + - orderItem.getCouponPrice() + - orderItem.getPointPrice()); + } + + /** + * 计算已选中的订单项,总支付金额 + * + * @param orderItems 订单项数组 + * @return 总支付金额 + */ + public static Integer calculateTotalPayPrice(List orderItems) { + return getSumValue(orderItems, + orderItem -> orderItem.getSelected() ? orderItem.getPayPrice() : 0, // 未选中的情况下,不计算支付金额 + Integer::sum); + } + + /** + * 计算已选中的订单项,总商品数 + * + * @param orderItems 订单项数组 + * @return 总商品数 + */ + public static Integer calculateTotalCount(List orderItems) { + return getSumValue(orderItems, + orderItem -> orderItem.getSelected() ? orderItem.getCount() : 0, // 未选中的情况下,不计算数量 + Integer::sum); + } + + /** + * 按照支付金额,返回每个订单项的分摊金额数组 + * + * @param orderItems 订单项数组 + * @param price 金额 + * @return 分摊金额数组,和传入的 orderItems 一一对应 + */ + public static List dividePrice(List orderItems, Integer price) { + Integer total = calculateTotalPayPrice(orderItems); + assert total != null; + // 遍历每一个,进行分摊 + List prices = new ArrayList<>(orderItems.size()); + int remainPrice = price; + for (int i = 0; i < orderItems.size(); i++) { + TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i); + // 1. 如果是未选中,则分摊为 0 + if (!orderItem.getSelected()) { + prices.add(0); + continue; + } + // 2. 如果选中,则按照百分比,进行分摊 + int partPrice; + if (i < orderItems.size() - 1) { // 减一的原因,是因为拆分时,如果按照比例,可能会出现.所以最后一个,使用反减 + partPrice = (int) (price * (1.0D * orderItem.getPayPrice() / total)); + remainPrice -= partPrice; + } else { + partPrice = remainPrice; + } + Assert.isTrue(partPrice >= 0, "分摊金额必须大于等于 0"); + prices.add(partPrice); + } + return prices; + } + + /** + * 添加【匹配】单个 OrderItem 的营销明细 + * + * @param result 价格计算结果 + * @param orderItem 单个订单商品 SKU + * @param id 营销编号 + * @param name 营销名字 + * @param description 满足条件的提示 + * @param type 营销类型 + * @param discountPrice 单个订单商品 SKU 的优惠价格(总) + */ + public static void addPromotion(TradePriceCalculateRespBO result, TradePriceCalculateRespBO.OrderItem orderItem, + Long id, String name, Integer type, String description, Integer discountPrice) { + addPromotion(result, singletonList(orderItem), id, name, type, description, singletonList(discountPrice)); + } + + /** + * 添加【匹配】多个 OrderItem 的营销明细 + * + * @param result 价格计算结果 + * @param orderItems 多个订单商品 SKU + * @param id 营销编号 + * @param name 营销名字 + * @param description 满足条件的提示 + * @param type 营销类型 + * @param discountPrices 多个订单商品 SKU 的优惠价格(总),和 orderItems 一一对应 + */ + public static void addPromotion(TradePriceCalculateRespBO result, List orderItems, + Long id, String name, Integer type, String description, List discountPrices) { + // 创建营销明细 Item + List promotionItems = new ArrayList<>(discountPrices.size()); + for (int i = 0; i < orderItems.size(); i++) { + TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i); + promotionItems.add(new TradePriceCalculateRespBO.PromotionItem().setSkuId(orderItem.getSkuId()) + .setTotalPrice(orderItem.getPayPrice()).setDiscountPrice(discountPrices.get(i))); + } + // 创建营销明细 + TradePriceCalculateRespBO.Promotion promotion = new TradePriceCalculateRespBO.Promotion() + .setId(id).setName(name).setType(type) + .setTotalPrice(calculateTotalPayPrice(orderItems)) + .setDiscountPrice(getSumValue(discountPrices, value -> value, Integer::sum)) + .setItems(promotionItems).setMatch(true).setDescription(description); + result.getPromotions().add(promotion); + } + + /** + * 添加【不匹配】多个 OrderItem 的营销明细 + * + * @param result 价格计算结果 + * @param orderItems 多个订单商品 SKU + * @param id 营销编号 + * @param name 营销名字 + * @param description 满足条件的提示 + * @param type 营销类型 + */ + public static void addNotMatchPromotion(TradePriceCalculateRespBO result, List orderItems, + Long id, String name, Integer type, String description) { + // 创建营销明细 Item + List promotionItems = CollectionUtils.convertList(orderItems, + orderItem -> new TradePriceCalculateRespBO.PromotionItem().setSkuId(orderItem.getSkuId()) + .setTotalPrice(orderItem.getPayPrice()).setDiscountPrice(0)); + // 创建营销明细 + TradePriceCalculateRespBO.Promotion promotion = new TradePriceCalculateRespBO.Promotion() + .setId(id).setName(name).setType(type) + .setTotalPrice(calculateTotalPayPrice(orderItems)) + .setDiscountPrice(0) + .setItems(promotionItems).setMatch(false).setDescription(description); + result.getPromotions().add(promotion); + } + + public static String formatPrice(Integer price) { + return String.format("%.2f", price / 100d); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java new file mode 100644 index 000000000..b0947fcc3 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java @@ -0,0 +1,133 @@ +package cn.iocoder.yudao.module.trade.service.price.calculator; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.promotion.api.reward.RewardActivityApi; +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; +import static cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper.formatPrice; + +/** + * 满减送活动的 {@link TradePriceCalculator} 实现类 + * + * @author 芋道源码 + */ +@Component +@Order(TradePriceCalculator.ORDER_REWARD_ACTIVITY) +public class TradeRewardActivityPriceCalculator implements TradePriceCalculator { + + @Resource + private RewardActivityApi rewardActivityApi; + + @Override + public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { + // 获得 SKU 对应的满减送活动 + List rewardActivities = rewardActivityApi.getMatchRewardActivityList( + convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSpuId)); + if (CollUtil.isEmpty(rewardActivities)) { + return; + } + + // 处理每个满减送活动 + rewardActivities.forEach(rewardActivity -> calculate(param, result, rewardActivity)); + } + + private void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result, + RewardActivityMatchRespDTO rewardActivity) { + // 1.1 获得满减送的订单项(商品)列表 + List orderItems = filterMatchCouponOrderItems(result, rewardActivity); + if (CollUtil.isEmpty(orderItems)) { + return; + } + // 1.2 获得最大匹配的满减送活动的规则 + RewardActivityMatchRespDTO.Rule rule = getMaxMatchRewardActivityRule(rewardActivity, orderItems); + if (rule == null) { + return; + } + + // 2.1 计算可以优惠的金额 + Integer newDiscountPrice = rule.getDiscountPrice(); + // 2.2 计算分摊的优惠金额 + List divideDiscountPrices = TradePriceCalculatorHelper.dividePrice(orderItems, newDiscountPrice); + + // 3.1 记录使用的优惠劵 + result.setCouponId(param.getCouponId()); + // 3.2 记录优惠明细 + TradePriceCalculatorHelper.addPromotion(result, orderItems, + rewardActivity.getId(), rewardActivity.getName(), PromotionTypeEnum.REWARD_ACTIVITY.getType(), + StrUtil.format("满减送:省 {} 元", formatPrice(rule.getDiscountPrice())), + divideDiscountPrices); + // 3.3 更新 SKU 优惠金额 + for (int i = 0; i < orderItems.size(); i++) { + TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i); + orderItem.setDiscountPrice(orderItem.getDiscountPrice() + divideDiscountPrices.get(i)); + TradePriceCalculatorHelper.recountPayPrice(orderItem); + } + TradePriceCalculatorHelper.recountAllPrice(result); + } + + /** + * 获得满减送的订单项(商品)列表 + * + * @param result 计算结果 + * @param rewardActivity 满减送活动 + * @return 订单项(商品)列表 + */ + private List filterMatchCouponOrderItems(TradePriceCalculateRespBO result, + RewardActivityMatchRespDTO rewardActivity) { + return filterList(result.getItems(), + orderItem -> CollUtil.contains(rewardActivity.getSpuIds(), orderItem.getSpuId())); + } + + /** + * 获得最大匹配的满减送活动的规则 + * + * @param rewardActivity 满减送活动 + * @param orderItems 商品项 + * @return 匹配的活动规则 + */ + private RewardActivityMatchRespDTO.Rule getMaxMatchRewardActivityRule(RewardActivityMatchRespDTO rewardActivity, + List orderItems) { + // 1. 计算数量和价格 + Integer count = TradePriceCalculatorHelper.calculateTotalCount(orderItems); + Integer price = TradePriceCalculatorHelper.calculateTotalPayPrice(orderItems); + assert count != null && price != null; + + // 2. 倒序找一个最大优惠的规则 + for (int i = rewardActivity.getRules().size() - 1; i >= 0; i--) { + RewardActivityMatchRespDTO.Rule rule = rewardActivity.getRules().get(i); + if (PromotionConditionTypeEnum.PRICE.getType().equals(rewardActivity.getConditionType()) + && price >= rule.getLimit()) { + return rule; + } + if (PromotionConditionTypeEnum.COUNT.getType().equals(rewardActivity.getConditionType()) + && count >= rule.getLimit()) { + return rule; + } + } + return null; + } + + /** + * 获得满减送活动部匹配时的提示 + * + * @param rewardActivity 满减送活动 + * @return 提示 + */ + private String getRewardActivityNotMeetTip(RewardActivityMatchRespDTO rewardActivity) { + // TODO 芋艿:后面再想想;应该找第一个规则,算下还差多少即可。 + return "TODO"; + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java index bd65bddfd..78f1c7902 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreate import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressRespVO; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; import cn.iocoder.yudao.module.member.convert.address.AddressConvert; -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; import cn.iocoder.yudao.module.member.service.address.AddressService; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Parameter; @@ -54,21 +54,21 @@ public class AppAddressController { @Operation(summary = "获得用户收件地址") @Parameter(name = "id", description = "编号", required = true, example = "1024") public CommonResult getAddress(@RequestParam("id") Long id) { - AddressDO address = addressService.getAddress(getLoginUserId(), id); + MemberAddressDO address = addressService.getAddress(getLoginUserId(), id); return success(AddressConvert.INSTANCE.convert(address)); } @GetMapping("/get-default") @Operation(summary = "获得默认的用户收件地址") public CommonResult getDefaultUserAddress() { - AddressDO address = addressService.getDefaultUserAddress(getLoginUserId()); + MemberAddressDO address = addressService.getDefaultUserAddress(getLoginUserId()); return success(AddressConvert.INSTANCE.convert(address)); } @GetMapping("/list") @Operation(summary = "获得用户收件地址列表") public CommonResult> getAddressList() { - List list = addressService.getAddressList(getLoginUserId()); + List list = addressService.getAddressList(getLoginUserId()); return success(AddressConvert.INSTANCE.convertList(list)); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/address/AddressConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/address/AddressConvert.java index 49a01805d..a93d79ec1 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/address/AddressConvert.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/address/AddressConvert.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressRespVO; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -21,16 +21,16 @@ public interface AddressConvert { AddressConvert INSTANCE = Mappers.getMapper(AddressConvert.class); - AddressDO convert(AppAddressCreateReqVO bean); + MemberAddressDO convert(AppAddressCreateReqVO bean); - AddressDO convert(AppAddressUpdateReqVO bean); + MemberAddressDO convert(AppAddressUpdateReqVO bean); - AppAddressRespVO convert(AddressDO bean); + AppAddressRespVO convert(MemberAddressDO bean); - List convertList(List list); + List convertList(List list); - PageResult convertPage(PageResult page); + PageResult convertPage(PageResult page); - AddressRespDTO convert02(AddressDO bean); + AddressRespDTO convert02(MemberAddressDO bean); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/AddressDO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/MemberAddressDO.java similarity index 95% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/AddressDO.java rename to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/MemberAddressDO.java index 7d8a96250..560edbba9 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/AddressDO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/MemberAddressDO.java @@ -17,7 +17,7 @@ import lombok.*; @Builder @NoArgsConstructor @AllArgsConstructor -public class AddressDO extends BaseDO { +public class MemberAddressDO extends BaseDO { /** * 编号 diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/AddressMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/AddressMapper.java index 80f78d41f..13ca89ef9 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/AddressMapper.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/address/AddressMapper.java @@ -2,21 +2,21 @@ package cn.iocoder.yudao.module.member.dal.mysql.address; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper -public interface AddressMapper extends BaseMapperX { +public interface AddressMapper extends BaseMapperX { - default AddressDO selectByIdAndUserId(Long id, Long userId) { - return selectOne(AddressDO::getId, id, AddressDO::getUserId, userId); + default MemberAddressDO selectByIdAndUserId(Long id, Long userId) { + return selectOne(MemberAddressDO::getId, id, MemberAddressDO::getUserId, userId); } - default List selectListByUserIdAndDefaulted(Long userId, Boolean defaulted) { - return selectList(new LambdaQueryWrapperX().eq(AddressDO::getUserId, userId) - .eqIfPresent(AddressDO::getDefaulted, defaulted)); + default List selectListByUserIdAndDefaulted(Long userId, Boolean defaulted) { + return selectList(new LambdaQueryWrapperX().eq(MemberAddressDO::getUserId, userId) + .eqIfPresent(MemberAddressDO::getDefaulted, defaulted)); } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java index 456a3d8ac..099c49c42 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressService.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.member.service.address; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; import javax.validation.Valid; import java.util.List; @@ -46,7 +46,7 @@ public interface AddressService { * @param id 编号 * @return 用户收件地址 */ - AddressDO getAddress(Long userId, Long id); + MemberAddressDO getAddress(Long userId, Long id); /** * 获得用户收件地址列表 @@ -54,7 +54,7 @@ public interface AddressService { * @param userId 用户编号 * @return 用户收件地址列表 */ - List getAddressList(Long userId); + List getAddressList(Long userId); /** * 获得用户默认的收件地址 @@ -62,6 +62,6 @@ public interface AddressService { * @param userId 用户编号 * @return 用户收件地址 */ - AddressDO getDefaultUserAddress(Long userId); + MemberAddressDO getDefaultUserAddress(Long userId); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java index bbcbbe592..488e7d32c 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImpl.java @@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; import cn.iocoder.yudao.module.member.convert.address.AddressConvert; -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; import cn.iocoder.yudao.module.member.dal.mysql.address.AddressMapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -33,12 +33,12 @@ public class AddressServiceImpl implements AddressService { public Long createAddress(Long userId, AppAddressCreateReqVO createReqVO) { // 如果添加的是默认收件地址,则将原默认地址修改为非默认 if (Boolean.TRUE.equals(createReqVO.getDefaulted())) { - List addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); - addresses.forEach(address -> addressMapper.updateById(new AddressDO().setId(address.getId()).setDefaulted(false))); + List addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); + addresses.forEach(address -> addressMapper.updateById(new MemberAddressDO().setId(address.getId()).setDefaulted(false))); } // 插入 - AddressDO address = AddressConvert.INSTANCE.convert(createReqVO); + MemberAddressDO address = AddressConvert.INSTANCE.convert(createReqVO); address.setUserId(userId); addressMapper.insert(address); // 返回 @@ -53,13 +53,13 @@ public class AddressServiceImpl implements AddressService { // 如果修改的是默认收件地址,则将原默认地址修改为非默认 if (Boolean.TRUE.equals(updateReqVO.getDefaulted())) { - List addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); + List addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); addresses.stream().filter(u -> !u.getId().equals(updateReqVO.getId())) // 排除自己 - .forEach(address -> addressMapper.updateById(new AddressDO().setId(address.getId()).setDefaulted(false))); + .forEach(address -> addressMapper.updateById(new MemberAddressDO().setId(address.getId()).setDefaulted(false))); } // 更新 - AddressDO updateObj = AddressConvert.INSTANCE.convert(updateReqVO); + MemberAddressDO updateObj = AddressConvert.INSTANCE.convert(updateReqVO); addressMapper.updateById(updateObj); } @@ -72,25 +72,25 @@ public class AddressServiceImpl implements AddressService { } private void validAddressExists(Long userId, Long id) { - AddressDO addressDO = getAddress(userId, id); + MemberAddressDO addressDO = getAddress(userId, id); if (addressDO == null) { throw exception(ADDRESS_NOT_EXISTS); } } @Override - public AddressDO getAddress(Long userId, Long id) { + public MemberAddressDO getAddress(Long userId, Long id) { return addressMapper.selectByIdAndUserId(id, userId); } @Override - public List getAddressList(Long userId) { + public List getAddressList(Long userId) { return addressMapper.selectListByUserIdAndDefaulted(userId, null); } @Override - public AddressDO getDefaultUserAddress(Long userId) { - List addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); + public MemberAddressDO getDefaultUserAddress(Long userId) { + List addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); return CollUtil.getFirst(addresses); } diff --git a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java index 6ddf80a0e..77b40705e 100644 --- a/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java +++ b/yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/address/AddressServiceImplTest.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.member.service.address; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; import cn.iocoder.yudao.module.member.dal.mysql.address.AddressMapper; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; @@ -42,14 +42,14 @@ public class AddressServiceImplTest extends BaseDbUnitTest { // 断言 assertNotNull(addressId); // 校验记录的属性是否正确 - AddressDO address = addressMapper.selectById(addressId); + MemberAddressDO address = addressMapper.selectById(addressId); assertPojoEquals(reqVO, address); } @Test public void testUpdateAddress_success() { // mock 数据 - AddressDO dbAddress = randomPojo(AddressDO.class); + MemberAddressDO dbAddress = randomPojo(MemberAddressDO.class); addressMapper.insert(dbAddress);// @Sql: 先插入出一条存在的数据 // 准备参数 AppAddressUpdateReqVO reqVO = randomPojo(AppAddressUpdateReqVO.class, o -> { @@ -59,7 +59,7 @@ public class AddressServiceImplTest extends BaseDbUnitTest { // 调用 addressService.updateAddress(dbAddress.getUserId(), reqVO); // 校验是否更新正确 - AddressDO address = addressMapper.selectById(reqVO.getId()); // 获取最新的 + MemberAddressDO address = addressMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, address); } @@ -75,7 +75,7 @@ public class AddressServiceImplTest extends BaseDbUnitTest { @Test public void testDeleteAddress_success() { // mock 数据 - AddressDO dbAddress = randomPojo(AddressDO.class); + MemberAddressDO dbAddress = randomPojo(MemberAddressDO.class); addressMapper.insert(dbAddress);// @Sql: 先插入出一条存在的数据 // 准备参数 Long id = dbAddress.getId(); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/ip/AreaConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/ip/AreaConvert.java index 05d193717..18609edb1 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/ip/AreaConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/ip/AreaConvert.java @@ -23,7 +23,8 @@ public interface AreaConvert { @Mapping(source = "type", target = "leaf") AreaNodeSimpleRespVO convert(Area area); - default Boolean convertAreaType(Integer type){ - return Objects.equals(AreaTypeEnum.DISTRICT.getType(),type); + default Boolean convertAreaType(Integer type) { + return Objects.equals(AreaTypeEnum.DISTRICT.getType(), type); } + }