Commit fcaa92d40695af8bb23380320ca9e7c68362dab3
Merge remote-tracking branch 'yudao/feature/mall_product' into feature/mall_product
Showing
92 changed files
with
1854 additions
and
1103 deletions
sql/mysql/optional/mall.sql
| ... | ... | @@ -330,9 +330,9 @@ CREATE TABLE `product_favorite` ( |
| 330 | 330 | -- ---------------------------- |
| 331 | 331 | DROP TABLE IF EXISTS `trade_delivery_express_template`; |
| 332 | 332 | CREATE TABLE `trade_delivery_express_template` ( |
| 333 | - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号,自增', | |
| 333 | + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', | |
| 334 | 334 | `name` varchar(64) NOT NULL COMMENT '模板名称', |
| 335 | - `charge_mode` tinyint NOT NULL DEFAULT 1 COMMENT '配送计费方式 1:按件 2:按重量 3:按体积', | |
| 335 | + `charge_mode` tinyint NOT NULL COMMENT '配送计费方式', | |
| 336 | 336 | `sort` int NOT NULL DEFAULT 0 COMMENT '排序', |
| 337 | 337 | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', |
| 338 | 338 | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', |
| ... | ... | @@ -348,11 +348,11 @@ CREATE TABLE `trade_delivery_express_template` ( |
| 348 | 348 | -- ---------------------------- |
| 349 | 349 | DROP TABLE IF EXISTS `trade_delivery_express_template_free`; |
| 350 | 350 | CREATE TABLE `trade_delivery_express_template_free` ( |
| 351 | - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号,自增', | |
| 352 | - `template_id` bigint NOT NULL COMMENT '配送模板编号, 对应delivery_template表id', | |
| 353 | - `area_id` int NOT NULL COMMENT '包邮区域id', | |
| 354 | - `free_price` int NOT NULL COMMENT '包邮金额(单位分) 订单总金额>包邮金额才免运费', | |
| 355 | - `free_count` int NOT NULL DEFAULT 0 COMMENT '包邮件数,订单总件数>包邮件数才免运费', | |
| 351 | + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', | |
| 352 | + `template_id` bigint NOT NULL COMMENT '快递运费模板编号', | |
| 353 | + `area_ids` varchar(100) NOT NULL COMMENT '包邮区域 ids', | |
| 354 | + `free_price` int NOT NULL COMMENT '包邮金额,单位:分', | |
| 355 | + `free_count` int NOT NULL DEFAULT 0 COMMENT '包邮件数,', | |
| 356 | 356 | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', |
| 357 | 357 | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', |
| 358 | 358 | `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', |
| ... | ... | @@ -368,13 +368,13 @@ CREATE TABLE `trade_delivery_express_template_free` ( |
| 368 | 368 | DROP TABLE IF EXISTS `trade_delivery_express_template_charge`; |
| 369 | 369 | CREATE TABLE `trade_delivery_express_template_charge` ( |
| 370 | 370 | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号,自增', |
| 371 | - `template_id` bigint NOT NULL COMMENT '配送模板编号, 对应delivery_template表id', | |
| 372 | - `area_id` int NOT NULL COMMENT '配送区域id 1:适用于全国', | |
| 373 | - `charge_mode` tinyint NOT NULL COMMENT '配送计费方式 1:按件 2:按重量 3:按体积', | |
| 374 | - `start_count` double NOT NULL COMMENT '首件数量(件数,重量,或体积)', | |
| 375 | - `start_price` int NOT NULL COMMENT '起步价(单位分)', | |
| 376 | - `extra_count` double NOT NULL COMMENT '续件数量(件,重量,或体积)', | |
| 377 | - `extra_price` int NOT NULL COMMENT '额外价(单位分)', | |
| 371 | + `template_id` bigint NOT NULL COMMENT '快递运费模板编号', | |
| 372 | + `area_ids` varchar(100) NOT NULL COMMENT '配送区域 ids', | |
| 373 | + `charge_mode` tinyint NOT NULL COMMENT '配送计费方式', | |
| 374 | + `start_count` double NOT NULL COMMENT '首件数量', | |
| 375 | + `start_price` int NOT NULL COMMENT '起步价,单位:分', | |
| 376 | + `extra_count` double NOT NULL COMMENT '续件数量', | |
| 377 | + `extra_price` int NOT NULL COMMENT '额外价,单位:分', | |
| 378 | 378 | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', |
| 379 | 379 | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', |
| 380 | 380 | `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`; |
| 417 | 417 | CREATE TABLE `trade_delivery_pick_up_store_staff` ( |
| 418 | 418 | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号,自增', |
| 419 | 419 | store_id bigint NOT NULL COMMENT '自提门店编号', |
| 420 | - `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态(0正常 1停用)', | |
| 420 | + `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态', | |
| 421 | 421 | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', |
| 422 | 422 | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', |
| 423 | 423 | `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` ( |
| 451 | 451 | -- ---------------------------- |
| 452 | 452 | DROP TABLE IF EXISTS `trade_delivery_express`; |
| 453 | 453 | CREATE TABLE `trade_delivery_express` ( |
| 454 | - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号,自增', | |
| 455 | - `code` varchar(64) NOT NULL COMMENT '快递公司编号', | |
| 454 | + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', | |
| 455 | + `code` varchar(64) NOT NULL COMMENT '快递公司编码', | |
| 456 | 456 | `name` varchar(64) NOT NULL COMMENT '快递公司名称', |
| 457 | - `logo` varchar(256) COMMENT '快递公司logo', | |
| 457 | + `logo` varchar(256) COMMENT '快递公司 logo', | |
| 458 | 458 | `sort` int NOT NULL DEFAULT 0 COMMENT '排序', |
| 459 | - `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态(0正常 1停用)', | |
| 459 | + `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态', | |
| 460 | 460 | `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', |
| 461 | 461 | `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', |
| 462 | 462 | `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', |
| ... | ... | @@ -501,7 +501,7 @@ INSERT INTO `ruoyi-vue-pro`.`system_menu` (`id`, `name`, `permission`, `type`, ` |
| 501 | 501 | 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'); |
| 502 | 502 | 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'); |
| 503 | 503 | 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'); |
| 504 | -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'); | |
| 504 | +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'); | |
| 505 | 505 | 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'); |
| 506 | 506 | 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'); |
| 507 | 507 | 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'); |
| ... | ... | @@ -540,4 +540,4 @@ INSERT INTO `ruoyi-vue-pro`.`system_dict_type` (`id`, `name`, `type`, `status`, |
| 540 | 540 | 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'); |
| 541 | 541 | 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'); |
| 542 | 542 | 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'); |
| 543 | -COMMIT; | |
| 544 | 543 | \ No newline at end of file |
| 544 | +COMMIT; | ... | ... |
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java
| ... | ... | @@ -40,9 +40,14 @@ public class StrUtils { |
| 40 | 40 | return false; |
| 41 | 41 | } |
| 42 | 42 | |
| 43 | - public static List<Long> splitToLong(String value, CharSequence separator) { | |
| 43 | + public static List<Long> splitToLong(String value, CharSequence separator) { | |
| 44 | 44 | long[] longs = StrUtil.splitToLong(value, separator); |
| 45 | 45 | return Arrays.stream(longs).boxed().collect(Collectors.toList()); |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | + public static List<Integer> splitToInteger(String value, CharSequence separator) { | |
| 49 | + int[] integers = StrUtil.splitToInt(value, separator); | |
| 50 | + return Arrays.stream(integers).boxed().collect(Collectors.toList()); | |
| 51 | + } | |
| 52 | + | |
| 48 | 53 | } | ... | ... |
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<T> extends MPJBaseMapper<T> { |
| 113 | 113 | Db.saveBatch(entities, size); |
| 114 | 114 | } |
| 115 | 115 | |
| 116 | + // @芋艿 是不是叫 updateByDo 或者 updateByEntity 更合适;回复:因为是使用实体作为条件去批量更新,所以没加 ByEntity,保持和 mybatis plus 风格一致 | |
| 116 | 117 | default void updateBatch(T update) { |
| 117 | 118 | update(update, new QueryWrapper<>()); |
| 118 | 119 | } |
| 119 | 120 | |
| 121 | + /** | |
| 122 | + * 根据ID 批量更新,适合大量数据更新 | |
| 123 | + * | |
| 124 | + * @param entities 实体们 | |
| 125 | + */ | |
| 126 | + default void updateBatch(Collection<T> entities) { | |
| 127 | + Db.updateBatchById(entities); | |
| 128 | + } | |
| 129 | + | |
| 120 | 130 | default void updateBatch(Collection<T> entities, int size) { |
| 121 | 131 | Db.updateBatchById(entities, size); |
| 122 | 132 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/type/IntegerListTypeHandler.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.mybatis.core.type; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.iocoder.yudao.framework.common.util.string.StrUtils; | |
| 5 | +import org.apache.ibatis.type.JdbcType; | |
| 6 | +import org.apache.ibatis.type.MappedJdbcTypes; | |
| 7 | +import org.apache.ibatis.type.MappedTypes; | |
| 8 | +import org.apache.ibatis.type.TypeHandler; | |
| 9 | + | |
| 10 | +import java.sql.CallableStatement; | |
| 11 | +import java.sql.PreparedStatement; | |
| 12 | +import java.sql.ResultSet; | |
| 13 | +import java.sql.SQLException; | |
| 14 | +import java.util.List; | |
| 15 | + | |
| 16 | +/** | |
| 17 | + * List<Integer> 的类型转换器实现类,对应数据库的 varchar 类型 | |
| 18 | + * | |
| 19 | + * @author jason | |
| 20 | + */ | |
| 21 | +@MappedJdbcTypes(JdbcType.VARCHAR) | |
| 22 | +@MappedTypes(List.class) | |
| 23 | +public class IntegerListTypeHandler implements TypeHandler<List<Integer>> { | |
| 24 | + | |
| 25 | + private static final String COMMA = ","; | |
| 26 | + | |
| 27 | + @Override | |
| 28 | + public void setParameter(PreparedStatement ps, int i, List<Integer> strings, JdbcType jdbcType) throws SQLException { | |
| 29 | + ps.setString(i, CollUtil.join(strings, COMMA)); | |
| 30 | + } | |
| 31 | + | |
| 32 | + @Override | |
| 33 | + public List<Integer> getResult(ResultSet rs, String columnName) throws SQLException { | |
| 34 | + String value = rs.getString(columnName); | |
| 35 | + return getResult(value); | |
| 36 | + } | |
| 37 | + | |
| 38 | + @Override | |
| 39 | + public List<Integer> getResult(ResultSet rs, int columnIndex) throws SQLException { | |
| 40 | + String value = rs.getString(columnIndex); | |
| 41 | + return getResult(value); | |
| 42 | + } | |
| 43 | + | |
| 44 | + @Override | |
| 45 | + public List<Integer> getResult(CallableStatement cs, int columnIndex) throws SQLException { | |
| 46 | + String value = cs.getString(columnIndex); | |
| 47 | + return getResult(value); | |
| 48 | + } | |
| 49 | + | |
| 50 | + private List<Integer> getResult(String value) { | |
| 51 | + if (value == null) { | |
| 52 | + return null; | |
| 53 | + } | |
| 54 | + return StrUtils.splitToInteger(value, COMMA); | |
| 55 | + } | |
| 56 | +} | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java
| 1 | 1 | package cn.iocoder.yudao.module.promotion.api.coupon; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; | |
| 3 | 4 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; |
| 5 | +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; | |
| 4 | 6 | |
| 5 | 7 | import javax.validation.Valid; |
| 6 | 8 | |
| ... | ... | @@ -18,4 +20,12 @@ public interface CouponApi { |
| 18 | 20 | */ |
| 19 | 21 | void useCoupon(@Valid CouponUseReqDTO useReqDTO); |
| 20 | 22 | |
| 23 | + /** | |
| 24 | + * 校验优惠劵 | |
| 25 | + * | |
| 26 | + * @param validReqDTO 校验请求 | |
| 27 | + * @return 优惠劵 | |
| 28 | + */ | |
| 29 | + CouponRespDTO validateCoupon(@Valid CouponValidReqDTO validReqDTO); | |
| 30 | + | |
| 21 | 31 | } | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponRespDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.api.coupon.dto; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; | |
| 4 | +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; | |
| 5 | +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; | |
| 6 | +import lombok.Data; | |
| 7 | + | |
| 8 | +import java.time.LocalDateTime; | |
| 9 | +import java.util.List; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 优惠劵 Response DTO | |
| 13 | + * | |
| 14 | + * @author 芋道源码 | |
| 15 | + */ | |
| 16 | +@Data | |
| 17 | +public class CouponRespDTO { | |
| 18 | + | |
| 19 | + // ========== 基本信息 BEGIN ========== | |
| 20 | + /** | |
| 21 | + * 优惠劵编号 | |
| 22 | + */ | |
| 23 | + private Long id; | |
| 24 | + /** | |
| 25 | + * 优惠劵模板编号 | |
| 26 | + */ | |
| 27 | + private Integer templateId; | |
| 28 | + /** | |
| 29 | + * 优惠劵名 | |
| 30 | + */ | |
| 31 | + private String name; | |
| 32 | + /** | |
| 33 | + * 优惠码状态 | |
| 34 | + * | |
| 35 | + * 枚举 {@link CouponStatusEnum} | |
| 36 | + */ | |
| 37 | + private Integer status; | |
| 38 | + | |
| 39 | + // ========== 基本信息 END ========== | |
| 40 | + | |
| 41 | + // ========== 领取情况 BEGIN ========== | |
| 42 | + /** | |
| 43 | + * 用户编号 | |
| 44 | + * | |
| 45 | + * 关联 MemberUserDO 的 id 字段 | |
| 46 | + */ | |
| 47 | + private Long userId; | |
| 48 | + /** | |
| 49 | + * 领取类型 | |
| 50 | + * | |
| 51 | + * 枚举 {@link CouponTakeTypeEnum} | |
| 52 | + */ | |
| 53 | + private Integer takeType; | |
| 54 | + // ========== 领取情况 END ========== | |
| 55 | + | |
| 56 | + // ========== 使用规则 BEGIN ========== | |
| 57 | + /** | |
| 58 | + * 是否设置满多少金额可用,单位:分 | |
| 59 | + */ | |
| 60 | + private Integer usePrice; | |
| 61 | + /** | |
| 62 | + * 生效开始时间 | |
| 63 | + */ | |
| 64 | + private LocalDateTime validStartTime; | |
| 65 | + /** | |
| 66 | + * 生效结束时间 | |
| 67 | + */ | |
| 68 | + private LocalDateTime validEndTime; | |
| 69 | + /** | |
| 70 | + * 商品范围 | |
| 71 | + */ | |
| 72 | + private Integer productScope; | |
| 73 | + /** | |
| 74 | + * 商品 SPU 编号的数组 | |
| 75 | + */ | |
| 76 | + private List<Long> productSpuIds; | |
| 77 | + // ========== 使用规则 END ========== | |
| 78 | + | |
| 79 | + // ========== 使用效果 BEGIN ========== | |
| 80 | + /** | |
| 81 | + * 折扣类型 | |
| 82 | + */ | |
| 83 | + private Integer discountType; | |
| 84 | + /** | |
| 85 | + * 折扣百分比 | |
| 86 | + */ | |
| 87 | + private Integer discountPercent; | |
| 88 | + /** | |
| 89 | + * 优惠金额,单位:分 | |
| 90 | + */ | |
| 91 | + private Integer discountPrice; | |
| 92 | + /** | |
| 93 | + * 折扣上限,仅在 {@link #discountType} 等于 {@link PromotionDiscountTypeEnum#PERCENT} 时生效 | |
| 94 | + */ | |
| 95 | + private Integer discountLimitPrice; | |
| 96 | + // ========== 使用效果 END ========== | |
| 97 | + | |
| 98 | + // ========== 使用情况 BEGIN ========== | |
| 99 | + /** | |
| 100 | + * 使用订单号 | |
| 101 | + */ | |
| 102 | + private Long useOrderId; | |
| 103 | + /** | |
| 104 | + * 使用时间 | |
| 105 | + */ | |
| 106 | + private LocalDateTime useTime; | |
| 107 | + | |
| 108 | + // ========== 使用情况 END ========== | |
| 109 | +} | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.api.coupon.dto; | |
| 2 | + | |
| 3 | +import lombok.Data; | |
| 4 | + | |
| 5 | +import javax.validation.constraints.NotNull; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * 优惠劵使用 Request DTO | |
| 9 | + * | |
| 10 | + * @author 芋道源码 | |
| 11 | + */ | |
| 12 | +@Data | |
| 13 | +public class CouponValidReqDTO { | |
| 14 | + | |
| 15 | + /** | |
| 16 | + * 优惠劵编号 | |
| 17 | + */ | |
| 18 | + @NotNull(message = "优惠劵编号不能为空") | |
| 19 | + private Long id; | |
| 20 | + | |
| 21 | + /** | |
| 22 | + * 用户编号 | |
| 23 | + */ | |
| 24 | + @NotNull(message = "用户编号不能为空") | |
| 25 | + private Long userId; | |
| 26 | + | |
| 27 | +} | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApi.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.api.discount; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; | |
| 4 | + | |
| 5 | +import java.util.Collection; | |
| 6 | +import java.util.List; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * 限时折扣 API 接口 | |
| 10 | + * | |
| 11 | + * @author 芋道源码 | |
| 12 | + */ | |
| 13 | +public interface DiscountActivityApi { | |
| 14 | + | |
| 15 | + /** | |
| 16 | + * 获得商品匹配的的限时折扣信息 | |
| 17 | + * | |
| 18 | + * @param skuIds 商品 SKU 编号数组 | |
| 19 | + * @return 限时折扣信息 | |
| 20 | + */ | |
| 21 | + List<DiscountProductRespDTO> getMatchDiscountProductList(Collection<Long> skuIds); | |
| 22 | + | |
| 23 | +} | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/bo/DiscountProductDetailBO.java renamed to yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java
| 1 | -package cn.iocoder.yudao.module.promotion.service.discount.bo; | |
| 1 | +package cn.iocoder.yudao.module.promotion.api.discount.dto; | |
| 2 | 2 | |
| 3 | 3 | import lombok.Data; |
| 4 | 4 | |
| 5 | 5 | /** |
| 6 | - * 限时折扣活动商品 BO | |
| 6 | + * 限时折扣活动商品 Response DTO | |
| 7 | 7 | * |
| 8 | 8 | * @author 芋道源码 |
| 9 | 9 | */ |
| 10 | 10 | @Data |
| 11 | -public class DiscountProductDetailBO { | |
| 12 | - | |
| 13 | - // ========== DiscountProductDO 字段 ========== | |
| 11 | +public class DiscountProductRespDTO { | |
| 14 | 12 | |
| 15 | 13 | /** |
| 16 | 14 | * 编号,主键自增 |
| 17 | 15 | */ |
| 18 | 16 | private Long id; |
| 19 | 17 | /** |
| 20 | - * 限时折扣活动的编号 | |
| 21 | - */ | |
| 22 | - private Long activityId; | |
| 23 | - /** | |
| 24 | 18 | * 商品 SPU 编号 |
| 25 | 19 | */ |
| 26 | 20 | private Long spuId; |
| ... | ... | @@ -41,7 +35,11 @@ public class DiscountProductDetailBO { |
| 41 | 35 | */ |
| 42 | 36 | private Integer discountPrice; |
| 43 | 37 | |
| 44 | - // ========== DiscountActivityDO 字段 ========== | |
| 38 | + // ========== 活动字段 ========== | |
| 39 | + /** | |
| 40 | + * 限时折扣活动的编号 | |
| 41 | + */ | |
| 42 | + private Long activityId; | |
| 45 | 43 | /** |
| 46 | 44 | * 活动标题 |
| 47 | 45 | */ | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/package-info.java deleted
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/price/dto/PriceCalculateReqDTO.java
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; |
| 24 | 24 | * @author 芋道源码 |
| 25 | 25 | */ |
| 26 | 26 | @Data |
| 27 | +@Deprecated | |
| 27 | 28 | public class PriceCalculateRespDTO { |
| 28 | 29 | |
| 29 | 30 | /** |
| ... | ... | @@ -38,6 +39,7 @@ public class PriceCalculateRespDTO { |
| 38 | 39 | */ |
| 39 | 40 | private List<Promotion> promotions; |
| 40 | 41 | |
| 42 | + // TODO @芋艿:需要改造下,主要是价格字段 | |
| 41 | 43 | /** |
| 42 | 44 | * 订单 |
| 43 | 45 | */ |
| ... | ... | @@ -51,14 +53,7 @@ public class PriceCalculateRespDTO { |
| 51 | 53 | * |
| 52 | 54 | * 对应 taobao 的 trade.total_fee 字段 |
| 53 | 55 | */ |
| 54 | - private Integer originalPrice; | |
| 55 | - /** | |
| 56 | - * 订单原价(总),单位:分 | |
| 57 | - * | |
| 58 | - * 基于 {@link OrderItem#getPayPrice()} 求和 | |
| 59 | - * 和 {@link #originalPrice} 的差异:去除商品级优惠 | |
| 60 | - */ | |
| 61 | - private Integer orderPrice; | |
| 56 | + private Integer totalPrice; | |
| 62 | 57 | /** |
| 63 | 58 | * 订单优惠(总),单位:分 |
| 64 | 59 | * |
| ... | ... | @@ -180,6 +175,7 @@ public class PriceCalculateRespDTO { |
| 180 | 175 | * 营销明细 |
| 181 | 176 | */ |
| 182 | 177 | @Data |
| 178 | + @Deprecated | |
| 183 | 179 | public static class Promotion { |
| 184 | 180 | |
| 185 | 181 | /** |
| ... | ... | @@ -207,7 +203,7 @@ public class PriceCalculateRespDTO { |
| 207 | 203 | /** |
| 208 | 204 | * 计算时的原价(总),单位:分 |
| 209 | 205 | */ |
| 210 | - private Integer originalPrice; | |
| 206 | + private Integer totalPrice; | |
| 211 | 207 | /** |
| 212 | 208 | * 计算时的优惠(总),单位:分 |
| 213 | 209 | */ |
| ... | ... | @@ -222,14 +218,14 @@ public class PriceCalculateRespDTO { |
| 222 | 218 | /** |
| 223 | 219 | * 是否满足优惠条件 |
| 224 | 220 | */ |
| 225 | - private Boolean meet; | |
| 221 | + private Boolean match; | |
| 226 | 222 | /** |
| 227 | 223 | * 满足条件的提示 |
| 228 | 224 | * |
| 229 | - * 如果 {@link #meet} = true 满足,则提示“圣诞价:省 150.00 元” | |
| 230 | - * 如果 {@link #meet} = false 不满足,则提示“购满 85 元,可减 40 元” | |
| 225 | + * 如果 {@link #match} = true 满足,则提示“圣诞价:省 150.00 元” | |
| 226 | + * 如果 {@link #match} = false 不满足,则提示“购满 85 元,可减 40 元” | |
| 231 | 227 | */ |
| 232 | - private String meetTip; | |
| 228 | + private String description; | |
| 233 | 229 | |
| 234 | 230 | } |
| 235 | 231 | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.api.reward; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; | |
| 4 | + | |
| 5 | +import java.util.Collection; | |
| 6 | +import java.util.List; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * 满减送活动 API 接口 | |
| 10 | + * | |
| 11 | + * @author 芋道源码 | |
| 12 | + */ | |
| 13 | +public interface RewardActivityApi { | |
| 14 | + | |
| 15 | + | |
| 16 | + /** | |
| 17 | + * 基于指定的 SPU 编号数组,获得它们匹配的满减送活动 | |
| 18 | + * | |
| 19 | + * @param spuIds SPU 编号数组 | |
| 20 | + * @return 满减送活动列表 | |
| 21 | + */ | |
| 22 | + List<RewardActivityMatchRespDTO> getMatchRewardActivityList(Collection<Long> spuIds); | |
| 23 | + | |
| 24 | +} | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/dto/RewardActivityMatchRespDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.api.reward.dto; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum; | |
| 4 | +import lombok.Data; | |
| 5 | + | |
| 6 | +import java.util.List; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * 满减送活动的匹配 Response DTO | |
| 10 | + * | |
| 11 | + * @author 芋道源码 | |
| 12 | + */ | |
| 13 | +@Data | |
| 14 | +public class RewardActivityMatchRespDTO { | |
| 15 | + | |
| 16 | + /** | |
| 17 | + * 活动编号,主键自增 | |
| 18 | + */ | |
| 19 | + private Long id; | |
| 20 | + /** | |
| 21 | + * 活动标题 | |
| 22 | + */ | |
| 23 | + private String name; | |
| 24 | + /** | |
| 25 | + * 条件类型 | |
| 26 | + * | |
| 27 | + * 枚举 {@link PromotionConditionTypeEnum} | |
| 28 | + */ | |
| 29 | + private Integer conditionType; | |
| 30 | + /** | |
| 31 | + * 优惠规则的数组 | |
| 32 | + */ | |
| 33 | + private List<Rule> rules; | |
| 34 | + | |
| 35 | + /** | |
| 36 | + * 商品 SPU 编号的数组 | |
| 37 | + */ | |
| 38 | + private List<Long> spuIds; | |
| 39 | + | |
| 40 | + // TODO 芋艿:后面 RewardActivityRespDTO 有了之后,Rule 可以放过去 | |
| 41 | + /** | |
| 42 | + * 优惠规则 | |
| 43 | + */ | |
| 44 | + @Data | |
| 45 | + public static class Rule { | |
| 46 | + | |
| 47 | + /** | |
| 48 | + * 优惠门槛 | |
| 49 | + * | |
| 50 | + * 1. 满 N 元,单位:分 | |
| 51 | + * 2. 满 N 件 | |
| 52 | + */ | |
| 53 | + private Integer limit; | |
| 54 | + /** | |
| 55 | + * 优惠价格,单位:分 | |
| 56 | + */ | |
| 57 | + private Integer discountPrice; | |
| 58 | + /** | |
| 59 | + * 是否包邮 | |
| 60 | + */ | |
| 61 | + private Boolean freeDelivery; | |
| 62 | + /** | |
| 63 | + * 赠送的积分 | |
| 64 | + */ | |
| 65 | + private Integer point; | |
| 66 | + /** | |
| 67 | + * 赠送的优惠劵编号的数组 | |
| 68 | + */ | |
| 69 | + private List<Long> couponIds; | |
| 70 | + /** | |
| 71 | + * 赠送的优惠卷数量的数组 | |
| 72 | + */ | |
| 73 | + private List<Integer> couponCounts; | |
| 74 | + | |
| 75 | + } | |
| 76 | + | |
| 77 | +} | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionLevelEnum.java deleted
| 1 | -package cn.iocoder.yudao.module.promotion.enums.common; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | |
| 4 | -import lombok.AllArgsConstructor; | |
| 5 | -import lombok.Getter; | |
| 6 | - | |
| 7 | -import java.util.Arrays; | |
| 8 | - | |
| 9 | -/** | |
| 10 | - * 营销的级别枚举 | |
| 11 | - * | |
| 12 | - * 参考有赞:<a href="https://img01.yzcdn.cn/upload_files/2021/11/02/FhDjUrNDq-G0wjNdYDtgUX09fdGj.png">营销级别</a> | |
| 13 | - * | |
| 14 | - * @author 芋道源码 | |
| 15 | - */ | |
| 16 | -@Getter | |
| 17 | -@AllArgsConstructor | |
| 18 | -public enum PromotionLevelEnum implements IntArrayValuable { | |
| 19 | - | |
| 20 | - ORDER(1, "订单级"), // 多个商品,进行组合后优惠。例如说:满减送、打包一口价、第二件半价 | |
| 21 | - SKU(2, "商品级"), // 单个商品,直接优惠。例如说:限时折扣、会员折扣 | |
| 22 | - COUPON(3, "优惠劵"), // 多个商品,进行组合后优惠。例如说:优惠劵 | |
| 23 | - ; | |
| 24 | - | |
| 25 | - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionLevelEnum::getLevel).toArray(); | |
| 26 | - | |
| 27 | - /** | |
| 28 | - * 级别值 | |
| 29 | - */ | |
| 30 | - private final Integer level; | |
| 31 | - /** | |
| 32 | - * 类型名 | |
| 33 | - */ | |
| 34 | - private final String name; | |
| 35 | - | |
| 36 | - @Override | |
| 37 | - public int[] array() { | |
| 38 | - return ARRAYS; | |
| 39 | - } | |
| 40 | -} |
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 { |
| 18 | 18 | DISCOUNT_ACTIVITY(1, "限时折扣"), |
| 19 | 19 | REWARD_ACTIVITY(2, "满减送"), |
| 20 | 20 | |
| 21 | - MEMBER(3, "会员折扣"), | |
| 21 | + MEMBER(3, "会员折扣"), // TODO 芋艿:待实现 StrUtil.format("会员折扣:省 {} 元", formatPrice(orderItem.getPayPrice() - memberPrice) | |
| 22 | 22 | COUPON(4, "优惠劵") |
| 23 | 23 | ; |
| 24 | 24 | |
| ... | ... | @@ -37,4 +37,5 @@ public enum PromotionTypeEnum implements IntArrayValuable { |
| 37 | 37 | public int[] array() { |
| 38 | 38 | return ARRAYS; |
| 39 | 39 | } |
| 40 | + | |
| 40 | 41 | } | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.promotion.api.coupon; |
| 2 | 2 | |
| 3 | 3 | |
| 4 | +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; | |
| 4 | 5 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; |
| 6 | +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; | |
| 7 | +import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; | |
| 8 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; | |
| 5 | 9 | import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; |
| 6 | 10 | import org.springframework.stereotype.Service; |
| 7 | 11 | |
| ... | ... | @@ -24,4 +28,10 @@ public class CouponApiImpl implements CouponApi { |
| 24 | 28 | useReqDTO.getOrderId()); |
| 25 | 29 | } |
| 26 | 30 | |
| 31 | + @Override | |
| 32 | + public CouponRespDTO validateCoupon(CouponValidReqDTO validReqDTO) { | |
| 33 | + CouponDO coupon = couponService.validCoupon(validReqDTO.getId(), validReqDTO.getUserId()); | |
| 34 | + return CouponConvert.INSTANCE.convert(coupon); | |
| 35 | + } | |
| 36 | + | |
| 27 | 37 | } | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.api.discount; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; | |
| 4 | +import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert; | |
| 5 | +import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService; | |
| 6 | +import org.springframework.stereotype.Service; | |
| 7 | + | |
| 8 | +import javax.annotation.Resource; | |
| 9 | +import java.util.Collection; | |
| 10 | +import java.util.List; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 限时折扣 API 实现类 | |
| 14 | + * | |
| 15 | + * @author 芋道源码 | |
| 16 | + */ | |
| 17 | +@Service | |
| 18 | +public class DiscountActivityApiImpl implements DiscountActivityApi { | |
| 19 | + | |
| 20 | + @Resource | |
| 21 | + private DiscountActivityService discountActivityService; | |
| 22 | + | |
| 23 | + @Override | |
| 24 | + public List<DiscountProductRespDTO> getMatchDiscountProductList(Collection<Long> skuIds) { | |
| 25 | + return DiscountActivityConvert.INSTANCE.convertList02(discountActivityService.getMatchDiscountProductList(skuIds)); | |
| 26 | + } | |
| 27 | + | |
| 28 | +} | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/package-info.java deleted
| 1 | -package cn.iocoder.yudao.module.promotion.api.discount; |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.api.reward; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; | |
| 4 | +import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService; | |
| 5 | +import org.springframework.stereotype.Service; | |
| 6 | + | |
| 7 | +import javax.annotation.Resource; | |
| 8 | +import java.util.Collection; | |
| 9 | +import java.util.List; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 满减送活动 API 实现类 | |
| 13 | + * | |
| 14 | + * @author 芋道源码 | |
| 15 | + */ | |
| 16 | +@Service | |
| 17 | +public class RewardActivityApiImpl implements RewardActivityApi { | |
| 18 | + | |
| 19 | + @Resource | |
| 20 | + private RewardActivityService rewardActivityService; | |
| 21 | + | |
| 22 | + @Override | |
| 23 | + public List<RewardActivityMatchRespDTO> getMatchRewardActivityList(Collection<Long> spuIds) { | |
| 24 | + return rewardActivityService.getMatchRewardActivityList(spuIds); | |
| 25 | + } | |
| 26 | + | |
| 27 | +} | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java
| 1 | 1 | package cn.iocoder.yudao.module.promotion.convert.coupon; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; | |
| 4 | 5 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageItemRespVO; |
| 5 | 6 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; |
| 6 | 7 | import org.mapstruct.Mapper; |
| ... | ... | @@ -18,4 +19,6 @@ public interface CouponConvert { |
| 18 | 19 | |
| 19 | 20 | PageResult<CouponPageItemRespVO> convertPage(PageResult<CouponDO> page); |
| 20 | 21 | |
| 22 | + CouponRespDTO convert(CouponDO bean); | |
| 23 | + | |
| 21 | 24 | } | ... | ... |
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; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.util.ObjectUtil; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 6 | -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | |
| 5 | +import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; | |
| 7 | 6 | import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.*; |
| 8 | 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; |
| 9 | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; |
| 10 | 9 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; |
| 11 | -import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO; | |
| 12 | 10 | import org.mapstruct.Mapper; |
| 13 | 11 | import org.mapstruct.factory.Mappers; |
| 14 | 12 | |
| 15 | 13 | import java.util.List; |
| 16 | -import java.util.Map; | |
| 17 | 14 | |
| 18 | 15 | /** |
| 19 | 16 | * 限时折扣活动 Convert |
| ... | ... | @@ -33,19 +30,9 @@ public interface DiscountActivityConvert { |
| 33 | 30 | |
| 34 | 31 | List<DiscountActivityRespVO> convertList(List<DiscountActivityDO> list); |
| 35 | 32 | |
| 36 | - PageResult<DiscountActivityRespVO> convertPage(PageResult<DiscountActivityDO> page); | |
| 37 | - | |
| 38 | - DiscountProductDetailBO convert(DiscountProductDO product); | |
| 33 | + List<DiscountProductRespDTO> convertList02(List<DiscountProductDO> list); | |
| 39 | 34 | |
| 40 | - default List<DiscountProductDetailBO> convertList(List<DiscountProductDO> products, Map<Long, DiscountActivityDO> activityMap) { | |
| 41 | - return CollectionUtils.convertList(products, product -> { | |
| 42 | - DiscountProductDetailBO detail = convert(product); | |
| 43 | - MapUtils.findAndThen(activityMap, product.getActivityId(), activity -> { | |
| 44 | - detail.setActivityName(activity.getName()); | |
| 45 | - }); | |
| 46 | - return detail; | |
| 47 | - }); | |
| 48 | - } | |
| 35 | + PageResult<DiscountActivityRespVO> convertPage(PageResult<DiscountActivityDO> page); | |
| 49 | 36 | |
| 50 | 37 | DiscountProductDO convert(DiscountActivityBaseVO.Product bean); |
| 51 | 38 | |
| ... | ... | @@ -99,4 +86,5 @@ public interface DiscountActivityConvert { |
| 99 | 86 | return true; |
| 100 | 87 | } |
| 101 | 88 | |
| 89 | + | |
| 102 | 90 | } | ... | ... |
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 { |
| 22 | 22 | // 创建 PriceCalculateRespDTO 对象 |
| 23 | 23 | PriceCalculateRespDTO priceCalculate = new PriceCalculateRespDTO(); |
| 24 | 24 | // 创建它的 Order 属性 |
| 25 | - PriceCalculateRespDTO.Order order = new PriceCalculateRespDTO.Order().setOriginalPrice(0).setDiscountPrice(0) | |
| 25 | + PriceCalculateRespDTO.Order order = new PriceCalculateRespDTO.Order().setTotalPrice(0).setDiscountPrice(0) | |
| 26 | 26 | .setCouponPrice(0).setPointPrice(0).setDeliveryPrice(0).setPayPrice(0) |
| 27 | 27 | .setItems(new ArrayList<>()).setCouponId(calculateReqDTO.getCouponId()); |
| 28 | 28 | priceCalculate.setOrder(order).setPromotions(new ArrayList<>()); |
| ... | ... | @@ -38,8 +38,8 @@ public interface PriceConvert { |
| 38 | 38 | orderItem.setPayPrice(orderItem.getOriginalPrice()).setOrderDividePrice(orderItem.getOriginalPrice()); |
| 39 | 39 | priceCalculate.getOrder().getItems().add(orderItem); |
| 40 | 40 | // 补充价格信息到 Order 中 |
| 41 | - order.setOriginalPrice(order.getOriginalPrice() + orderItem.getOriginalPrice()) | |
| 42 | - .setOrderPrice(order.getOriginalPrice()).setPayPrice(order.getOriginalPrice()); | |
| 41 | + order.setTotalPrice(order.getTotalPrice() + orderItem.getOriginalPrice()) | |
| 42 | + .setPayPrice(order.getTotalPrice()); | |
| 43 | 43 | }); |
| 44 | 44 | return priceCalculate; |
| 45 | 45 | } | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/discount/DiscountActivityDO.java
| 1 | 1 | package cn.iocoder.yudao.module.promotion.dal.dataobject.discount; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | |
| 3 | 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 4 | -import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; | |
| 5 | 5 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| 6 | 6 | import com.baomidou.mybatisplus.annotation.TableId; |
| 7 | 7 | import com.baomidou.mybatisplus.annotation.TableName; |
| ... | ... | @@ -33,10 +33,13 @@ public class DiscountActivityDO extends BaseDO { |
| 33 | 33 | * 活动标题 |
| 34 | 34 | */ |
| 35 | 35 | private String name; |
| 36 | + // TODO 芋艿:状态调整,只有开启和关闭; | |
| 36 | 37 | /** |
| 37 | 38 | * 状态 |
| 38 | 39 | * |
| 39 | - * 枚举 {@link PromotionActivityStatusEnum} | |
| 40 | + * 枚举 {@link CommonStatusEnum} | |
| 41 | + * | |
| 42 | + * 活动被关闭后,不允许再次开启。 | |
| 40 | 43 | */ |
| 41 | 44 | private Integer status; |
| 42 | 45 | /** | ... | ... |
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 { |
| 24 | 24 | */ |
| 25 | 25 | @TableId |
| 26 | 26 | private Long id; |
| 27 | + | |
| 28 | + // TODO 芋艿:把 activity 所有的字段冗余过来 | |
| 27 | 29 | /** |
| 28 | 30 | * 限时折扣活动的编号 |
| 29 | 31 | * |
| 30 | 32 | * 关联 {@link DiscountActivityDO#getId()} |
| 31 | 33 | */ |
| 32 | 34 | private Long activityId; |
| 35 | + | |
| 33 | 36 | /** |
| 34 | 37 | * 商品 SPU 编号 |
| 35 | 38 | * | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/reward/RewardActivityDO.java
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 |
| 6 | 6 | import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO; |
| 7 | 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; |
| 8 | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; |
| 9 | -import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO; | |
| 10 | 9 | |
| 11 | 10 | import javax.validation.Valid; |
| 12 | 11 | import java.util.Collection; |
| 13 | 12 | import java.util.List; |
| 14 | -import java.util.Map; | |
| 15 | 13 | |
| 16 | 14 | /** |
| 17 | 15 | * 限时折扣 Service 接口 |
| ... | ... | @@ -28,7 +26,7 @@ public interface DiscountActivityService { |
| 28 | 26 | * @param skuIds SKU 编号数组 |
| 29 | 27 | * @return 匹配的限时折扣商品 |
| 30 | 28 | */ |
| 31 | - Map<Long, DiscountProductDetailBO> getMatchDiscountProducts(Collection<Long> skuIds); | |
| 29 | + List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> skuIds); | |
| 32 | 30 | |
| 33 | 31 | /** |
| 34 | 32 | * 创建限时折扣活动 | ... | ... |
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; |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.collection.CollectionUtil; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 7 | 6 | import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityBaseVO; |
| 8 | 7 | import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO; |
| 9 | 8 | 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 |
| 14 | 13 | import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountActivityMapper; |
| 15 | 14 | import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper; |
| 16 | 15 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; |
| 17 | -import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO; | |
| 18 | 16 | import cn.iocoder.yudao.module.promotion.util.PromotionUtils; |
| 19 | 17 | import org.springframework.stereotype.Service; |
| 20 | 18 | import org.springframework.validation.annotation.Validated; |
| 21 | 19 | |
| 22 | 20 | import javax.annotation.Resource; |
| 23 | -import java.util.*; | |
| 21 | +import java.util.Collection; | |
| 22 | +import java.util.List; | |
| 24 | 23 | |
| 25 | 24 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 26 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | |
| 25 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | |
| 27 | 26 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; |
| 28 | -import static java.util.Arrays.asList; | |
| 29 | 27 | |
| 30 | 28 | /** |
| 31 | 29 | * 限时折扣 Service 实现类 |
| ... | ... | @@ -42,9 +40,9 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { |
| 42 | 40 | private DiscountProductMapper discountProductMapper; |
| 43 | 41 | |
| 44 | 42 | @Override |
| 45 | - public Map<Long, DiscountProductDetailBO> getMatchDiscountProducts(Collection<Long> skuIds) { | |
| 46 | - List<DiscountProductDetailBO> discountProducts = getRewardProductListBySkuIds(skuIds, singleton(PromotionActivityStatusEnum.RUN.getStatus())); | |
| 47 | - return convertMap(discountProducts, DiscountProductDetailBO::getSkuId); | |
| 43 | + public List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> skuIds) { | |
| 44 | + // TODO 芋艿:开启、满足 skuId、日期内 | |
| 45 | + return null; | |
| 48 | 46 | } |
| 49 | 47 | |
| 50 | 48 | @Override |
| ... | ... | @@ -101,6 +99,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { |
| 101 | 99 | } |
| 102 | 100 | } |
| 103 | 101 | |
| 102 | + // TODO 芋艿:校验逻辑简化,只查询时间冲突的活动,开启状态的。 | |
| 104 | 103 | /** |
| 105 | 104 | * 校验商品是否冲突 |
| 106 | 105 | * |
| ... | ... | @@ -112,9 +111,10 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { |
| 112 | 111 | return; |
| 113 | 112 | } |
| 114 | 113 | // 查询商品参加的活动 |
| 115 | - List<DiscountProductDetailBO> discountActivityProductList = getRewardProductListBySkuIds( | |
| 116 | - convertSet(products, DiscountActivityBaseVO.Product::getSkuId), | |
| 117 | - asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus())); | |
| 114 | + List<DiscountProductDO> discountActivityProductList = null; | |
| 115 | +// getRewardProductListBySkuIds( | |
| 116 | +// convertSet(products, DiscountActivityBaseVO.Product::getSkuId), | |
| 117 | +// asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus())); | |
| 118 | 118 | if (id != null) { // 排除自己这个活动 |
| 119 | 119 | discountActivityProductList.removeIf(product -> id.equals(product.getActivityId())); |
| 120 | 120 | } |
| ... | ... | @@ -124,24 +124,6 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { |
| 124 | 124 | } |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | - private List<DiscountProductDetailBO> getRewardProductListBySkuIds(Collection<Long> skuIds, | |
| 128 | - Collection<Integer> statuses) { | |
| 129 | - // 查询商品 | |
| 130 | - List<DiscountProductDO> products = discountProductMapper.selectListBySkuId(skuIds); | |
| 131 | - if (CollUtil.isEmpty(products)) { | |
| 132 | - return new ArrayList<>(0); | |
| 133 | - } | |
| 134 | - | |
| 135 | - // 查询活动 | |
| 136 | - List<DiscountActivityDO> activities = discountActivityMapper.selectBatchIds(skuIds); | |
| 137 | - activities.removeIf(activity -> !statuses.contains(activity.getStatus())); // 移除不满足 statuses 状态的 | |
| 138 | - Map<Long, DiscountActivityDO> activityMap = CollectionUtils.convertMap(activities, DiscountActivityDO::getId); | |
| 139 | - | |
| 140 | - // 移除不满足活动的商品 | |
| 141 | - products.removeIf(product -> !activityMap.containsKey(product.getActivityId())); | |
| 142 | - return DiscountActivityConvert.INSTANCE.convertList(products, activityMap); | |
| 143 | - } | |
| 144 | - | |
| 145 | 127 | @Override |
| 146 | 128 | public void closeRewardActivity(Long id) { |
| 147 | 129 | // 校验存在 |
| ... | ... | @@ -153,7 +135,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { |
| 153 | 135 | throw exception(DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_END); |
| 154 | 136 | } |
| 155 | 137 | |
| 156 | - // 更新 | |
| 138 | + // 更新为关闭。 | |
| 157 | 139 | DiscountActivityDO updateObj = new DiscountActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus()); |
| 158 | 140 | discountActivityMapper.updateById(updateObj); |
| 159 | 141 | } | ... | ... |
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; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO; |
| 4 | 4 | import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO; |
| 5 | -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; | |
| 6 | 5 | |
| 7 | 6 | import java.util.List; |
| 8 | 7 | |
| ... | ... | @@ -14,14 +13,6 @@ import java.util.List; |
| 14 | 13 | public interface PriceService { |
| 15 | 14 | |
| 16 | 15 | /** |
| 17 | - * 计算商品的价格 | |
| 18 | - * | |
| 19 | - * @param calculateReqDTO 价格请求 | |
| 20 | - * @return 价格响应 | |
| 21 | - */ | |
| 22 | - PriceCalculateRespDTO calculatePrice(PriceCalculateReqDTO calculateReqDTO); | |
| 23 | - | |
| 24 | - /** | |
| 25 | 16 | * 获得优惠劵的匹配信息列表 |
| 26 | 17 | * |
| 27 | 18 | * @param calculateReqDTO 价格请求 | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/price/PriceServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.promotion.service.price; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | -import cn.hutool.core.lang.Assert; | |
| 5 | -import cn.hutool.core.util.StrUtil; | |
| 6 | 4 | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| 7 | 5 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 8 | -import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | |
| 9 | -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | |
| 10 | 6 | import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO; |
| 11 | 7 | import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO; |
| 12 | 8 | import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; |
| 13 | 9 | import cn.iocoder.yudao.module.promotion.convert.price.PriceConvert; |
| 14 | 10 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; |
| 15 | -import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; | |
| 16 | -import cn.iocoder.yudao.module.promotion.enums.common.*; | |
| 17 | 11 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; |
| 18 | 12 | import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; |
| 19 | -import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService; | |
| 20 | -import cn.iocoder.yudao.module.promotion.service.discount.bo.DiscountProductDetailBO; | |
| 21 | -import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService; | |
| 22 | -import com.google.common.base.Suppliers; | |
| 23 | 13 | import lombok.extern.slf4j.Slf4j; |
| 24 | 14 | import org.springframework.stereotype.Service; |
| 25 | 15 | import org.springframework.validation.annotation.Validated; |
| 26 | 16 | |
| 27 | 17 | import javax.annotation.Resource; |
| 28 | -import java.util.*; | |
| 29 | -import java.util.function.Supplier; | |
| 18 | +import java.util.Collections; | |
| 19 | +import java.util.List; | |
| 30 | 20 | |
| 31 | -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 32 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | |
| 33 | 21 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; |
| 34 | -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; | |
| 35 | -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; | |
| 36 | -import static java.util.Collections.singletonList; | |
| 22 | +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_VALID_TIME_NOT_NOW; | |
| 37 | 23 | |
| 38 | 24 | /** |
| 39 | 25 | * 价格计算 Service 实现类 |
| ... | ... | @@ -55,42 +41,13 @@ import static java.util.Collections.singletonList; |
| 55 | 41 | public class PriceServiceImpl implements PriceService { |
| 56 | 42 | |
| 57 | 43 | @Resource |
| 58 | - private DiscountActivityService discountService; | |
| 59 | - @Resource | |
| 60 | - private RewardActivityService rewardActivityService; | |
| 61 | - @Resource | |
| 62 | 44 | private CouponService couponService; |
| 63 | 45 | |
| 64 | - @Resource | |
| 65 | - private ProductSkuApi productSkuApi; | |
| 66 | - | |
| 67 | - @Override | |
| 68 | - public PriceCalculateRespDTO calculatePrice(PriceCalculateReqDTO calculateReqDTO) { | |
| 69 | - // 获得商品 SKU 数组 | |
| 70 | - List<ProductSkuRespDTO> skuList = checkSkus(calculateReqDTO); | |
| 71 | - // 初始化 PriceCalculateRespDTO 对象 | |
| 72 | - PriceCalculateRespDTO priceCalculate = PriceConvert.INSTANCE.convert(calculateReqDTO, skuList); | |
| 73 | - | |
| 74 | - // 计算商品级别的价格 | |
| 75 | - calculatePriceForSkuLevel(calculateReqDTO.getUserId(), priceCalculate); | |
| 76 | - // 计算订单级别的价格 | |
| 77 | - calculatePriceForOrderLevel(calculateReqDTO.getUserId(), priceCalculate); | |
| 78 | - // 计算优惠劵级别的价格 | |
| 79 | - calculatePriceForCouponLevel(calculateReqDTO.getUserId(), calculateReqDTO.getCouponId(), priceCalculate); | |
| 80 | - | |
| 81 | - // 如果最终支付金额小于等于 0,则抛出业务异常 | |
| 82 | - if (priceCalculate.getOrder().getPayPrice() <= 0) { | |
| 83 | - log.error("[calculatePrice][价格计算不正确,请求 calculateReqDTO({}),结果 priceCalculate({})]", | |
| 84 | - calculateReqDTO, priceCalculate); | |
| 85 | - throw exception(PRICE_CALCULATE_PAY_PRICE_ILLEGAL); | |
| 86 | - } | |
| 87 | - return priceCalculate; | |
| 88 | - } | |
| 89 | - | |
| 90 | 46 | @Override |
| 91 | 47 | public List<CouponMeetRespDTO> getMeetCouponList(PriceCalculateReqDTO calculateReqDTO) { |
| 92 | 48 | // 先计算一轮价格 |
| 93 | - PriceCalculateRespDTO priceCalculate = calculatePrice(calculateReqDTO); | |
| 49 | +// PriceCalculateRespDTO priceCalculate = calculatePrice(calculateReqDTO); | |
| 50 | + PriceCalculateRespDTO priceCalculate = null; | |
| 94 | 51 | |
| 95 | 52 | // 获得用户的待使用优惠劵 |
| 96 | 53 | List<CouponDO> couponList = couponService.getCouponList(calculateReqDTO.getUserId(), CouponStatusEnum.UNUSED.getStatus()); |
| ... | ... | @@ -106,7 +63,9 @@ public class PriceServiceImpl implements PriceService { |
| 106 | 63 | couponService.validCoupon(coupon); |
| 107 | 64 | |
| 108 | 65 | // 获得匹配的商品 SKU 数组 |
| 109 | - List<PriceCalculateRespDTO.OrderItem> orderItems = getMatchCouponOrderItems(priceCalculate, coupon); | |
| 66 | + // TODO 芋艿:后续处理 | |
| 67 | +// List<PriceCalculateRespDTO.OrderItem> orderItems = getMatchCouponOrderItems(priceCalculate, coupon); | |
| 68 | + List<PriceCalculateRespDTO.OrderItem> orderItems = null; | |
| 110 | 69 | if (CollUtil.isEmpty(orderItems)) { |
| 111 | 70 | return couponMeetRespDTO.setMeet(false).setMeetTip("所结算商品没有符合条件的商品"); |
| 112 | 71 | } |
| ... | ... | @@ -134,414 +93,4 @@ public class PriceServiceImpl implements PriceService { |
| 134 | 93 | }); |
| 135 | 94 | } |
| 136 | 95 | |
| 137 | - private List<ProductSkuRespDTO> checkSkus(PriceCalculateReqDTO calculateReqDTO) { | |
| 138 | - // 获得商品 SKU 数组 | |
| 139 | - Map<Long, Integer> skuIdCountMap = CollectionUtils.convertMap(calculateReqDTO.getItems(), | |
| 140 | - PriceCalculateReqDTO.Item::getSkuId, PriceCalculateReqDTO.Item::getCount); | |
| 141 | - List<ProductSkuRespDTO> skus = productSkuApi.getSkuList(skuIdCountMap.keySet()); | |
| 142 | - | |
| 143 | - // 校验商品 SKU | |
| 144 | - skus.forEach(sku -> { | |
| 145 | - Integer count = skuIdCountMap.get(sku.getId()); | |
| 146 | - if (count == null) { | |
| 147 | - throw exception(SKU_NOT_EXISTS); | |
| 148 | - } | |
| 149 | - // 不校验库存不足,避免购物车场景,商品无货的情况 | |
| 150 | - }); | |
| 151 | - return skus; | |
| 152 | - } | |
| 153 | - | |
| 154 | - // ========== 计算商品级别的价格 ========== | |
| 155 | - | |
| 156 | - /** | |
| 157 | - * 计算商品级别的价格,例如说: | |
| 158 | - * 1. 会员折扣 | |
| 159 | - * 2. 限时折扣 {@link cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO} | |
| 160 | - * | |
| 161 | - * 其中,会员折扣、限时折扣取最低价 | |
| 162 | - * | |
| 163 | - * @param userId 用户编号 | |
| 164 | - * @param priceCalculate 价格计算的结果 | |
| 165 | - */ | |
| 166 | - private void calculatePriceForSkuLevel(Long userId, PriceCalculateRespDTO priceCalculate) { | |
| 167 | - // 获取 SKU 级别的所有优惠信息 | |
| 168 | - Supplier<Double> memberDiscountPercentSupplier = getMemberDiscountPercentSupplier(userId); | |
| 169 | - Map<Long, DiscountProductDetailBO> discountProducts = discountService.getMatchDiscountProducts( | |
| 170 | - convertSet(priceCalculate.getOrder().getItems(), PriceCalculateRespDTO.OrderItem::getSkuId)); | |
| 171 | - | |
| 172 | - // 处理每个 SKU 的优惠 | |
| 173 | - priceCalculate.getOrder().getItems().forEach(orderItem -> { | |
| 174 | - // 获取该 SKU 的优惠信息 | |
| 175 | - Double memberDiscountPercent = memberDiscountPercentSupplier.get(); | |
| 176 | - DiscountProductDetailBO discountProduct = discountProducts.get(orderItem.getSkuId()); | |
| 177 | - if (memberDiscountPercent == null && discountProduct == null) { | |
| 178 | - return; | |
| 179 | - } | |
| 180 | - // 计算价格,判断选择哪个折扣 | |
| 181 | - Integer memberPrice = memberDiscountPercent != null ? (int) (orderItem.getPayPrice() * memberDiscountPercent / 100) : null; | |
| 182 | - Integer promotionPrice = discountProduct != null ? getDiscountProductPrice(discountProduct, orderItem) : null; | |
| 183 | - if (memberPrice == null) { | |
| 184 | - calculatePriceByDiscountActivity(priceCalculate, orderItem, discountProduct, promotionPrice); | |
| 185 | - } else if (promotionPrice == null) { | |
| 186 | - calculatePriceByMemberDiscount(priceCalculate, orderItem, memberPrice); | |
| 187 | - } else if (memberPrice < promotionPrice) { | |
| 188 | - calculatePriceByDiscountActivity(priceCalculate, orderItem, discountProduct, promotionPrice); | |
| 189 | - } else { | |
| 190 | - calculatePriceByMemberDiscount(priceCalculate, orderItem, memberPrice); | |
| 191 | - } | |
| 192 | - }); | |
| 193 | - } | |
| 194 | - | |
| 195 | - private Integer getDiscountProductPrice(DiscountProductDetailBO discountProduct, | |
| 196 | - PriceCalculateRespDTO.OrderItem orderItem) { | |
| 197 | - Integer price = orderItem.getPayPrice(); | |
| 198 | - if (PromotionDiscountTypeEnum.PRICE.getType().equals(discountProduct.getDiscountType())) { // 减价 | |
| 199 | - price -= discountProduct.getDiscountPrice() * orderItem.getCount(); | |
| 200 | - } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(discountProduct.getDiscountType())) { // 打折 | |
| 201 | - price = price * discountProduct.getDiscountPercent() / 100; | |
| 202 | - } else { | |
| 203 | - throw new IllegalArgumentException(String.format("优惠活动的商品(%s) 的优惠类型不正确", discountProduct)); | |
| 204 | - } | |
| 205 | - return price; | |
| 206 | - } | |
| 207 | - | |
| 208 | - private void calculatePriceByMemberDiscount(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem, | |
| 209 | - Integer memberPrice) { | |
| 210 | - // 记录优惠明细 | |
| 211 | - addPromotion(priceCalculate, orderItem, null, PromotionTypeEnum.MEMBER.getName(), | |
| 212 | - PromotionTypeEnum.MEMBER.getType(), PromotionLevelEnum.SKU.getLevel(), memberPrice, | |
| 213 | - true, StrUtil.format("会员折扣:省 {} 元", formatPrice(orderItem.getPayPrice() - memberPrice))); | |
| 214 | - // 修改 SKU 的优惠 | |
| 215 | - modifyOrderItemPayPrice(orderItem, memberPrice, priceCalculate); | |
| 216 | - } | |
| 217 | - | |
| 218 | - private void calculatePriceByDiscountActivity(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem, | |
| 219 | - DiscountProductDetailBO discountProduct, Integer promotionPrice) { | |
| 220 | - // 记录优惠明细 | |
| 221 | - addPromotion(priceCalculate, orderItem, discountProduct.getActivityId(), discountProduct.getActivityName(), | |
| 222 | - PromotionTypeEnum.DISCOUNT_ACTIVITY.getType(), PromotionLevelEnum.SKU.getLevel(), promotionPrice, | |
| 223 | - true, StrUtil.format("限时折扣:省 {} 元", formatPrice(orderItem.getPayPrice() - promotionPrice))); | |
| 224 | - // 修改 SKU 的优惠 | |
| 225 | - modifyOrderItemPayPrice(orderItem, promotionPrice, priceCalculate); | |
| 226 | - } | |
| 227 | - | |
| 228 | - // TODO 芋艿:提前实现 | |
| 229 | - private Supplier<Double> getMemberDiscountPercentSupplier(Long userId) { | |
| 230 | - return Suppliers.memoize(() -> { | |
| 231 | - if (userId == 1) { | |
| 232 | - return 90d; | |
| 233 | - } | |
| 234 | - if (userId == 2) { | |
| 235 | - return 80d; | |
| 236 | - } | |
| 237 | - return null; // 无优惠 | |
| 238 | - }); | |
| 239 | - } | |
| 240 | - | |
| 241 | - // ========== 计算商品级别的价格 ========== | |
| 242 | - | |
| 243 | - /** | |
| 244 | - * 计算订单级别的价格,例如说: | |
| 245 | - * 1. 满减送 {@link cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO} | |
| 246 | - * | |
| 247 | - * @param userId 用户编号 | |
| 248 | - * @param priceCalculate 价格计算的结果 | |
| 249 | - */ | |
| 250 | - @SuppressWarnings("unused") | |
| 251 | - private void calculatePriceForOrderLevel(Long userId, PriceCalculateRespDTO priceCalculate) { | |
| 252 | - // 获取 SKU 级别的所有优惠信息 | |
| 253 | - Set<Long> spuIds = convertSet(priceCalculate.getOrder().getItems(), PriceCalculateRespDTO.OrderItem::getSpuId); | |
| 254 | - Map<RewardActivityDO, Set<Long>> rewardActivities = rewardActivityService.getMatchRewardActivities(spuIds); | |
| 255 | - | |
| 256 | - // 处理满减送活动 | |
| 257 | - if (CollUtil.isNotEmpty(rewardActivities)) { | |
| 258 | - rewardActivities.forEach((rewardActivity, activitySpuIds) -> { | |
| 259 | - List<PriceCalculateRespDTO.OrderItem> orderItems = CollectionUtils.filterList(priceCalculate.getOrder().getItems(), | |
| 260 | - orderItem -> CollUtil.contains(activitySpuIds, orderItem.getSpuId())); | |
| 261 | - calculatePriceByRewardActivity(priceCalculate, orderItems, rewardActivity); | |
| 262 | - }); | |
| 263 | - } | |
| 264 | - } | |
| 265 | - | |
| 266 | - private void calculatePriceByRewardActivity(PriceCalculateRespDTO priceCalculate, List<PriceCalculateRespDTO.OrderItem> orderItems, | |
| 267 | - RewardActivityDO rewardActivity) { | |
| 268 | - // 获得最大匹配的满减送活动的规则 | |
| 269 | - RewardActivityDO.Rule rule = getLastMatchRewardActivityRule(rewardActivity, orderItems); | |
| 270 | - if (rule == null) { | |
| 271 | - // 获取不到的情况下,记录不满足的优惠明细 | |
| 272 | - addNotMeetPromotion(priceCalculate, orderItems, rewardActivity.getId(), rewardActivity.getName(), | |
| 273 | - PromotionTypeEnum.REWARD_ACTIVITY.getType(), PromotionLevelEnum.ORDER.getLevel(), | |
| 274 | - getRewardActivityNotMeetTip(rewardActivity)); | |
| 275 | - return; | |
| 276 | - } | |
| 277 | - | |
| 278 | - // 分摊金额 | |
| 279 | - List<Integer> discountPartPrices = dividePrice(orderItems, rule.getDiscountPrice()); | |
| 280 | - // 记录优惠明细 | |
| 281 | - addPromotion(priceCalculate, orderItems, rewardActivity.getId(), rewardActivity.getName(), | |
| 282 | - PromotionTypeEnum.REWARD_ACTIVITY.getType(), PromotionLevelEnum.ORDER.getLevel(), discountPartPrices, | |
| 283 | - true, StrUtil.format("满减送:省 {} 元", formatPrice(rule.getDiscountPrice()))); | |
| 284 | - // 修改 SKU 的分摊 | |
| 285 | - for (int i = 0; i < orderItems.size(); i++) { | |
| 286 | - modifyOrderItemOrderPartPriceFromDiscountPrice(orderItems.get(i), discountPartPrices.get(i), priceCalculate); | |
| 287 | - } | |
| 288 | - } | |
| 289 | - | |
| 290 | - /** | |
| 291 | - * 获得最大匹配的满减送活动的规则 | |
| 292 | - * | |
| 293 | - * @param rewardActivity 满减送活动 | |
| 294 | - * @param orderItems 商品项 | |
| 295 | - * @return 匹配的活动规则 | |
| 296 | - */ | |
| 297 | - private RewardActivityDO.Rule getLastMatchRewardActivityRule(RewardActivityDO rewardActivity, | |
| 298 | - List<PriceCalculateRespDTO.OrderItem> orderItems) { | |
| 299 | - Integer count = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getCount, Integer::sum); | |
| 300 | - // price 的计算逻辑,使用 orderDividePrice 的原因,主要考虑分摊后,这个才是该 SKU 当前真实的支付总价 | |
| 301 | - Integer price = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum); | |
| 302 | - assert count != null && price != null; | |
| 303 | - for (int i = rewardActivity.getRules().size() - 1; i >= 0; i--) { | |
| 304 | - RewardActivityDO.Rule rule = rewardActivity.getRules().get(i); | |
| 305 | - if (PromotionConditionTypeEnum.PRICE.getType().equals(rewardActivity.getConditionType()) | |
| 306 | - && price >= rule.getLimit()) { | |
| 307 | - return rule; | |
| 308 | - } | |
| 309 | - if (PromotionConditionTypeEnum.COUNT.getType().equals(rewardActivity.getConditionType()) | |
| 310 | - && count >= rule.getLimit()) { | |
| 311 | - return rule; | |
| 312 | - } | |
| 313 | - } | |
| 314 | - return null; | |
| 315 | - } | |
| 316 | - | |
| 317 | - /** | |
| 318 | - * 获得满减送活动部匹配时的提示 | |
| 319 | - * | |
| 320 | - * @param rewardActivity 满减送活动 | |
| 321 | - * @return 提示 | |
| 322 | - */ | |
| 323 | - private String getRewardActivityNotMeetTip(RewardActivityDO rewardActivity) { | |
| 324 | - return "TODO"; // TODO 芋艿:后面再想想 | |
| 325 | - } | |
| 326 | - | |
| 327 | - // ========== 计算优惠劵级别的价格 ========== | |
| 328 | - | |
| 329 | - private void calculatePriceForCouponLevel(Long userId, Long couponId, PriceCalculateRespDTO priceCalculate) { | |
| 330 | - // 校验优惠劵 | |
| 331 | - if (couponId == null) { | |
| 332 | - return; | |
| 333 | - } | |
| 334 | - CouponDO coupon = couponService.validCoupon(couponId, userId); | |
| 335 | - | |
| 336 | - // 获得匹配的商品 SKU 数组 | |
| 337 | - List<PriceCalculateRespDTO.OrderItem> orderItems = getMatchCouponOrderItems(priceCalculate, coupon); | |
| 338 | - if (CollUtil.isEmpty(orderItems)) { | |
| 339 | - throw exception(COUPON_NO_MATCH_SPU); | |
| 340 | - } | |
| 341 | - | |
| 342 | - // 计算是否满足优惠劵的使用金额 | |
| 343 | - Integer originPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum); | |
| 344 | - assert originPrice != null; | |
| 345 | - if (originPrice < coupon.getUsePrice()) { | |
| 346 | - throw exception(COUPON_NO_MATCH_MIN_PRICE); | |
| 347 | - } | |
| 348 | - | |
| 349 | - // 计算可以优惠的金额 | |
| 350 | - priceCalculate.getOrder().setCouponId(couponId); | |
| 351 | - Integer couponPrice = getCouponPrice(coupon, originPrice); | |
| 352 | - // 分摊金额 | |
| 353 | - List<Integer> couponPartPrices = dividePrice(orderItems, couponPrice); | |
| 354 | - // 记录优惠明细 | |
| 355 | - addPromotion(priceCalculate, orderItems, coupon.getId(), coupon.getName(), | |
| 356 | - PromotionTypeEnum.COUPON.getType(), PromotionLevelEnum.COUPON.getLevel(), couponPartPrices, | |
| 357 | - true, StrUtil.format("优惠劵:省 {} 元", formatPrice(couponPrice))); | |
| 358 | - // 修改 SKU 的分摊 | |
| 359 | - for (int i = 0; i < orderItems.size(); i++) { | |
| 360 | - modifyOrderItemOrderPartPriceFromCouponPrice(orderItems.get(i), couponPartPrices.get(i), priceCalculate); | |
| 361 | - } | |
| 362 | - } | |
| 363 | - | |
| 364 | - private List<PriceCalculateRespDTO.OrderItem> getMatchCouponOrderItems(PriceCalculateRespDTO priceCalculate, | |
| 365 | - CouponDO coupon) { | |
| 366 | - if (PromotionProductScopeEnum.ALL.getScope().equals(coupon.getProductScope())) { | |
| 367 | - return priceCalculate.getOrder().getItems(); | |
| 368 | - } | |
| 369 | - return CollectionUtils.filterList(priceCalculate.getOrder().getItems(), | |
| 370 | - orderItem -> coupon.getProductSpuIds().contains(orderItem.getSpuId())); | |
| 371 | - } | |
| 372 | - | |
| 373 | - private Integer getCouponPrice(CouponDO coupon, Integer originPrice) { | |
| 374 | - if (PromotionDiscountTypeEnum.PRICE.getType().equals(coupon.getDiscountType())) { // 减价 | |
| 375 | - return coupon.getDiscountPrice(); | |
| 376 | - } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(coupon.getDiscountType())) { // 打折 | |
| 377 | - int couponPrice = originPrice * coupon.getDiscountPercent() / 100; | |
| 378 | - return coupon.getDiscountLimitPrice() == null ? couponPrice | |
| 379 | - : Math.min(couponPrice, coupon.getDiscountLimitPrice()); // 优惠上限 | |
| 380 | - } | |
| 381 | - throw new IllegalArgumentException(String.format("优惠劵(%s) 的优惠类型不正确", coupon)); | |
| 382 | - } | |
| 383 | - | |
| 384 | - // ========== 其它相对通用的方法 ========== | |
| 385 | - | |
| 386 | - /** | |
| 387 | - * 添加单个 OrderItem 的营销明细 | |
| 388 | - * | |
| 389 | - * @param priceCalculate 价格计算结果 | |
| 390 | - * @param orderItem 单个订单商品 SKU | |
| 391 | - * @param id 营销编号 | |
| 392 | - * @param name 营销名字 | |
| 393 | - * @param type 营销类型 | |
| 394 | - * @param level 营销级别 | |
| 395 | - * @param newPayPrice 新的单实付金额(总) | |
| 396 | - * @param meet 是否满足优惠条件 | |
| 397 | - * @param meetTip 满足条件的提示 | |
| 398 | - */ | |
| 399 | - private void addPromotion(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem, | |
| 400 | - Long id, String name, Integer type, Integer level, | |
| 401 | - Integer newPayPrice, Boolean meet, String meetTip) { | |
| 402 | - // 创建营销明细 Item | |
| 403 | - // TODO 芋艿:orderItem.getPayPrice() 要不要改成 orderDividePrice;同时,newPayPrice 要不要改成直接传递 discountPrice | |
| 404 | - PriceCalculateRespDTO.PromotionItem promotionItem = new PriceCalculateRespDTO.PromotionItem().setSkuId(orderItem.getSkuId()) | |
| 405 | - .setOriginalPrice(orderItem.getPayPrice()).setDiscountPrice(orderItem.getPayPrice() - newPayPrice); | |
| 406 | - // 创建营销明细 | |
| 407 | - PriceCalculateRespDTO.Promotion promotion = new PriceCalculateRespDTO.Promotion() | |
| 408 | - .setId(id).setName(name).setType(type).setLevel(level) | |
| 409 | - .setOriginalPrice(promotionItem.getOriginalPrice()).setDiscountPrice(promotionItem.getDiscountPrice()) | |
| 410 | - .setItems(singletonList(promotionItem)).setMeet(meet).setMeetTip(meetTip); | |
| 411 | - priceCalculate.getPromotions().add(promotion); | |
| 412 | - } | |
| 413 | - | |
| 414 | - /** | |
| 415 | - * 添加多个 OrderItem 的营销明细 | |
| 416 | - * | |
| 417 | - * @param priceCalculate 价格计算结果 | |
| 418 | - * @param orderItems 多个订单商品 SKU | |
| 419 | - * @param id 营销编号 | |
| 420 | - * @param name 营销名字 | |
| 421 | - * @param type 营销类型 | |
| 422 | - * @param level 营销级别 | |
| 423 | - * @param discountPrices 多个订单商品 SKU 的优惠价格(总),和 orderItems 一一对应 | |
| 424 | - * @param meet 是否满足优惠条件 | |
| 425 | - * @param meetTip 满足条件的提示 | |
| 426 | - */ | |
| 427 | - private void addPromotion(PriceCalculateRespDTO priceCalculate, List<PriceCalculateRespDTO.OrderItem> orderItems, | |
| 428 | - Long id, String name, Integer type, Integer level, | |
| 429 | - List<Integer> discountPrices, Boolean meet, String meetTip) { | |
| 430 | - // 创建营销明细 Item | |
| 431 | - List<PriceCalculateRespDTO.PromotionItem> promotionItems = new ArrayList<>(discountPrices.size()); | |
| 432 | - for (int i = 0; i < orderItems.size(); i++) { | |
| 433 | - PriceCalculateRespDTO.OrderItem orderItem = orderItems.get(i); | |
| 434 | - promotionItems.add(new PriceCalculateRespDTO.PromotionItem().setSkuId(orderItem.getSkuId()) | |
| 435 | - .setOriginalPrice(orderItem.getPayPrice()).setDiscountPrice(discountPrices.get(i))); | |
| 436 | - } | |
| 437 | - // 创建营销明细 | |
| 438 | - PriceCalculateRespDTO.Promotion promotion = new PriceCalculateRespDTO.Promotion() | |
| 439 | - .setId(id).setName(name).setType(type).setLevel(level) | |
| 440 | - .setOriginalPrice(getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum)) | |
| 441 | - .setDiscountPrice(getSumValue(discountPrices, value -> value, Integer::sum)) | |
| 442 | - .setItems(promotionItems).setMeet(meet).setMeetTip(meetTip); | |
| 443 | - priceCalculate.getPromotions().add(promotion); | |
| 444 | - } | |
| 445 | - | |
| 446 | - private void addNotMeetPromotion(PriceCalculateRespDTO priceCalculate, List<PriceCalculateRespDTO.OrderItem> orderItems, | |
| 447 | - Long id, String name, Integer type, Integer level, String meetTip) { | |
| 448 | - // 创建营销明细 Item | |
| 449 | - List<PriceCalculateRespDTO.PromotionItem> promotionItems = CollectionUtils.convertList(orderItems, | |
| 450 | - orderItem -> new PriceCalculateRespDTO.PromotionItem().setSkuId(orderItem.getSkuId()) | |
| 451 | - .setOriginalPrice(orderItem.getOrderDividePrice()).setDiscountPrice(0)); | |
| 452 | - // 创建营销明细 | |
| 453 | - Integer originalPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum); | |
| 454 | - PriceCalculateRespDTO.Promotion promotion = new PriceCalculateRespDTO.Promotion() | |
| 455 | - .setId(id).setName(name).setType(type).setLevel(level) | |
| 456 | - .setOriginalPrice(originalPrice).setDiscountPrice(0) | |
| 457 | - .setItems(promotionItems).setMeet(false).setMeetTip(meetTip); | |
| 458 | - priceCalculate.getPromotions().add(promotion); | |
| 459 | - } | |
| 460 | - | |
| 461 | - /** | |
| 462 | - * 修改 OrderItem 的 payPrice 价格,同时会修改 Order 的 payPrice 价格 | |
| 463 | - * | |
| 464 | - * @param orderItem 订单商品 SKU | |
| 465 | - * @param newPayPrice 新的 payPrice 价格 | |
| 466 | - * @param priceCalculate 价格计算结果 | |
| 467 | - */ | |
| 468 | - private void modifyOrderItemPayPrice(PriceCalculateRespDTO.OrderItem orderItem, Integer newPayPrice, | |
| 469 | - PriceCalculateRespDTO priceCalculate) { | |
| 470 | - // diffPayPrice 等于额外增加的商品级的优惠 | |
| 471 | - int diffPayPrice = orderItem.getPayPrice() - newPayPrice; | |
| 472 | - // 设置 OrderItem 价格相关字段 | |
| 473 | - orderItem.setDiscountPrice(orderItem.getDiscountPrice() + diffPayPrice); | |
| 474 | - orderItem.setPayPrice(newPayPrice); | |
| 475 | - orderItem.setOrderDividePrice(orderItem.getPayPrice() - orderItem.getOrderPartPrice()); | |
| 476 | - // 设置 Order 相关相关字段 | |
| 477 | - PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); | |
| 478 | - order.setPayPrice(order.getPayPrice() - diffPayPrice); | |
| 479 | - order.setOrderPrice(order.getOrderPrice() - diffPayPrice); | |
| 480 | - } | |
| 481 | - | |
| 482 | - /** | |
| 483 | - * 修改 OrderItem 的 orderPartPrice 价格,同时会修改 Order 的 discountPrice 价格 | |
| 484 | - * | |
| 485 | - * 本质:分摊 Order 的 discountPrice 价格,到对应的 OrderItem 的 orderPartPrice 价格中 | |
| 486 | - * | |
| 487 | - * @param orderItem 订单商品 SKU | |
| 488 | - * @param addOrderPartPrice 新增的 discountPrice 价格 | |
| 489 | - * @param priceCalculate 价格计算结果 | |
| 490 | - */ | |
| 491 | - private void modifyOrderItemOrderPartPriceFromDiscountPrice(PriceCalculateRespDTO.OrderItem orderItem, Integer addOrderPartPrice, | |
| 492 | - PriceCalculateRespDTO priceCalculate) { | |
| 493 | - // 设置 OrderItem 价格相关字段 | |
| 494 | - orderItem.setOrderPartPrice(orderItem.getOrderPartPrice() + addOrderPartPrice); | |
| 495 | - orderItem.setOrderDividePrice(orderItem.getPayPrice() - orderItem.getOrderPartPrice()); | |
| 496 | - // 设置 Order 相关相关字段 | |
| 497 | - PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); | |
| 498 | - order.setDiscountPrice(order.getDiscountPrice() + addOrderPartPrice); | |
| 499 | - order.setPayPrice(order.getPayPrice() - addOrderPartPrice); | |
| 500 | - } | |
| 501 | - | |
| 502 | - /** | |
| 503 | - * 修改 OrderItem 的 orderPartPrice 价格,同时会修改 Order 的 couponPrice 价格 | |
| 504 | - * | |
| 505 | - * 本质:分摊 Order 的 couponPrice 价格,到对应的 OrderItem 的 orderPartPrice 价格中 | |
| 506 | - * | |
| 507 | - * @param orderItem 订单商品 SKU | |
| 508 | - * @param addOrderPartPrice 新增的 couponPrice 价格 | |
| 509 | - * @param priceCalculate 价格计算结果 | |
| 510 | - */ | |
| 511 | - private void modifyOrderItemOrderPartPriceFromCouponPrice(PriceCalculateRespDTO.OrderItem orderItem, Integer addOrderPartPrice, | |
| 512 | - PriceCalculateRespDTO priceCalculate) { | |
| 513 | - // 设置 OrderItem 价格相关字段 | |
| 514 | - orderItem.setOrderPartPrice(orderItem.getOrderPartPrice() + addOrderPartPrice); | |
| 515 | - orderItem.setOrderDividePrice(orderItem.getPayPrice() - orderItem.getOrderPartPrice()); | |
| 516 | - // 设置 Order 相关相关字段 | |
| 517 | - PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); | |
| 518 | - order.setCouponPrice(order.getCouponPrice() + addOrderPartPrice); | |
| 519 | - order.setPayPrice(order.getPayPrice() - addOrderPartPrice); | |
| 520 | - } | |
| 521 | - | |
| 522 | - private List<Integer> dividePrice(List<PriceCalculateRespDTO.OrderItem> orderItems, Integer price) { | |
| 523 | - List<Integer> prices = new ArrayList<>(orderItems.size()); | |
| 524 | - Integer total = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum); | |
| 525 | - assert total != null; | |
| 526 | - int remainPrice = price; | |
| 527 | - // 遍历每一个,进行分摊 | |
| 528 | - for (int i = 0; i < orderItems.size(); i++) { | |
| 529 | - PriceCalculateRespDTO.OrderItem orderItem = orderItems.get(i); | |
| 530 | - int partPrice; | |
| 531 | - if (i < orderItems.size() - 1) { // 减一的原因,是因为拆分时,如果按照比例,可能会出现.所以最后一个,使用反减 | |
| 532 | - partPrice = (int) (price * (1.0D * orderItem.getOrderDividePrice() / total)); | |
| 533 | - remainPrice -= partPrice; | |
| 534 | - } else { | |
| 535 | - partPrice = remainPrice; | |
| 536 | - } | |
| 537 | - Assert.isTrue(partPrice > 0, "分摊金额必须大于 0"); | |
| 538 | - prices.add(partPrice); | |
| 539 | - } | |
| 540 | - return prices; | |
| 541 | - } | |
| 542 | - | |
| 543 | - private String formatPrice(Integer price) { | |
| 544 | - return String.format("%.2f", price / 100d); | |
| 545 | - } | |
| 546 | - | |
| 547 | 96 | } | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java
| 1 | 1 | package cn.iocoder.yudao.module.promotion.service.reward; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; | |
| 4 | 5 | import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO; |
| 5 | 6 | import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO; |
| 6 | 7 | import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; |
| 8 | 9 | |
| 9 | 10 | import javax.validation.Valid; |
| 10 | -import java.util.Map; | |
| 11 | -import java.util.Set; | |
| 11 | +import java.util.Collection; | |
| 12 | +import java.util.List; | |
| 12 | 13 | |
| 13 | 14 | /** |
| 14 | 15 | * 满减送活动 Service 接口 |
| ... | ... | @@ -66,8 +67,8 @@ public interface RewardActivityService { |
| 66 | 67 | * 基于指定的 SPU 编号数组,获得它们匹配的满减送活动 |
| 67 | 68 | * |
| 68 | 69 | * @param spuIds SPU 编号数组 |
| 69 | - * @return 满减送活动,与对应的 SPU 编号的映射。即,value 就是 SPU 编号的集合 | |
| 70 | + * @return 满减送活动列表 | |
| 70 | 71 | */ |
| 71 | - Map<RewardActivityDO, Set<Long>> getMatchRewardActivities(Set<Long> spuIds); | |
| 72 | + List<RewardActivityMatchRespDTO> getMatchRewardActivityList(Collection<Long> spuIds); | |
| 72 | 73 | |
| 73 | 74 | } | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.promotion.service.reward; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | -import cn.hutool.core.map.MapUtil; | |
| 5 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; | |
| 6 | 6 | import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO; |
| 7 | 7 | import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO; |
| 8 | 8 | import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO; |
| ... | ... | @@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.promotion.convert.reward.RewardActivityConvert; |
| 10 | 10 | import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; |
| 11 | 11 | import cn.iocoder.yudao.module.promotion.dal.mysql.reward.RewardActivityMapper; |
| 12 | 12 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; |
| 13 | -import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; | |
| 14 | 13 | import cn.iocoder.yudao.module.promotion.util.PromotionUtils; |
| 15 | 14 | import org.springframework.stereotype.Service; |
| 16 | 15 | import org.springframework.validation.annotation.Validated; |
| ... | ... | @@ -18,15 +17,10 @@ import org.springframework.validation.annotation.Validated; |
| 18 | 17 | import javax.annotation.Resource; |
| 19 | 18 | import java.util.Collection; |
| 20 | 19 | import java.util.List; |
| 21 | -import java.util.Map; | |
| 22 | -import java.util.Set; | |
| 23 | 20 | |
| 24 | -import static cn.hutool.core.collection.CollUtil.intersectionDistinct; | |
| 25 | 21 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 26 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | |
| 27 | 22 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; |
| 28 | 23 | import static java.util.Arrays.asList; |
| 29 | -import static java.util.Collections.singleton; | |
| 30 | 24 | |
| 31 | 25 | /** |
| 32 | 26 | * 满减送活动 Service 实现类 |
| ... | ... | @@ -105,6 +99,7 @@ public class RewardActivityServiceImpl implements RewardActivityService { |
| 105 | 99 | return activity; |
| 106 | 100 | } |
| 107 | 101 | |
| 102 | + // TODO @芋艿:逻辑有问题,需要优化;要分成全场、和指定来校验; | |
| 108 | 103 | /** |
| 109 | 104 | * 校验商品参加的活动是否冲突 |
| 110 | 105 | * |
| ... | ... | @@ -151,19 +146,21 @@ public class RewardActivityServiceImpl implements RewardActivityService { |
| 151 | 146 | } |
| 152 | 147 | |
| 153 | 148 | @Override |
| 154 | - public Map<RewardActivityDO, Set<Long>> getMatchRewardActivities(Set<Long> spuIds) { | |
| 155 | - // 如果有全局活动,则直接选择它 | |
| 156 | - List<RewardActivityDO> allActivities = rewardActivityMapper.selectListByProductScopeAndStatus( | |
| 157 | - PromotionProductScopeEnum.ALL.getScope(), PromotionActivityStatusEnum.RUN.getStatus()); | |
| 158 | - if (CollUtil.isNotEmpty(allActivities)) { | |
| 159 | - return MapUtil.builder(allActivities.get(0), spuIds).build(); | |
| 160 | - } | |
| 161 | - | |
| 162 | - // 查询某个活动参加的活动 | |
| 163 | - List<RewardActivityDO> productActivityList = getRewardActivityListBySpuIds(spuIds, | |
| 164 | - singleton(PromotionActivityStatusEnum.RUN.getStatus())); | |
| 165 | - return convertMap(productActivityList, activity -> activity, | |
| 166 | - rewardActivityDO -> intersectionDistinct(rewardActivityDO.getProductSpuIds(), spuIds)); // 求交集返回 | |
| 149 | + public List<RewardActivityMatchRespDTO> getMatchRewardActivityList(Collection<Long> spuIds) { | |
| 150 | + // TODO 芋艿:待实现;先指定,然后再全局的; | |
| 151 | +// // 如果有全局活动,则直接选择它 | |
| 152 | +// List<RewardActivityDO> allActivities = rewardActivityMapper.selectListByProductScopeAndStatus( | |
| 153 | +// PromotionProductScopeEnum.ALL.getScope(), PromotionActivityStatusEnum.RUN.getStatus()); | |
| 154 | +// if (CollUtil.isNotEmpty(allActivities)) { | |
| 155 | +// return MapUtil.builder(allActivities.get(0), spuIds).build(); | |
| 156 | +// } | |
| 157 | +// | |
| 158 | +// // 查询某个活动参加的活动 | |
| 159 | +// List<RewardActivityDO> productActivityList = getRewardActivityListBySpuIds(spuIds, | |
| 160 | +// singleton(PromotionActivityStatusEnum.RUN.getStatus())); | |
| 161 | +// return convertMap(productActivityList, activity -> activity, | |
| 162 | +// rewardActivityDO -> intersectionDistinct(rewardActivityDO.getProductSpuIds(), spuIds)); // 求交集返回 | |
| 163 | + return null; | |
| 167 | 164 | } |
| 168 | 165 | |
| 169 | 166 | } | ... | ... |
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 { |
| 70 | 70 | PriceCalculateRespDTO priceCalculate = priceService.calculatePrice(calculateReqDTO); |
| 71 | 71 | // 断言 Order 部分 |
| 72 | 72 | PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); |
| 73 | - assertEquals(order.getOriginalPrice(), 200); | |
| 74 | - assertEquals(order.getOrderPrice(), 180); | |
| 73 | + assertEquals(order.getTotalPrice(), 200); | |
| 75 | 74 | assertEquals(order.getDiscountPrice(), 0); |
| 76 | 75 | assertEquals(order.getPointPrice(), 0); |
| 77 | 76 | assertEquals(order.getDeliveryPrice(), 0); |
| ... | ... | @@ -95,10 +94,10 @@ public class PriceServiceTest extends BaseMockitoUnitTest { |
| 95 | 94 | assertEquals(promotion.getName(), "会员折扣"); |
| 96 | 95 | assertEquals(promotion.getType(), PromotionTypeEnum.MEMBER.getType()); |
| 97 | 96 | assertEquals(promotion.getLevel(), PromotionLevelEnum.SKU.getLevel()); |
| 98 | - assertEquals(promotion.getOriginalPrice(), 200); | |
| 97 | + assertEquals(promotion.getTotalPrice(), 200); | |
| 99 | 98 | assertEquals(promotion.getDiscountPrice(), 20); |
| 100 | - assertTrue(promotion.getMeet()); | |
| 101 | - assertEquals(promotion.getMeetTip(), "会员折扣:省 0.20 元"); | |
| 99 | + assertTrue(promotion.getMatch()); | |
| 100 | + assertEquals(promotion.getDescription(), "会员折扣:省 0.20 元"); | |
| 102 | 101 | PriceCalculateRespDTO.PromotionItem promotionItem = promotion.getItems().get(0); |
| 103 | 102 | assertEquals(promotion.getItems().size(), 1); |
| 104 | 103 | assertEquals(promotionItem.getSkuId(), 10L); |
| ... | ... | @@ -123,7 +122,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { |
| 123 | 122 | DiscountProductDetailBO discountProduct02 = randomPojo(DiscountProductDetailBO.class, o -> o.setActivityId(2000L) |
| 124 | 123 | .setActivityName("活动 2000 号").setSkuId(20L) |
| 125 | 124 | .setDiscountType(PromotionDiscountTypeEnum.PERCENT.getType()).setDiscountPercent(60)); |
| 126 | - when(discountService.getMatchDiscountProducts(eq(asSet(10L, 20L)))).thenReturn( | |
| 125 | + when(discountService.getMatchDiscountProductList(eq(asSet(10L, 20L)))).thenReturn( | |
| 127 | 126 | MapUtil.builder(10L, discountProduct01).put(20L, discountProduct02).map()); |
| 128 | 127 | |
| 129 | 128 | // 10L: 100 * 2 - 40 * 2 = 120 |
| ... | ... | @@ -133,8 +132,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { |
| 133 | 132 | PriceCalculateRespDTO priceCalculate = priceService.calculatePrice(calculateReqDTO); |
| 134 | 133 | // 断言 Order 部分 |
| 135 | 134 | PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); |
| 136 | - assertEquals(order.getOriginalPrice(), 350); | |
| 137 | - assertEquals(order.getOrderPrice(), 210); | |
| 135 | + assertEquals(order.getTotalPrice(), 350); | |
| 138 | 136 | assertEquals(order.getDiscountPrice(), 0); |
| 139 | 137 | assertEquals(order.getPointPrice(), 0); |
| 140 | 138 | assertEquals(order.getDeliveryPrice(), 0); |
| ... | ... | @@ -167,10 +165,10 @@ public class PriceServiceTest extends BaseMockitoUnitTest { |
| 167 | 165 | assertEquals(promotion01.getName(), "活动 1000 号"); |
| 168 | 166 | assertEquals(promotion01.getType(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType()); |
| 169 | 167 | assertEquals(promotion01.getLevel(), PromotionLevelEnum.SKU.getLevel()); |
| 170 | - assertEquals(promotion01.getOriginalPrice(), 200); | |
| 168 | + assertEquals(promotion01.getTotalPrice(), 200); | |
| 171 | 169 | assertEquals(promotion01.getDiscountPrice(), 80); |
| 172 | - assertTrue(promotion01.getMeet()); | |
| 173 | - assertEquals(promotion01.getMeetTip(), "限时折扣:省 0.80 元"); | |
| 170 | + assertTrue(promotion01.getMatch()); | |
| 171 | + assertEquals(promotion01.getDescription(), "限时折扣:省 0.80 元"); | |
| 174 | 172 | PriceCalculateRespDTO.PromotionItem promotionItem01 = promotion01.getItems().get(0); |
| 175 | 173 | assertEquals(promotion01.getItems().size(), 1); |
| 176 | 174 | assertEquals(promotionItem01.getSkuId(), 10L); |
| ... | ... | @@ -181,10 +179,10 @@ public class PriceServiceTest extends BaseMockitoUnitTest { |
| 181 | 179 | assertEquals(promotion02.getName(), "活动 2000 号"); |
| 182 | 180 | assertEquals(promotion02.getType(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType()); |
| 183 | 181 | assertEquals(promotion02.getLevel(), PromotionLevelEnum.SKU.getLevel()); |
| 184 | - assertEquals(promotion02.getOriginalPrice(), 150); | |
| 182 | + assertEquals(promotion02.getTotalPrice(), 150); | |
| 185 | 183 | assertEquals(promotion02.getDiscountPrice(), 60); |
| 186 | - assertTrue(promotion02.getMeet()); | |
| 187 | - assertEquals(promotion02.getMeetTip(), "限时折扣:省 0.60 元"); | |
| 184 | + assertTrue(promotion02.getMatch()); | |
| 185 | + assertEquals(promotion02.getDescription(), "限时折扣:省 0.60 元"); | |
| 188 | 186 | PriceCalculateRespDTO.PromotionItem promotionItem02 = promotion02.getItems().get(0); |
| 189 | 187 | assertEquals(promotion02.getItems().size(), 1); |
| 190 | 188 | assertEquals(promotionItem02.getSkuId(), 20L); |
| ... | ... | @@ -225,8 +223,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { |
| 225 | 223 | PriceCalculateRespDTO priceCalculate = priceService.calculatePrice(calculateReqDTO); |
| 226 | 224 | // 断言 Order 部分 |
| 227 | 225 | PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); |
| 228 | - assertEquals(order.getOriginalPrice(), 470); | |
| 229 | - assertEquals(order.getOrderPrice(), 470); | |
| 226 | + assertEquals(order.getTotalPrice(), 470); | |
| 230 | 227 | assertEquals(order.getDiscountPrice(), 130); |
| 231 | 228 | assertEquals(order.getPointPrice(), 0); |
| 232 | 229 | assertEquals(order.getDeliveryPrice(), 0); |
| ... | ... | @@ -268,10 +265,10 @@ public class PriceServiceTest extends BaseMockitoUnitTest { |
| 268 | 265 | assertEquals(promotion01.getName(), "活动 1000 号"); |
| 269 | 266 | assertEquals(promotion01.getType(), PromotionTypeEnum.REWARD_ACTIVITY.getType()); |
| 270 | 267 | assertEquals(promotion01.getLevel(), PromotionLevelEnum.ORDER.getLevel()); |
| 271 | - assertEquals(promotion01.getOriginalPrice(), 350); | |
| 268 | + assertEquals(promotion01.getTotalPrice(), 350); | |
| 272 | 269 | assertEquals(promotion01.getDiscountPrice(), 70); |
| 273 | - assertTrue(promotion01.getMeet()); | |
| 274 | - assertEquals(promotion01.getMeetTip(), "满减送:省 0.70 元"); | |
| 270 | + assertTrue(promotion01.getMatch()); | |
| 271 | + assertEquals(promotion01.getDescription(), "满减送:省 0.70 元"); | |
| 275 | 272 | assertEquals(promotion01.getItems().size(), 2); |
| 276 | 273 | PriceCalculateRespDTO.PromotionItem promotionItem011 = promotion01.getItems().get(0); |
| 277 | 274 | assertEquals(promotionItem011.getSkuId(), 10L); |
| ... | ... | @@ -287,10 +284,10 @@ public class PriceServiceTest extends BaseMockitoUnitTest { |
| 287 | 284 | assertEquals(promotion02.getName(), "活动 2000 号"); |
| 288 | 285 | assertEquals(promotion02.getType(), PromotionTypeEnum.REWARD_ACTIVITY.getType()); |
| 289 | 286 | assertEquals(promotion02.getLevel(), PromotionLevelEnum.ORDER.getLevel()); |
| 290 | - assertEquals(promotion02.getOriginalPrice(), 120); | |
| 287 | + assertEquals(promotion02.getTotalPrice(), 120); | |
| 291 | 288 | assertEquals(promotion02.getDiscountPrice(), 60); |
| 292 | - assertTrue(promotion02.getMeet()); | |
| 293 | - assertEquals(promotion02.getMeetTip(), "满减送:省 0.60 元"); | |
| 289 | + assertTrue(promotion02.getMatch()); | |
| 290 | + assertEquals(promotion02.getDescription(), "满减送:省 0.60 元"); | |
| 294 | 291 | PriceCalculateRespDTO.PromotionItem promotionItem02 = promotion02.getItems().get(0); |
| 295 | 292 | assertEquals(promotion02.getItems().size(), 1); |
| 296 | 293 | assertEquals(promotionItem02.getSkuId(), 30L); |
| ... | ... | @@ -323,8 +320,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { |
| 323 | 320 | PriceCalculateRespDTO priceCalculate = priceService.calculatePrice(calculateReqDTO); |
| 324 | 321 | // 断言 Order 部分 |
| 325 | 322 | PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); |
| 326 | - assertEquals(order.getOriginalPrice(), 350); | |
| 327 | - assertEquals(order.getOrderPrice(), 350); | |
| 323 | + assertEquals(order.getTotalPrice(), 350); | |
| 328 | 324 | assertEquals(order.getDiscountPrice(), 0); |
| 329 | 325 | assertEquals(order.getPointPrice(), 0); |
| 330 | 326 | assertEquals(order.getDeliveryPrice(), 0); |
| ... | ... | @@ -357,10 +353,10 @@ public class PriceServiceTest extends BaseMockitoUnitTest { |
| 357 | 353 | assertEquals(promotion01.getName(), "活动 1000 号"); |
| 358 | 354 | assertEquals(promotion01.getType(), PromotionTypeEnum.REWARD_ACTIVITY.getType()); |
| 359 | 355 | assertEquals(promotion01.getLevel(), PromotionLevelEnum.ORDER.getLevel()); |
| 360 | - assertEquals(promotion01.getOriginalPrice(), 350); | |
| 356 | + assertEquals(promotion01.getTotalPrice(), 350); | |
| 361 | 357 | assertEquals(promotion01.getDiscountPrice(), 0); |
| 362 | - assertFalse(promotion01.getMeet()); | |
| 363 | - assertEquals(promotion01.getMeetTip(), "TODO"); // TODO 芋艿:后面再想想 | |
| 358 | + assertFalse(promotion01.getMatch()); | |
| 359 | + assertEquals(promotion01.getDescription(), "TODO"); // TODO 芋艿:后面再想想 | |
| 364 | 360 | assertEquals(promotion01.getItems().size(), 2); |
| 365 | 361 | PriceCalculateRespDTO.PromotionItem promotionItem011 = promotion01.getItems().get(0); |
| 366 | 362 | assertEquals(promotionItem011.getSkuId(), 10L); |
| ... | ... | @@ -396,8 +392,7 @@ public class PriceServiceTest extends BaseMockitoUnitTest { |
| 396 | 392 | PriceCalculateRespDTO priceCalculate = priceService.calculatePrice(calculateReqDTO); |
| 397 | 393 | // 断言 Order 部分 |
| 398 | 394 | PriceCalculateRespDTO.Order order = priceCalculate.getOrder(); |
| 399 | - assertEquals(order.getOriginalPrice(), 470); | |
| 400 | - assertEquals(order.getOrderPrice(), 470); | |
| 395 | + assertEquals(order.getTotalPrice(), 470); | |
| 401 | 396 | assertEquals(order.getDiscountPrice(), 0); |
| 402 | 397 | assertEquals(order.getPointPrice(), 0); |
| 403 | 398 | assertEquals(order.getDeliveryPrice(), 0); |
| ... | ... | @@ -440,10 +435,10 @@ public class PriceServiceTest extends BaseMockitoUnitTest { |
| 440 | 435 | assertEquals(promotion01.getName(), "程序员节"); |
| 441 | 436 | assertEquals(promotion01.getType(), PromotionTypeEnum.COUPON.getType()); |
| 442 | 437 | assertEquals(promotion01.getLevel(), PromotionLevelEnum.COUPON.getLevel()); |
| 443 | - assertEquals(promotion01.getOriginalPrice(), 350); | |
| 438 | + assertEquals(promotion01.getTotalPrice(), 350); | |
| 444 | 439 | assertEquals(promotion01.getDiscountPrice(), 70); |
| 445 | - assertTrue(promotion01.getMeet()); | |
| 446 | - assertEquals(promotion01.getMeetTip(), "优惠劵:省 0.70 元"); | |
| 440 | + assertTrue(promotion01.getMatch()); | |
| 441 | + assertEquals(promotion01.getDescription(), "优惠劵:省 0.70 元"); | |
| 447 | 442 | assertEquals(promotion01.getItems().size(), 2); |
| 448 | 443 | PriceCalculateRespDTO.PromotionItem promotionItem011 = promotion01.getItems().get(0); |
| 449 | 444 | assertEquals(promotionItem011.getSkuId(), 10L); | ... | ... |
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 { |
| 50 | 50 | ErrorCode EXPRESS_CODE_DUPLICATE = new ErrorCode(1011003001, "已经存在该编码的快递公司"); |
| 51 | 51 | ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1011003002, "运费模板不存在"); |
| 52 | 52 | ErrorCode EXPRESS_TEMPLATE_NAME_DUPLICATE = new ErrorCode(1011003002, "已经存在该运费模板名"); |
| 53 | + | |
| 54 | + // ========== Price 相关 1011004000 ============ | |
| 55 | + ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011004000, "支付价格计算异常,原因:价格小于等于 0"); | |
| 56 | + | |
| 53 | 57 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressController.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.controller.admin.delivery; |
| 2 | 2 | |
| 3 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.*; | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 5 | +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | |
| 6 | +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | |
| 7 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.*; | |
| 8 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressUpdateReqVO; | |
| 4 | 9 | import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryExpressConvert; |
| 5 | 10 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; |
| 6 | 11 | import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; |
| 7 | -import org.springframework.web.bind.annotation.*; | |
| 8 | -import javax.annotation.Resource; | |
| 9 | -import org.springframework.validation.annotation.Validated; | |
| 10 | -import org.springframework.security.access.prepost.PreAuthorize; | |
| 11 | -import io.swagger.v3.oas.annotations.tags.Tag; | |
| 12 | -import io.swagger.v3.oas.annotations.Parameter; | |
| 13 | 12 | import io.swagger.v3.oas.annotations.Operation; |
| 13 | +import io.swagger.v3.oas.annotations.Parameter; | |
| 14 | +import io.swagger.v3.oas.annotations.tags.Tag; | |
| 15 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 16 | +import org.springframework.validation.annotation.Validated; | |
| 17 | +import org.springframework.web.bind.annotation.*; | |
| 14 | 18 | |
| 15 | -import javax.validation.constraints.*; | |
| 16 | -import javax.validation.*; | |
| 17 | -import javax.servlet.http.*; | |
| 18 | -import java.util.*; | |
| 19 | +import javax.annotation.Resource; | |
| 20 | +import javax.servlet.http.HttpServletResponse; | |
| 21 | +import javax.validation.Valid; | |
| 19 | 22 | import java.io.IOException; |
| 23 | +import java.util.List; | |
| 20 | 24 | |
| 21 | -import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 22 | -import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 23 | 25 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 24 | - | |
| 25 | -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | |
| 26 | - | |
| 27 | -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | |
| 28 | -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*; | |
| 26 | +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; | |
| 29 | 27 | |
| 30 | 28 | @Tag(name = "管理后台 - 快递公司") |
| 31 | 29 | @RestController |
| ... | ... | @@ -77,6 +75,7 @@ public class DeliveryExpressController { |
| 77 | 75 | return success(DeliveryExpressConvert.INSTANCE.convertPage(pageResult)); |
| 78 | 76 | } |
| 79 | 77 | |
| 78 | + // TODO @jason:运费模版,@芋艿 你的意思是运费模板导出没有必要吧。已经去掉了。这个是快递公司导出 | |
| 80 | 79 | @GetMapping("/export-excel") |
| 81 | 80 | @Operation(summary = "导出快递公司 Excel") |
| 82 | 81 | @PreAuthorize("@ss.hasPermission('trade:delivery:express:export')") | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressTemplateController.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.controller.admin.delivery; |
| 2 | 2 | |
| 3 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.*; | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 5 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.*; | |
| 4 | 6 | import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryExpressTemplateConvert; |
| 5 | 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; |
| 6 | 8 | import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService; |
| 7 | -import org.springframework.web.bind.annotation.*; | |
| 8 | -import javax.annotation.Resource; | |
| 9 | -import org.springframework.validation.annotation.Validated; | |
| 10 | -import org.springframework.security.access.prepost.PreAuthorize; | |
| 11 | -import io.swagger.v3.oas.annotations.tags.Tag; | |
| 12 | -import io.swagger.v3.oas.annotations.Parameter; | |
| 13 | 9 | import io.swagger.v3.oas.annotations.Operation; |
| 10 | +import io.swagger.v3.oas.annotations.Parameter; | |
| 11 | +import io.swagger.v3.oas.annotations.tags.Tag; | |
| 12 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 13 | +import org.springframework.validation.annotation.Validated; | |
| 14 | +import org.springframework.web.bind.annotation.*; | |
| 14 | 15 | |
| 15 | -import javax.validation.*; | |
| 16 | -import javax.servlet.http.*; | |
| 17 | -import java.util.*; | |
| 18 | -import java.io.IOException; | |
| 16 | +import javax.annotation.Resource; | |
| 17 | +import javax.validation.Valid; | |
| 18 | +import java.util.Collection; | |
| 19 | +import java.util.List; | |
| 19 | 20 | |
| 20 | -import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 21 | -import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 22 | 21 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 23 | 22 | |
| 24 | -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | |
| 25 | - | |
| 26 | -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | |
| 27 | -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*; | |
| 28 | - | |
| 29 | 23 | |
| 30 | 24 | @Tag(name = "管理后台 - 快递运费模板") |
| 31 | 25 | @RestController |
| ... | ... | @@ -85,16 +79,4 @@ public class DeliveryExpressTemplateController { |
| 85 | 79 | return success(DeliveryExpressTemplateConvert.INSTANCE.convertPage(pageResult)); |
| 86 | 80 | } |
| 87 | 81 | |
| 88 | - @GetMapping("/export-excel") | |
| 89 | - @Operation(summary = "导出快递运费模板 Excel") | |
| 90 | - @PreAuthorize("@ss.hasPermission('trade:delivery:express-template:export')") | |
| 91 | - @OperateLog(type = EXPORT) | |
| 92 | - public void exportDeliveryExpressTemplateExcel(@Valid DeliveryExpressTemplateExportReqVO exportReqVO, | |
| 93 | - HttpServletResponse response) throws IOException { | |
| 94 | - List<DeliveryExpressTemplateDO> list = deliveryExpressTemplateService.getDeliveryExpressTemplateList(exportReqVO); | |
| 95 | - // 导出 Excel | |
| 96 | - List<DeliveryExpressTemplateExcelVO> datas = DeliveryExpressTemplateConvert.INSTANCE.convertList02(list); | |
| 97 | - ExcelUtils.write(response, "快递运费模板.xls", "数据", DeliveryExpressTemplateExcelVO.class, datas); | |
| 98 | - } | |
| 99 | - | |
| 100 | 82 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateExcelVO.java deleted
| 1 | -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; | |
| 2 | - | |
| 3 | -import com.alibaba.excel.annotation.ExcelProperty; | |
| 4 | -import lombok.Data; | |
| 5 | - | |
| 6 | -import java.time.LocalDateTime; | |
| 7 | - | |
| 8 | -/** | |
| 9 | - * 快递运费模板 Excel VO | |
| 10 | - * | |
| 11 | - * @author jason | |
| 12 | - */ | |
| 13 | -@Data | |
| 14 | -public class DeliveryExpressTemplateExcelVO { | |
| 15 | - | |
| 16 | - @ExcelProperty("编号,自增") | |
| 17 | - private Long id; | |
| 18 | - | |
| 19 | - @ExcelProperty("模板名称") | |
| 20 | - private String name; | |
| 21 | - | |
| 22 | - @ExcelProperty("配送计费方式 1:按件 2:按重量 3:按体积") | |
| 23 | - private Integer chargeMode; | |
| 24 | - | |
| 25 | - @ExcelProperty("排序") | |
| 26 | - private Integer sort; | |
| 27 | - | |
| 28 | - @ExcelProperty("创建时间") | |
| 29 | - private LocalDateTime createTime; | |
| 30 | - | |
| 31 | -} |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateExportReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; | |
| 2 | - | |
| 3 | -import lombok.*; | |
| 4 | -import java.util.*; | |
| 5 | -import io.swagger.v3.oas.annotations.media.Schema; | |
| 6 | -import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 7 | -import java.time.LocalDateTime; | |
| 8 | -import org.springframework.format.annotation.DateTimeFormat; | |
| 9 | - | |
| 10 | -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 11 | - | |
| 12 | -@Schema(description = "管理后台 - 快递运费模板 Excel 导出 Request VO,参数和 DeliveryExpressTemplatePageReqVO 是一致的") | |
| 13 | -@Data | |
| 14 | -public class DeliveryExpressTemplateExportReqVO { | |
| 15 | - | |
| 16 | - @Schema(description = "模板名称", example = "王五") | |
| 17 | - private String name; | |
| 18 | - | |
| 19 | - @Schema(description = "配送计费方式 1:按件 2:按重量 3:按体积") | |
| 20 | - private Integer chargeMode; | |
| 21 | - | |
| 22 | - @Schema(description = "创建时间") | |
| 23 | - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 24 | - private LocalDateTime[] createTime; | |
| 25 | - | |
| 26 | -} |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressBaseVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressBaseVO.java
| 1 | -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; | |
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express; | |
| 2 | 2 | |
| 3 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | -import lombok.*; | |
| 5 | -import java.util.*; | |
| 6 | -import java.time.LocalDateTime; | |
| 7 | -import java.time.LocalDateTime; | |
| 8 | -import javax.validation.constraints.*; | |
| 4 | +import lombok.Data; | |
| 5 | + | |
| 6 | +import javax.validation.constraints.NotNull; | |
| 9 | 7 | |
| 10 | 8 | /** |
| 11 | 9 | * 快递公司 Base VO,提供给添加、修改、详细的子 VO 使用 |
| ... | ... | @@ -14,8 +12,8 @@ import javax.validation.constraints.*; |
| 14 | 12 | @Data |
| 15 | 13 | public class DeliveryExpressBaseVO { |
| 16 | 14 | |
| 17 | - @Schema(description = "快递公司编号", required = true) | |
| 18 | - @NotNull(message = "快递公司编号不能为空") | |
| 15 | + @Schema(description = "快递公司编码", required = true) | |
| 16 | + @NotNull(message = "快递公司编码不能为空") | |
| 19 | 17 | private String code; |
| 20 | 18 | |
| 21 | 19 | @Schema(description = "快递公司名称", required = true, example = "李四") | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressCreateReqVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressCreateReqVO.java
| 1 | -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; | |
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express; | |
| 2 | 2 | |
| 3 | 3 | import lombok.*; |
| 4 | -import java.util.*; | |
| 5 | 4 | import io.swagger.v3.oas.annotations.media.Schema; |
| 6 | -import javax.validation.constraints.*; | |
| 7 | 5 | |
| 8 | 6 | @Schema(description = "管理后台 - 快递公司创建 Request VO") |
| 9 | 7 | @Data | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExcelVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressExcelVO.java
| 1 | -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; | |
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express; | |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 4 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 5 | +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; | |
| 3 | 6 | import com.alibaba.excel.annotation.ExcelProperty; |
| 4 | 7 | import lombok.Data; |
| 5 | 8 | |
| ... | ... | @@ -7,8 +10,6 @@ import java.time.LocalDateTime; |
| 7 | 10 | |
| 8 | 11 | /** |
| 9 | 12 | * 快递公司 Excel VO |
| 10 | - * | |
| 11 | - * @author jason | |
| 12 | 13 | */ |
| 13 | 14 | @Data |
| 14 | 15 | public class DeliveryExpressExcelVO { |
| ... | ... | @@ -16,20 +17,21 @@ public class DeliveryExpressExcelVO { |
| 16 | 17 | @ExcelProperty("编号") |
| 17 | 18 | private Long id; |
| 18 | 19 | |
| 19 | - @ExcelProperty("快递公司编号") | |
| 20 | + @ExcelProperty("快递公司编码") | |
| 20 | 21 | private String code; |
| 21 | 22 | |
| 22 | 23 | @ExcelProperty("快递公司名称") |
| 23 | 24 | private String name; |
| 24 | 25 | |
| 25 | - @ExcelProperty("快递公司logo") | |
| 26 | + @ExcelProperty("快递公司 logo") | |
| 26 | 27 | private String logo; |
| 27 | 28 | |
| 28 | 29 | @ExcelProperty("排序") |
| 29 | 30 | private Integer sort; |
| 30 | 31 | |
| 31 | - @ExcelProperty("状态(0正常 1停用)") | |
| 32 | - private Byte status; | |
| 32 | + @ExcelProperty(value = "状态", converter = DictConvert.class) | |
| 33 | + @DictFormat(DictTypeConstants.COMMON_STATUS) | |
| 34 | + private Integer status; | |
| 33 | 35 | |
| 34 | 36 | @ExcelProperty("创建时间") |
| 35 | 37 | private LocalDateTime createTime; | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressExportReqVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressExportReqVO.java
| 1 | -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; | |
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express; | |
| 2 | 2 | |
| 3 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | 4 | import lombok.Data; |
| ... | ... | @@ -12,7 +12,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ |
| 12 | 12 | @Data |
| 13 | 13 | public class DeliveryExpressExportReqVO { |
| 14 | 14 | |
| 15 | - @Schema(description = "快递公司编号") | |
| 15 | + @Schema(description = "快递公司编码") | |
| 16 | 16 | private String code; |
| 17 | 17 | |
| 18 | 18 | @Schema(description = "快递公司名称", example = "李四") | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressPageReqVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressPageReqVO.java
| 1 | -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; | |
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express; | |
| 2 | 2 | |
| 3 | 3 | import lombok.*; |
| 4 | 4 | import java.util.*; |
| ... | ... | @@ -15,7 +15,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ |
| 15 | 15 | @ToString(callSuper = true) |
| 16 | 16 | public class DeliveryExpressPageReqVO extends PageParam { |
| 17 | 17 | |
| 18 | - @Schema(description = "快递公司编号") | |
| 18 | + @Schema(description = "快递公司编码") | |
| 19 | 19 | private String code; |
| 20 | 20 | |
| 21 | 21 | @Schema(description = "快递公司名称", example = "李四") | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressRespVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressRespVO.java
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressUpdateReqVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressUpdateReqVO.java
| 1 | -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; | |
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express; | |
| 2 | 2 | |
| 3 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | -import lombok.*; | |
| 5 | -import java.util.*; | |
| 6 | -import javax.validation.constraints.*; | |
| 4 | +import lombok.Data; | |
| 5 | +import lombok.EqualsAndHashCode; | |
| 6 | +import lombok.ToString; | |
| 7 | + | |
| 8 | +import javax.validation.constraints.NotNull; | |
| 7 | 9 | |
| 8 | 10 | @Schema(description = "管理后台 - 快递公司更新 Request VO") |
| 9 | 11 | @Data | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateBaseVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateBaseVO.java
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateCreateReqVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateCreateReqVO.java
| 1 | -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; | |
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; | |
| 2 | 2 | |
| 3 | -import lombok.*; | |
| 4 | -import java.util.*; | |
| 5 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | +import lombok.Data; | |
| 5 | +import lombok.EqualsAndHashCode; | |
| 6 | +import lombok.ToString; | |
| 6 | 7 | |
| 7 | 8 | import javax.validation.Valid; |
| 9 | +import java.util.Collections; | |
| 10 | +import java.util.List; | |
| 8 | 11 | |
| 9 | 12 | @Schema(description = "管理后台 - 快递运费模板创建 Request VO") |
| 10 | 13 | @Data |
| ... | ... | @@ -12,6 +15,8 @@ import javax.validation.Valid; |
| 12 | 15 | @ToString(callSuper = true) |
| 13 | 16 | public class DeliveryExpressTemplateCreateReqVO extends DeliveryExpressTemplateBaseVO { |
| 14 | 17 | |
| 18 | + // TODO @jason:不用给默认值哈 | |
| 19 | + | |
| 15 | 20 | @Schema(description = "区域运费列表") |
| 16 | 21 | @Valid |
| 17 | 22 | private List<ExpressTemplateChargeBaseVO> templateCharge = Collections.emptyList(); | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplatePageReqVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplatePageReqVO.java
| 1 | -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; | |
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; | |
| 2 | 2 | |
| 3 | -import lombok.*; | |
| 4 | -import java.util.*; | |
| 5 | -import io.swagger.v3.oas.annotations.media.Schema; | |
| 6 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.EqualsAndHashCode; | |
| 7 | +import lombok.ToString; | |
| 7 | 8 | import org.springframework.format.annotation.DateTimeFormat; |
| 9 | + | |
| 8 | 10 | import java.time.LocalDateTime; |
| 9 | 11 | |
| 10 | 12 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateRespVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateRespVO.java
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateSimpleRespVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateSimpleRespVO.java
| 1 | -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; | |
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; | |
| 2 | 2 | |
| 3 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | 4 | import lombok.*; |
| 5 | 5 | import java.time.LocalDateTime; |
| 6 | 6 | |
| 7 | +// TODO @jason:simplae 是不是不用继承 DeliveryExpressTemplateBaseVO,直接 id name 属性就够了。 | |
| 7 | 8 | @Schema(description = "管理后台 - 快递运费模板 精简 Response VO") |
| 8 | 9 | @Data |
| 9 | 10 | @EqualsAndHashCode(callSuper = true) | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/DeliveryExpressTemplateUpdateReqVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateUpdateReqVO.java
| 1 | -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; | |
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; | |
| 2 | 2 | |
| 3 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | -import lombok.*; | |
| 5 | -import java.util.*; | |
| 4 | +import lombok.Data; | |
| 5 | +import lombok.EqualsAndHashCode; | |
| 6 | +import lombok.ToString; | |
| 7 | + | |
| 6 | 8 | import javax.validation.Valid; |
| 7 | -import javax.validation.constraints.*; | |
| 9 | +import javax.validation.constraints.NotNull; | |
| 10 | +import java.util.Collections; | |
| 11 | +import java.util.List; | |
| 8 | 12 | |
| 9 | 13 | @Schema(description = "管理后台 - 快递运费模板更新 Request VO") |
| 10 | 14 | @Data |
| ... | ... | @@ -16,6 +20,8 @@ public class DeliveryExpressTemplateUpdateReqVO extends DeliveryExpressTemplateB |
| 16 | 20 | @NotNull(message = "编号不能为空") |
| 17 | 21 | private Long id; |
| 18 | 22 | |
| 23 | + // TODO @jason:pojo 不给默认值哈 | |
| 24 | + | |
| 19 | 25 | @Schema(description = "区域运费列表") |
| 20 | 26 | @Valid |
| 21 | 27 | private List<ExpressTemplateChargeUpdateVO> templateCharge = Collections.emptyList(); | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateChargeBaseVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/ExpressTemplateChargeBaseVO.java
| 1 | -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; | |
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; | |
| 2 | 2 | |
| 3 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | 4 | import lombok.Data; |
| 5 | 5 | |
| 6 | +import javax.validation.constraints.NotEmpty; | |
| 6 | 7 | import javax.validation.constraints.NotNull; |
| 8 | +import java.util.List; | |
| 7 | 9 | |
| 8 | 10 | /** |
| 9 | 11 | * 快递运费模板运费设置 Base VO,提供给添加运费模板使用 |
| 10 | - * | |
| 11 | - * @author jason | |
| 12 | 12 | */ |
| 13 | 13 | @Data |
| 14 | 14 | public class ExpressTemplateChargeBaseVO { |
| 15 | 15 | |
| 16 | - @Schema(description = "区域编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 17 | - @NotNull(message = "区域编号不能为空") | |
| 18 | - private Integer areaId; | |
| 16 | + @Schema(description = "区域编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,120000]") | |
| 17 | + @NotEmpty(message = "区域编号列表不能为空") | |
| 18 | + private List<Integer> areaIds; | |
| 19 | 19 | |
| 20 | 20 | @Schema(description = "首件数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") |
| 21 | 21 | @NotNull(message = "首件数量不能为空") | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateChargeUpdateVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/ExpressTemplateChargeUpdateVO.java
| 1 | -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; | |
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; | |
| 2 | 2 | |
| 3 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | 4 | import lombok.Data; |
| 5 | 5 | |
| 6 | -/** | |
| 7 | - * @author jason | |
| 8 | - */ | |
| 6 | +// TODO @jason:这个 vo 可以内嵌到 DeliveryExpressTemplateUpdateReqVO,避免 vo 过多,不好分辨 | |
| 7 | +@Schema(description = "管理后台 - 快递公司创建 Request VO") | |
| 9 | 8 | @Data |
| 10 | 9 | public class ExpressTemplateChargeUpdateVO extends ExpressTemplateChargeBaseVO { |
| 11 | 10 | |
| 12 | 11 | @Schema(description = "编号", example = "6592") |
| 13 | 12 | private Long id; |
| 14 | 13 | |
| 14 | + // TODO @jason:这几个字段,应该不通过前端传递,而是后端查询后去赋值的 | |
| 15 | + | |
| 15 | 16 | @Schema(description = "配送模板编号", example = "1") |
| 16 | 17 | private Long templateId; |
| 17 | 18 | |
| 18 | 19 | @Schema(description = "配送计费方式", example = "1") |
| 19 | 20 | private Integer chargeMode; |
| 21 | + | |
| 20 | 22 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateFreeBaseVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/ExpressTemplateFreeBaseVO.java
| 1 | -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; | |
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; | |
| 2 | 2 | |
| 3 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | 4 | import lombok.Data; |
| 5 | 5 | |
| 6 | +import javax.validation.constraints.NotEmpty; | |
| 6 | 7 | import javax.validation.constraints.NotNull; |
| 8 | +import java.util.List; | |
| 7 | 9 | |
| 8 | 10 | /** |
| 9 | 11 | * 快递运费模板包邮 Base VO,提供给添加运费模板使用 |
| 10 | - * | |
| 11 | - * @author jason | |
| 12 | 12 | */ |
| 13 | 13 | @Data |
| 14 | 14 | public class ExpressTemplateFreeBaseVO { |
| 15 | 15 | |
| 16 | - @Schema(description = "区域编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 17 | - @NotNull(message = "区域编号不能为空") | |
| 18 | - private Integer areaId; | |
| 16 | + @Schema(description = "区域编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,120000]") | |
| 17 | + @NotEmpty(message = "区域编号列表不能为空") | |
| 18 | + private List<Integer> areaIds; | |
| 19 | 19 | |
| 20 | 20 | @Schema(description = "包邮金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "5000") |
| 21 | 21 | @NotNull(message = "包邮金额不能为空") |
| ... | ... | @@ -24,4 +24,5 @@ public class ExpressTemplateFreeBaseVO { |
| 24 | 24 | @Schema(description = "包邮件数", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") |
| 25 | 25 | @NotNull(message = "包邮件数不能为空") |
| 26 | 26 | private Integer freeCount; |
| 27 | + | |
| 27 | 28 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/ExpressTemplateFreeUpdateVO.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/ExpressTemplateFreeUpdateVO.java
| 1 | -package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo; | |
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; | |
| 2 | 2 | |
| 3 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | 4 | import lombok.Data; |
| 5 | 5 | |
| 6 | +// TODO @jason:这个 vo 可以内嵌到 DeliveryExpressTemplateUpdateReqVO,避免 vo 过多,不好分辨 | |
| 7 | +// TODO @jason:swagger 缺失 | |
| 6 | 8 | /** |
| 7 | 9 | * 快递运费模板包邮 更新 VO |
| 8 | - * | |
| 9 | - * @author jason | |
| 10 | 10 | */ |
| 11 | 11 | @Data |
| 12 | 12 | public class ExpressTemplateFreeUpdateVO extends ExpressTemplateFreeBaseVO { | ... | ... |
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 { |
| 73 | 73 | @Schema(description = "商品原价(总)", required = true, example = "1000") |
| 74 | 74 | private Integer originalPrice; |
| 75 | 75 | |
| 76 | - @Schema(description = "订单原价(总)", required = true, example = "1000") | |
| 77 | - private Integer orderPrice; | |
| 78 | - | |
| 79 | 76 | @Schema(description = "订单优惠(总)", required = true, example = "100") |
| 80 | 77 | private Integer discountPrice; |
| 81 | 78 | ... | ... |
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 { |
| 59 | 59 | private String payChannelCode; |
| 60 | 60 | |
| 61 | 61 | @Schema(description = "商品原价(总)", required = true, example = "1000") |
| 62 | - private Integer originalPrice; | |
| 63 | - | |
| 64 | - @Schema(description = "订单原价(总)", required = true, example = "1000") | |
| 65 | - private Integer orderPrice; | |
| 62 | + private Integer totalPrice; | |
| 66 | 63 | |
| 67 | 64 | @Schema(description = "订单优惠(总)", required = true, example = "100") |
| 68 | 65 | private Integer discountPrice; | ... | ... |
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.*; |
| 4 | 4 | |
| 5 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | 6 | |
| 7 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressCreateReqVO; | |
| 8 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressExcelVO; | |
| 9 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressRespVO; | |
| 10 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressUpdateReqVO; | |
| 7 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressCreateReqVO; | |
| 8 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressExcelVO; | |
| 9 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressRespVO; | |
| 10 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressUpdateReqVO; | |
| 11 | 11 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; |
| 12 | 12 | import org.mapstruct.Mapper; |
| 13 | 13 | import org.mapstruct.factory.Mappers; |
| ... | ... | @@ -16,7 +16,7 @@ import org.mapstruct.factory.Mappers; |
| 16 | 16 | /** |
| 17 | 17 | * 快递公司 Convert |
| 18 | 18 | * |
| 19 | - * @author 芋道源码 | |
| 19 | + * @author jason | |
| 20 | 20 | */ |
| 21 | 21 | @Mapper |
| 22 | 22 | public interface DeliveryExpressConvert { | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.convert.delivery; |
| 2 | 2 | |
| 3 | -import java.util.*; | |
| 4 | - | |
| 5 | -import cn.hutool.core.collection.CollUtil; | |
| 6 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | - | |
| 8 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.*; | |
| 4 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 5 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.*; | |
| 9 | 6 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO; |
| 10 | 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; |
| 11 | 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateFreeDO; |
| 12 | 9 | import org.mapstruct.Mapper; |
| 13 | 10 | import org.mapstruct.factory.Mappers; |
| 14 | 11 | |
| 12 | +import java.util.List; | |
| 13 | + | |
| 15 | 14 | /** |
| 16 | 15 | * 快递运费模板 Convert |
| 17 | 16 | * |
| 18 | - * @author 芋道源码 | |
| 17 | + * @author jason | |
| 19 | 18 | */ |
| 20 | 19 | @Mapper |
| 21 | 20 | public interface DeliveryExpressTemplateConvert { |
| 22 | 21 | |
| 23 | 22 | DeliveryExpressTemplateConvert INSTANCE = Mappers.getMapper(DeliveryExpressTemplateConvert.class); |
| 24 | 23 | |
| 24 | + // ========== Template ========== | |
| 25 | + | |
| 25 | 26 | DeliveryExpressTemplateDO convert(DeliveryExpressTemplateCreateReqVO bean); |
| 26 | 27 | |
| 27 | 28 | DeliveryExpressTemplateDO convert(DeliveryExpressTemplateUpdateReqVO bean); |
| ... | ... | @@ -34,12 +35,27 @@ public interface DeliveryExpressTemplateConvert { |
| 34 | 35 | |
| 35 | 36 | PageResult<DeliveryExpressTemplateSimpleRespVO> convertPage(PageResult<DeliveryExpressTemplateDO> page); |
| 36 | 37 | |
| 37 | - List<DeliveryExpressTemplateExcelVO> convertList02(List<DeliveryExpressTemplateDO> list); | |
| 38 | + default DeliveryExpressTemplateRespVO convert(DeliveryExpressTemplateDO bean, | |
| 39 | + List<DeliveryExpressTemplateChargeDO> chargeList, | |
| 40 | + List<DeliveryExpressTemplateFreeDO> freeList){ | |
| 41 | + DeliveryExpressTemplateRespVO respVO = convert2(bean); | |
| 42 | + respVO.setTemplateCharge(convertTemplateChargeList(chargeList)); | |
| 43 | + respVO.setTemplateFree(convertTemplateFreeList(freeList)); | |
| 44 | + return respVO; | |
| 45 | + } | |
| 46 | + | |
| 47 | + // ========== Template Charge ========== | |
| 38 | 48 | |
| 39 | 49 | DeliveryExpressTemplateChargeDO convertTemplateCharge(Long templateId, Integer chargeMode, ExpressTemplateChargeBaseVO vo); |
| 40 | 50 | |
| 41 | 51 | DeliveryExpressTemplateChargeDO convertTemplateCharge(ExpressTemplateChargeUpdateVO vo); |
| 42 | 52 | |
| 53 | + default List<DeliveryExpressTemplateChargeDO> convertTemplateChargeList(Long templateId, Integer chargeMode, List<ExpressTemplateChargeBaseVO> list) { | |
| 54 | + return CollectionUtils.convertList(list, vo -> convertTemplateCharge(templateId, chargeMode, vo)); | |
| 55 | + } | |
| 56 | + | |
| 57 | + // ========== Template Free ========== | |
| 58 | + | |
| 43 | 59 | DeliveryExpressTemplateFreeDO convertTemplateFree(Long templateId, ExpressTemplateFreeBaseVO vo); |
| 44 | 60 | |
| 45 | 61 | DeliveryExpressTemplateFreeDO convertTemplateFree(ExpressTemplateFreeUpdateVO vo); |
| ... | ... | @@ -48,36 +64,8 @@ public interface DeliveryExpressTemplateConvert { |
| 48 | 64 | |
| 49 | 65 | List<ExpressTemplateFreeBaseVO> convertTemplateFreeList(List<DeliveryExpressTemplateFreeDO> list); |
| 50 | 66 | |
| 51 | - default List<DeliveryExpressTemplateChargeDO> convertTemplateChargeList(Long templateId, Integer chargeMode, List<ExpressTemplateChargeBaseVO> list){ | |
| 52 | - if(CollUtil.isEmpty(list)){ | |
| 53 | - return Collections.emptyList(); | |
| 54 | - } | |
| 55 | - List<DeliveryExpressTemplateChargeDO> templateChargeList = new ArrayList<>( list.size() ); | |
| 56 | - for (ExpressTemplateChargeBaseVO item : list) { | |
| 57 | - templateChargeList.add(convertTemplateCharge(templateId, chargeMode, item)); | |
| 58 | - } | |
| 59 | - return templateChargeList; | |
| 60 | - } | |
| 61 | - | |
| 62 | - | |
| 63 | - | |
| 64 | - default List<DeliveryExpressTemplateFreeDO> convertTemplateFreeList(Long templateId, List<ExpressTemplateFreeBaseVO> list) { | |
| 65 | - if (CollUtil.isEmpty(list)) { | |
| 66 | - return Collections.emptyList(); | |
| 67 | - } | |
| 68 | - List<DeliveryExpressTemplateFreeDO> templateFreeList = new ArrayList<>(list.size()); | |
| 69 | - for (ExpressTemplateFreeBaseVO item : list) { | |
| 70 | - templateFreeList.add(convertTemplateFree(templateId, item)); | |
| 71 | - } | |
| 72 | - return templateFreeList; | |
| 67 | + default List<DeliveryExpressTemplateFreeDO> convertTemplateFreeList(Long templateId, List<ExpressTemplateFreeBaseVO> list) { | |
| 68 | + return CollectionUtils.convertList(list, vo -> convertTemplateFree(templateId, vo)); | |
| 73 | 69 | } |
| 74 | 70 | |
| 75 | - default DeliveryExpressTemplateRespVO convert(DeliveryExpressTemplateDO bean, | |
| 76 | - List<DeliveryExpressTemplateChargeDO> chargeList, | |
| 77 | - List<DeliveryExpressTemplateFreeDO> freeList){ | |
| 78 | - DeliveryExpressTemplateRespVO respVO = convert2(bean); | |
| 79 | - respVO.setTemplateCharge(convertTemplateChargeList(chargeList)); | |
| 80 | - respVO.setTemplateFree(convertTemplateFreeList(freeList)); | |
| 81 | - return respVO; | |
| 82 | - } | |
| 83 | 71 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/delivery/DeliveryExpressTemplateChargeDO.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.dal.dataobject.delivery; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.type.IntegerListTypeHandler; | |
| 4 | 5 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| 6 | +import com.baomidou.mybatisplus.annotation.TableField; | |
| 5 | 7 | import com.baomidou.mybatisplus.annotation.TableId; |
| 6 | 8 | import com.baomidou.mybatisplus.annotation.TableName; |
| 7 | 9 | import lombok.Data; |
| 8 | 10 | |
| 11 | +import java.util.List; | |
| 12 | + | |
| 9 | 13 | /** |
| 10 | 14 | * 快递运费模板计费配置 DO |
| 11 | 15 | * |
| 12 | 16 | * @author jason |
| 13 | 17 | */ |
| 14 | -@TableName(value ="trade_delivery_express_template_charge") | |
| 18 | +@TableName(value ="trade_delivery_express_template_charge", autoResultMap = true) | |
| 15 | 19 | @KeySequence("trade_delivery_express_template_charge_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 |
| 16 | 20 | @Data |
| 17 | 21 | public class DeliveryExpressTemplateChargeDO extends BaseDO { |
| ... | ... | @@ -30,9 +34,10 @@ public class DeliveryExpressTemplateChargeDO extends BaseDO { |
| 30 | 34 | private Long templateId; |
| 31 | 35 | |
| 32 | 36 | /** |
| 33 | - * 配送区域 | |
| 37 | + * 配送区域编号列表 | |
| 34 | 38 | */ |
| 35 | - private Integer areaId; | |
| 39 | + @TableField(typeHandler = IntegerListTypeHandler.class) | |
| 40 | + private List<Integer> areaIds; | |
| 36 | 41 | |
| 37 | 42 | /** |
| 38 | 43 | * 配送计费方式 | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/delivery/DeliveryExpressTemplateFreeDO.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.dal.dataobject.delivery; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.type.IntegerListTypeHandler; | |
| 4 | 5 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| 6 | +import com.baomidou.mybatisplus.annotation.TableField; | |
| 5 | 7 | import com.baomidou.mybatisplus.annotation.TableId; |
| 6 | 8 | import com.baomidou.mybatisplus.annotation.TableName; |
| 7 | 9 | import lombok.Data; |
| 8 | 10 | |
| 11 | +import java.util.List; | |
| 12 | + | |
| 9 | 13 | /** |
| 10 | 14 | * 快递运费模板包邮配置 DO |
| 11 | 15 | * |
| 12 | 16 | * @author jason |
| 13 | 17 | */ |
| 14 | -@TableName(value ="trade_delivery_express_template_free") | |
| 18 | +@TableName(value ="trade_delivery_express_template_free", autoResultMap = true) | |
| 15 | 19 | @KeySequence("trade_delivery_express_template_free_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 |
| 16 | 20 | @Data |
| 17 | 21 | public class DeliveryExpressTemplateFreeDO extends BaseDO { |
| ... | ... | @@ -29,10 +33,12 @@ public class DeliveryExpressTemplateFreeDO extends BaseDO { |
| 29 | 33 | */ |
| 30 | 34 | private Long templateId; |
| 31 | 35 | |
| 36 | + | |
| 32 | 37 | /** |
| 33 | - * 包邮区域id | |
| 38 | + * 配送区域编号列表 | |
| 34 | 39 | */ |
| 35 | - private Integer areaId; | |
| 40 | + @TableField(typeHandler = IntegerListTypeHandler.class) | |
| 41 | + private List<Integer> areaIds; | |
| 36 | 42 | |
| 37 | 43 | /** |
| 38 | 44 | * 包邮金额,单位:分 | ... | ... |
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; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.enums.TerminalEnum; |
| 4 | 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 5 | -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO.OrderItem; | |
| 6 | 5 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; |
| 7 | -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum; | |
| 8 | -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum; | |
| 9 | -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderDeliveryStatusEnum; | |
| 10 | -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; | |
| 11 | -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | |
| 6 | +import cn.iocoder.yudao.module.trade.enums.order.*; | |
| 12 | 7 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| 13 | 8 | import com.baomidou.mybatisplus.annotation.TableName; |
| 14 | 9 | import lombok.*; |
| ... | ... | @@ -134,25 +129,15 @@ public class TradeOrderDO extends BaseDO { |
| 134 | 129 | private String payChannelCode; |
| 135 | 130 | |
| 136 | 131 | /** |
| 137 | - * 商品原价(总),单位:分 | |
| 132 | + * 商品原价,单位:分 | |
| 138 | 133 | * |
| 139 | 134 | * totalPrice = {@link TradeOrderItemDO#getPrice()} * {@link TradeOrderItemDO#getCount()} 求和 |
| 140 | 135 | * |
| 141 | 136 | * 对应 taobao 的 trade.total_fee 字段 |
| 142 | 137 | */ |
| 143 | 138 | private Integer totalPrice; |
| 144 | - // TODO 芋艿:是不是要删除这个字段? | |
| 145 | 139 | /** |
| 146 | - * 订单原价(总),单位:分 | |
| 147 | - * | |
| 148 | - * 1. orderPrice = {@link OrderItem#getPayPrice()} 求和 | |
| 149 | - * 2. orderPrice = {@link #totalPrice} - 商品级优惠 | |
| 150 | - */ | |
| 151 | - private Integer orderPrice; | |
| 152 | - /** | |
| 153 | - * 订单优惠(总),单位:分 | |
| 154 | - * | |
| 155 | - * 订单级优惠:对主订单的优惠,常见如:订单满 200 元减 10 元;订单满 80 包邮。 | |
| 140 | + * 优惠金额,单位:分 | |
| 156 | 141 | * |
| 157 | 142 | * 对应 taobao 的 order.discount_fee 字段 |
| 158 | 143 | */ |
| ... | ... | @@ -162,7 +147,7 @@ public class TradeOrderDO extends BaseDO { |
| 162 | 147 | */ |
| 163 | 148 | private Integer deliveryPrice; |
| 164 | 149 | /** |
| 165 | - * 订单调价(总),单位:分 | |
| 150 | + * 订单调价,单位:分 | |
| 166 | 151 | * |
| 167 | 152 | * 正数,加价;负数,减价 |
| 168 | 153 | */ |
| ... | ... | @@ -170,11 +155,11 @@ public class TradeOrderDO extends BaseDO { |
| 170 | 155 | /** |
| 171 | 156 | * 应付金额(总),单位:分 |
| 172 | 157 | * |
| 173 | - * = {@link OrderItem#getPayPrice()} 求和 | |
| 158 | + * = {@link #totalPrice} | |
| 174 | 159 | * - {@link #couponPrice} |
| 175 | 160 | * - {@link #pointPrice} |
| 176 | - * + {@link #deliveryPrice} | |
| 177 | 161 | * - {@link #discountPrice} |
| 162 | + * + {@link #deliveryPrice} | |
| 178 | 163 | * + {@link #adjustPrice} |
| 179 | 164 | */ |
| 180 | 165 | private Integer payPrice; | ... | ... |
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 { |
| 102 | 102 | */ |
| 103 | 103 | private Integer price; |
| 104 | 104 | /** |
| 105 | - * 商品优惠(总),单位:分 | |
| 106 | - * | |
| 107 | - * 商品级优惠:对单个商品的,常见如:商品原价的 8 折;商品原价的减 50 元 | |
| 105 | + * 优惠金额(总),单位:分 | |
| 108 | 106 | * |
| 109 | 107 | * 对应 taobao 的 order.discount_fee 字段 |
| 110 | 108 | */ |
| 111 | 109 | private Integer discountPrice; |
| 112 | 110 | /** |
| 113 | - * 子订单实付金额(总),不算主订单分摊金额,单位:分 | |
| 111 | + * 运费金额(总),单位:分 | |
| 112 | + */ | |
| 113 | + private Integer deliveryPrice; | |
| 114 | + /** | |
| 115 | + * 订单调价(总),单位:分 | |
| 116 | + * | |
| 117 | + * 正数,加价;负数,减价 | |
| 118 | + */ | |
| 119 | + private Integer adjustPrice; | |
| 120 | + /** | |
| 121 | + * 应付金额(总),单位:分 | |
| 114 | 122 | * |
| 115 | 123 | * = {@link #price} * {@link #count} |
| 124 | + * - {@link #couponPrice} | |
| 125 | + * - {@link #pointPrice} | |
| 116 | 126 | * - {@link #discountPrice} |
| 117 | - * | |
| 118 | - * 对应 taobao 的 order.payment 字段 | |
| 127 | + * + {@link #deliveryPrice} | |
| 128 | + * + {@link #adjustPrice} | |
| 119 | 129 | */ |
| 120 | 130 | private Integer payPrice; |
| 121 | 131 | |
| 132 | + // ========== 营销基本信息 ========== | |
| 133 | + | |
| 122 | 134 | /** |
| 123 | - * 子订单分摊金额(总),单位:分 | |
| 124 | - * 需要分摊 {@link TradeOrderDO#getDiscountPrice()}、{@link TradeOrderDO#getCouponPrice()}、{@link TradeOrderDO#getPointPrice()} | |
| 135 | + * 优惠劵减免金额,单位:分 | |
| 125 | 136 | * |
| 126 | - * 对应 taobao 的 order.part_mjz_discount 字段 | |
| 127 | - * 淘宝说明:子订单分摊优惠基础逻辑:一般正常优惠券和满减优惠按照子订单的金额进行分摊,特殊情况如果优惠券是指定商品使用的,只会分摊到对应商品子订单上不分摊。 | |
| 137 | + * 对应 taobao 的 trade.coupon_fee 字段 | |
| 128 | 138 | */ |
| 129 | - private Integer orderPartPrice; | |
| 139 | + private Integer couponPrice; | |
| 130 | 140 | /** |
| 131 | - * 分摊后子订单实付金额(总),单位:分 | |
| 132 | - * | |
| 133 | - * = {@link #payPrice} | |
| 134 | - * - {@link #orderPartPrice} | |
| 141 | + * 积分抵扣的金额,单位:分 | |
| 135 | 142 | * |
| 136 | - * 对应 taobao 的 divide_order_fee 字段 | |
| 143 | + * 对应 taobao 的 trade.point_fee 字段 | |
| 137 | 144 | */ |
| 138 | - private Integer orderDividePrice; | |
| 139 | - | |
| 140 | - // ========== 营销基本信息 ========== | |
| 141 | - | |
| 142 | - // TODO 芋艿:在捉摸一下 | |
| 145 | + private Integer pointPrice; | |
| 143 | 146 | |
| 144 | 147 | // ========== 售后基本信息 ========== |
| 145 | 148 | /** | ... | ... |
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; |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 6 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressExportReqVO; | |
| 7 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressPageReqVO; | |
| 6 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressExportReqVO; | |
| 7 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressPageReqVO; | |
| 8 | 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; |
| 9 | 9 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| 10 | 10 | import org.apache.ibatis.annotations.Mapper; | ... | ... |
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; |
| 14 | 14 | @Mapper |
| 15 | 15 | public interface DeliveryExpressTemplateChargeMapper extends BaseMapperX<DeliveryExpressTemplateChargeDO> { |
| 16 | 16 | |
| 17 | - @Repository | |
| 18 | - class BatchInsertMapper extends ServiceImpl<DeliveryExpressTemplateChargeMapper, DeliveryExpressTemplateChargeDO> { | |
| 19 | - } | |
| 20 | - | |
| 21 | 17 | default List<DeliveryExpressTemplateChargeDO> selectListByTemplateId(Long templateId){ |
| 22 | 18 | return selectList(new LambdaQueryWrapper<DeliveryExpressTemplateChargeDO>() |
| 23 | 19 | .eq(DeliveryExpressTemplateChargeDO::getTemplateId, templateId)); | ... | ... |
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; |
| 14 | 14 | @Mapper |
| 15 | 15 | public interface DeliveryExpressTemplateFreeMapper extends BaseMapperX<DeliveryExpressTemplateFreeDO> { |
| 16 | 16 | |
| 17 | - @Repository | |
| 18 | - class BatchInsertMapper extends ServiceImpl<DeliveryExpressTemplateFreeMapper, DeliveryExpressTemplateFreeDO> { | |
| 19 | - } | |
| 20 | - | |
| 21 | 17 | default List<DeliveryExpressTemplateFreeDO> selectListByTemplateId(Long templateId) { |
| 22 | 18 | return selectList(new LambdaQueryWrapper<DeliveryExpressTemplateFreeDO>() |
| 23 | 19 | .eq(DeliveryExpressTemplateFreeDO::getTemplateId, templateId)); | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/delivery/DeliveryExpressTemplateMapper.java
| ... | ... | @@ -3,17 +3,11 @@ package cn.iocoder.yudao.module.trade.dal.mysql.delivery; |
| 3 | 3 | |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | 5 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 6 | - | |
| 7 | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 8 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressTemplateExportReqVO; | |
| 9 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressTemplatePageReqVO; | |
| 10 | -import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; | |
| 7 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplatePageReqVO; | |
| 11 | 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; |
| 12 | -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |
| 13 | 9 | import org.apache.ibatis.annotations.Mapper; |
| 14 | 10 | |
| 15 | -import java.util.List; | |
| 16 | - | |
| 17 | 11 | @Mapper |
| 18 | 12 | public interface DeliveryExpressTemplateMapper extends BaseMapperX<DeliveryExpressTemplateDO> { |
| 19 | 13 | |
| ... | ... | @@ -25,16 +19,8 @@ public interface DeliveryExpressTemplateMapper extends BaseMapperX<DeliveryExpre |
| 25 | 19 | .orderByAsc(DeliveryExpressTemplateDO::getSort)); |
| 26 | 20 | } |
| 27 | 21 | |
| 28 | - default List<DeliveryExpressTemplateDO> selectList(DeliveryExpressTemplateExportReqVO reqVO) { | |
| 29 | - return selectList(new LambdaQueryWrapperX<DeliveryExpressTemplateDO>() | |
| 30 | - .likeIfPresent(DeliveryExpressTemplateDO::getName, reqVO.getName()) | |
| 31 | - .eqIfPresent(DeliveryExpressTemplateDO::getChargeMode, reqVO.getChargeMode()) | |
| 32 | - .betweenIfPresent(DeliveryExpressTemplateDO::getCreateTime, reqVO.getCreateTime()) | |
| 33 | - .orderByAsc(DeliveryExpressTemplateDO::getSort)); | |
| 34 | - } | |
| 35 | - | |
| 36 | 22 | default DeliveryExpressTemplateDO selectByName(String name) { |
| 37 | - return selectOne(new LambdaQueryWrapper<DeliveryExpressTemplateDO>() | |
| 38 | - .eq(DeliveryExpressTemplateDO::getName, name)); | |
| 23 | + return selectOne(DeliveryExpressTemplateDO::getName,name); | |
| 39 | 24 | } |
| 25 | + | |
| 40 | 26 | } | ... | ... |
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 { |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | 99 | // 申请的退款金额,不能超过商品的价格 |
| 100 | - if (createReqVO.getRefundPrice() > orderItem.getOrderDividePrice()) { | |
| 100 | + if (createReqVO.getRefundPrice() > orderItem.getPayPrice()) { | |
| 101 | 101 | throw exception(AFTER_SALE_CREATE_FAIL_REFUND_PRICE_ERROR); |
| 102 | 102 | } |
| 103 | 103 | ... | ... |
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.*; |
| 4 | 4 | import javax.validation.*; |
| 5 | 5 | |
| 6 | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressCreateReqVO; | |
| 8 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressExportReqVO; | |
| 9 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressPageReqVO; | |
| 10 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressUpdateReqVO; | |
| 7 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressCreateReqVO; | |
| 8 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressExportReqVO; | |
| 9 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressPageReqVO; | |
| 10 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressUpdateReqVO; | |
| 11 | 11 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; |
| 12 | 12 | |
| 13 | 13 | /** | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.service.delivery; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressCreateReqVO; | |
| 5 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressExportReqVO; | |
| 6 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressPageReqVO; | |
| 7 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.DeliveryExpressUpdateReqVO; | |
| 4 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressCreateReqVO; | |
| 5 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressExportReqVO; | |
| 6 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressPageReqVO; | |
| 7 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressUpdateReqVO; | |
| 8 | 8 | import cn.iocoder.yudao.module.trade.convert.delivery.DeliveryExpressConvert; |
| 9 | 9 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; |
| 10 | 10 | import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressMapper; | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateService.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.service.delivery; |
| 2 | 2 | |
| 3 | -import java.util.*; | |
| 4 | -import javax.validation.*; | |
| 5 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.*; | |
| 4 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateCreateReqVO; | |
| 5 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplatePageReqVO; | |
| 6 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateRespVO; | |
| 7 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateUpdateReqVO; | |
| 7 | 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; |
| 8 | 9 | |
| 10 | +import javax.validation.Valid; | |
| 11 | +import java.util.Collection; | |
| 12 | +import java.util.List; | |
| 13 | + | |
| 9 | 14 | /** |
| 10 | 15 | * 快递运费模板 Service 接口 |
| 11 | 16 | * |
| ... | ... | @@ -58,13 +63,4 @@ public interface DeliveryExpressTemplateService { |
| 58 | 63 | * @return 快递运费模板分页 |
| 59 | 64 | */ |
| 60 | 65 | PageResult<DeliveryExpressTemplateDO> getDeliveryExpressTemplatePage(DeliveryExpressTemplatePageReqVO pageReqVO); |
| 61 | - | |
| 62 | - /** | |
| 63 | - * 获得快递运费模板列表, 用于 Excel 导出 | |
| 64 | - * | |
| 65 | - * @param exportReqVO 查询条件 | |
| 66 | - * @return 快递运费模板列表 | |
| 67 | - */ | |
| 68 | - List<DeliveryExpressTemplateDO> getDeliveryExpressTemplateList(DeliveryExpressTemplateExportReqVO exportReqVO); | |
| 69 | - | |
| 70 | 66 | } | ... | ... |
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; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 6 | -import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.*; | |
| 5 | +import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.*; | |
| 7 | 6 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO; |
| 8 | 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; |
| 9 | 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateFreeDO; |
| ... | ... | @@ -18,8 +17,10 @@ import javax.annotation.Resource; |
| 18 | 17 | import java.util.*; |
| 19 | 18 | |
| 20 | 19 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 20 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | |
| 21 | 21 | import static cn.iocoder.yudao.module.trade.convert.delivery.DeliveryExpressTemplateConvert.INSTANCE; |
| 22 | -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; | |
| 22 | +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_TEMPLATE_NAME_DUPLICATE; | |
| 23 | +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_TEMPLATE_NOT_EXISTS; | |
| 23 | 24 | |
| 24 | 25 | /** |
| 25 | 26 | * 快递运费模板 Service 实现类 |
| ... | ... | @@ -36,28 +37,25 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla |
| 36 | 37 | private DeliveryExpressTemplateChargeMapper expressTemplateChargeMapper; |
| 37 | 38 | @Resource |
| 38 | 39 | private DeliveryExpressTemplateFreeMapper expressTemplateFreeMapper; |
| 39 | - @Resource | |
| 40 | - private DeliveryExpressTemplateChargeMapper.BatchInsertMapper expressTemplateChargeBatchMapper; | |
| 41 | - @Resource | |
| 42 | - private DeliveryExpressTemplateFreeMapper.BatchInsertMapper expressTemplateFreeBatchMapper; | |
| 43 | 40 | |
| 44 | 41 | @Override |
| 45 | 42 | @Transactional(rollbackFor = Exception.class) |
| 46 | 43 | public Long createDeliveryExpressTemplate(DeliveryExpressTemplateCreateReqVO createReqVO) { |
| 47 | - //校验模板名是否唯一 | |
| 44 | + // 校验模板名是否唯一 | |
| 48 | 45 | validateTemplateNameUnique(createReqVO.getName(), null); |
| 46 | + | |
| 49 | 47 | // 插入 |
| 50 | 48 | DeliveryExpressTemplateDO deliveryExpressTemplate = INSTANCE.convert(createReqVO); |
| 51 | 49 | expressTemplateMapper.insert(deliveryExpressTemplate); |
| 52 | - //插入运费模板计费表 | |
| 53 | - if(CollUtil.isNotEmpty(createReqVO.getTemplateCharge())) { | |
| 54 | - expressTemplateChargeBatchMapper.saveBatch( | |
| 55 | - INSTANCE.convertTemplateChargeList(deliveryExpressTemplate.getId(), createReqVO.getChargeMode(), createReqVO.getTemplateCharge()) | |
| 50 | + // 插入运费模板计费表 | |
| 51 | + if (CollUtil.isNotEmpty(createReqVO.getTemplateCharge())) { | |
| 52 | + expressTemplateChargeMapper.insertBatch( | |
| 53 | + INSTANCE.convertTemplateChargeList(deliveryExpressTemplate.getId(), createReqVO.getChargeMode(), createReqVO.getTemplateCharge()) | |
| 56 | 54 | ); |
| 57 | 55 | } |
| 58 | - //插入运费模板包邮表 | |
| 59 | - if(CollUtil.isNotEmpty(createReqVO.getTemplateFree())) { | |
| 60 | - expressTemplateFreeBatchMapper.saveBatch( | |
| 56 | + // 插入运费模板包邮表 | |
| 57 | + if (CollUtil.isNotEmpty(createReqVO.getTemplateFree())) { | |
| 58 | + expressTemplateFreeMapper.insertBatch( | |
| 61 | 59 | INSTANCE.convertTemplateFreeList(deliveryExpressTemplate.getId(), createReqVO.getTemplateFree()) |
| 62 | 60 | ); |
| 63 | 61 | } |
| ... | ... | @@ -69,80 +67,78 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla |
| 69 | 67 | public void updateDeliveryExpressTemplate(DeliveryExpressTemplateUpdateReqVO updateReqVO) { |
| 70 | 68 | // 校验存在 |
| 71 | 69 | validateDeliveryExpressTemplateExists(updateReqVO.getId()); |
| 72 | - //校验模板名是否唯一 | |
| 70 | + // 校验模板名是否唯一 | |
| 73 | 71 | validateTemplateNameUnique(updateReqVO.getName(), updateReqVO.getId()); |
| 74 | 72 | |
| 75 | - //更新运费从表 | |
| 73 | + // 更新运费从表 | |
| 76 | 74 | updateExpressTemplateCharge(updateReqVO); |
| 77 | - //更新包邮从表 | |
| 75 | + // 更新包邮从表 | |
| 78 | 76 | updateExpressTemplateFree(updateReqVO); |
| 79 | - //更新模板主表 | |
| 77 | + // 更新模板主表 | |
| 80 | 78 | DeliveryExpressTemplateDO updateObj = INSTANCE.convert(updateReqVO); |
| 81 | 79 | expressTemplateMapper.updateById(updateObj); |
| 82 | 80 | } |
| 83 | 81 | |
| 84 | 82 | private void updateExpressTemplateFree(DeliveryExpressTemplateUpdateReqVO updateReqVO) { |
| 83 | + // 1.1 获得新增/修改的区域列表 | |
| 85 | 84 | List<DeliveryExpressTemplateFreeDO> oldFreeList = expressTemplateFreeMapper.selectListByTemplateId(updateReqVO.getId()); |
| 86 | 85 | List<ExpressTemplateFreeUpdateVO> newFreeList = updateReqVO.getTemplateFree(); |
| 87 | - //新增包邮区域列表 | |
| 88 | - List<DeliveryExpressTemplateFreeDO> addFreeList = new ArrayList<>(newFreeList.size()); | |
| 89 | - //更新包邮区域列表 | |
| 90 | - List<DeliveryExpressTemplateFreeDO> updateFreeList = new ArrayList<>(newFreeList.size()); | |
| 86 | + List<DeliveryExpressTemplateFreeDO> addFreeList = new ArrayList<>(newFreeList.size()); // 新增包邮区域列表 | |
| 87 | + List<DeliveryExpressTemplateFreeDO> updateFreeList = new ArrayList<>(newFreeList.size()); // 更新包邮区域列表 | |
| 91 | 88 | for (ExpressTemplateFreeUpdateVO item : newFreeList) { |
| 92 | 89 | if (Objects.nonNull(item.getId())) { |
| 93 | 90 | updateFreeList.add(INSTANCE.convertTemplateFree(item)); |
| 94 | - }else{ | |
| 91 | + } else { | |
| 95 | 92 | item.setTemplateId(updateReqVO.getId()); |
| 96 | 93 | addFreeList.add(INSTANCE.convertTemplateFree(item)); |
| 97 | 94 | } |
| 98 | 95 | } |
| 99 | - //删除的包邮区域id | |
| 100 | - Set<Long> deleteFreeIds = CollectionUtils.convertSet(oldFreeList, DeliveryExpressTemplateFreeDO::getId); | |
| 101 | - deleteFreeIds.removeAll(CollectionUtils.convertSet(updateFreeList, DeliveryExpressTemplateFreeDO::getId)); | |
| 102 | - //新增 | |
| 96 | + // 1.2 新增 | |
| 103 | 97 | if (CollUtil.isNotEmpty(addFreeList)) { |
| 104 | - expressTemplateFreeBatchMapper.saveBatch(addFreeList); | |
| 98 | + expressTemplateFreeMapper.insertBatch(addFreeList); | |
| 105 | 99 | } |
| 106 | - //修改 | |
| 100 | + // 1.3 修改 | |
| 107 | 101 | if (CollUtil.isNotEmpty(updateFreeList)) { |
| 108 | - expressTemplateFreeBatchMapper.saveOrUpdateBatch(updateFreeList); | |
| 102 | + expressTemplateFreeMapper.updateBatch(updateFreeList); | |
| 109 | 103 | } |
| 110 | - //删除 | |
| 104 | + | |
| 105 | + // 2. 删除 | |
| 106 | + Set<Long> deleteFreeIds = convertSet(oldFreeList, DeliveryExpressTemplateFreeDO::getId); | |
| 107 | + deleteFreeIds.removeAll(convertSet(updateFreeList, DeliveryExpressTemplateFreeDO::getId)); | |
| 111 | 108 | if (CollUtil.isNotEmpty(deleteFreeIds)) { |
| 112 | 109 | expressTemplateFreeMapper.deleteBatchIds(deleteFreeIds); |
| 113 | 110 | } |
| 114 | 111 | } |
| 115 | 112 | |
| 116 | 113 | private void updateExpressTemplateCharge(DeliveryExpressTemplateUpdateReqVO updateReqVO) { |
| 114 | + // 1.1 获得新增/修改的区域列表 | |
| 117 | 115 | List<DeliveryExpressTemplateChargeDO> oldChargeList = expressTemplateChargeMapper.selectListByTemplateId(updateReqVO.getId()); |
| 118 | 116 | List<ExpressTemplateChargeUpdateVO> newChargeList = updateReqVO.getTemplateCharge(); |
| 119 | - //新增运费区域列表 | |
| 120 | - List<DeliveryExpressTemplateChargeDO> addList = new ArrayList<>(newChargeList.size()); | |
| 121 | - //更新运费区域列表 | |
| 122 | - List<DeliveryExpressTemplateChargeDO> updateList = new ArrayList<>(newChargeList.size()); | |
| 117 | + List<DeliveryExpressTemplateChargeDO> addList = new ArrayList<>(newChargeList.size()); // 新增运费区域列表 | |
| 118 | + List<DeliveryExpressTemplateChargeDO> updateList = new ArrayList<>(newChargeList.size()); // 更新运费区域列表 | |
| 123 | 119 | for (ExpressTemplateChargeUpdateVO item : newChargeList) { |
| 124 | - if (Objects.nonNull(item.getId())) { | |
| 125 | - //计费模式以主表为准 | |
| 120 | + if (item.getId() != null) { | |
| 121 | + // 计费模式以主表为准 | |
| 126 | 122 | item.setChargeMode(updateReqVO.getChargeMode()); |
| 127 | 123 | updateList.add(INSTANCE.convertTemplateCharge(item)); |
| 128 | - }else{ | |
| 124 | + } else { | |
| 129 | 125 | item.setTemplateId(updateReqVO.getId()); |
| 130 | 126 | item.setChargeMode(updateReqVO.getChargeMode()); |
| 131 | 127 | addList.add(INSTANCE.convertTemplateCharge(item)); |
| 132 | 128 | } |
| 133 | 129 | } |
| 134 | - //删除的运费区域id | |
| 135 | - Set<Long> deleteChargeIds = CollectionUtils.convertSet(oldChargeList, DeliveryExpressTemplateChargeDO::getId); | |
| 136 | - deleteChargeIds.removeAll(CollectionUtils.convertSet(updateList, DeliveryExpressTemplateChargeDO::getId)); | |
| 137 | - //新增 | |
| 130 | + // 1.2 新增 | |
| 138 | 131 | if (CollUtil.isNotEmpty(addList)) { |
| 139 | - expressTemplateChargeBatchMapper.saveBatch(addList); | |
| 132 | + expressTemplateChargeMapper.insertBatch(addList); | |
| 140 | 133 | } |
| 141 | - //修改 | |
| 134 | + // 1.3 修改 | |
| 142 | 135 | if (CollUtil.isNotEmpty(updateList)) { |
| 143 | - expressTemplateChargeBatchMapper.saveOrUpdateBatch(updateList); | |
| 136 | + expressTemplateChargeMapper.updateBatch(updateList); | |
| 144 | 137 | } |
| 145 | - //删除 | |
| 138 | + | |
| 139 | + // 2. 删除 | |
| 140 | + Set<Long> deleteChargeIds = convertSet(oldChargeList, DeliveryExpressTemplateChargeDO::getId); | |
| 141 | + deleteChargeIds.removeAll(convertSet(updateList, DeliveryExpressTemplateChargeDO::getId)); | |
| 146 | 142 | if (CollUtil.isNotEmpty(deleteChargeIds)) { |
| 147 | 143 | expressTemplateChargeMapper.deleteBatchIds(deleteChargeIds); |
| 148 | 144 | } |
| ... | ... | @@ -153,6 +149,7 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla |
| 153 | 149 | public void deleteDeliveryExpressTemplate(Long id) { |
| 154 | 150 | // 校验存在 |
| 155 | 151 | validateDeliveryExpressTemplateExists(id); |
| 152 | + | |
| 156 | 153 | // 删除主表 |
| 157 | 154 | expressTemplateMapper.deleteById(id); |
| 158 | 155 | // 删除运费从表 |
| ... | ... | @@ -163,8 +160,9 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla |
| 163 | 160 | |
| 164 | 161 | /** |
| 165 | 162 | * 校验运费模板名是否唯一 |
| 163 | + * | |
| 166 | 164 | * @param name 模板名称 |
| 167 | - * @param id 运费模板编号, 可以为null | |
| 165 | + * @param id 运费模板编号,可以为 null | |
| 168 | 166 | */ |
| 169 | 167 | private void validateTemplateNameUnique(String name, Long id) { |
| 170 | 168 | DeliveryExpressTemplateDO template = expressTemplateMapper.selectByName(name); |
| ... | ... | @@ -191,7 +189,7 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla |
| 191 | 189 | List<DeliveryExpressTemplateChargeDO> chargeList = expressTemplateChargeMapper.selectListByTemplateId(id); |
| 192 | 190 | List<DeliveryExpressTemplateFreeDO> freeList = expressTemplateFreeMapper.selectListByTemplateId(id); |
| 193 | 191 | DeliveryExpressTemplateDO template = expressTemplateMapper.selectById(id); |
| 194 | - return INSTANCE.convert(template, chargeList,freeList); | |
| 192 | + return INSTANCE.convert(template, chargeList, freeList); | |
| 195 | 193 | } |
| 196 | 194 | |
| 197 | 195 | @Override |
| ... | ... | @@ -204,9 +202,4 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla |
| 204 | 202 | return expressTemplateMapper.selectPage(pageReqVO); |
| 205 | 203 | } |
| 206 | 204 | |
| 207 | - @Override | |
| 208 | - public List<DeliveryExpressTemplateDO> getDeliveryExpressTemplateList(DeliveryExpressTemplateExportReqVO exportReqVO) { | |
| 209 | - return expressTemplateMapper.selectList(exportReqVO); | |
| 210 | - } | |
| 211 | - | |
| 212 | 205 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.price; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | |
| 4 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * 价格计算 Service 接口 | |
| 8 | + * | |
| 9 | + * @author 芋道源码 | |
| 10 | + */ | |
| 11 | +public interface TradePriceService { | |
| 12 | + | |
| 13 | + /** | |
| 14 | + * 价格计算 | |
| 15 | + * | |
| 16 | + * @param calculateReqDTO 计算信息 | |
| 17 | + * @return 计算结果 | |
| 18 | + */ | |
| 19 | + TradePriceCalculateRespBO calculatePrice(TradePriceCalculateReqBO calculateReqDTO); | |
| 20 | + | |
| 21 | +} | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.price; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | |
| 4 | +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | |
| 5 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | |
| 6 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | |
| 7 | +import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculator; | |
| 8 | +import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper; | |
| 9 | +import lombok.extern.slf4j.Slf4j; | |
| 10 | +import org.springframework.stereotype.Service; | |
| 11 | + | |
| 12 | +import javax.annotation.Resource; | |
| 13 | +import java.util.List; | |
| 14 | +import java.util.Map; | |
| 15 | + | |
| 16 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 17 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | |
| 18 | +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; | |
| 19 | +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_STOCK_NOT_ENOUGH; | |
| 20 | +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.PRICE_CALCULATE_PAY_PRICE_ILLEGAL; | |
| 21 | + | |
| 22 | +/** | |
| 23 | + * 价格计算 Service 实现类 | |
| 24 | + * | |
| 25 | + * @author 芋道源码 | |
| 26 | + */ | |
| 27 | +@Service | |
| 28 | +@Slf4j | |
| 29 | +public class TradePriceServiceImpl implements TradePriceService { | |
| 30 | + | |
| 31 | + @Resource | |
| 32 | + private ProductSkuApi productSkuApi; | |
| 33 | + @Resource | |
| 34 | + private List<TradePriceCalculator> priceCalculators; | |
| 35 | + | |
| 36 | + @Override | |
| 37 | + public TradePriceCalculateRespBO calculatePrice(TradePriceCalculateReqBO calculateReqBO) { | |
| 38 | + // 1. 获得商品 SKU 数组 | |
| 39 | + List<ProductSkuRespDTO> skuList = checkSkus(calculateReqBO); | |
| 40 | + | |
| 41 | + // 2.1 计算价格 | |
| 42 | + TradePriceCalculateRespBO calculateRespBO = TradePriceCalculatorHelper | |
| 43 | + .buildCalculateResp(calculateReqBO, skuList); | |
| 44 | + priceCalculators.forEach(calculator -> calculator.calculate(calculateReqBO, calculateRespBO)); | |
| 45 | + // 2.2 如果最终支付金额小于等于 0,则抛出业务异常 | |
| 46 | + if (calculateRespBO.getPrice().getPayPrice() <= 0) { | |
| 47 | + log.error("[calculatePrice][价格计算不正确,请求 calculateReqDTO({}),结果 priceCalculate({})]", | |
| 48 | + calculateReqBO, calculateRespBO); | |
| 49 | + throw exception(PRICE_CALCULATE_PAY_PRICE_ILLEGAL); | |
| 50 | + } | |
| 51 | + return calculateRespBO; | |
| 52 | + } | |
| 53 | + | |
| 54 | + private List<ProductSkuRespDTO> checkSkus(TradePriceCalculateReqBO reqBO) { | |
| 55 | + // 获得商品 SKU 数组 | |
| 56 | + Map<Long, Integer> skuIdCountMap = convertMap(reqBO.getItems(), | |
| 57 | + TradePriceCalculateReqBO.Item::getSkuId, TradePriceCalculateReqBO.Item::getCount); | |
| 58 | + List<ProductSkuRespDTO> skus = productSkuApi.getSkuList(skuIdCountMap.keySet()); | |
| 59 | + | |
| 60 | + // 校验商品 SKU | |
| 61 | + skus.forEach(sku -> { | |
| 62 | + Integer count = skuIdCountMap.get(sku.getId()); | |
| 63 | + if (count == null) { | |
| 64 | + throw exception(SKU_NOT_EXISTS); | |
| 65 | + } | |
| 66 | + if (count > sku.getStock()) { | |
| 67 | + throw exception(SKU_STOCK_NOT_ENOUGH); | |
| 68 | + } | |
| 69 | + }); | |
| 70 | + return skus; | |
| 71 | + } | |
| 72 | + | |
| 73 | +} | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.price.bo; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | |
| 4 | +import lombok.Data; | |
| 5 | + | |
| 6 | +import javax.validation.Valid; | |
| 7 | +import javax.validation.constraints.Min; | |
| 8 | +import javax.validation.constraints.NotNull; | |
| 9 | +import java.util.List; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 价格计算 Request BO | |
| 13 | + * | |
| 14 | + * @author yudao源码 | |
| 15 | + */ | |
| 16 | +@Data | |
| 17 | +public class TradePriceCalculateReqBO { | |
| 18 | + | |
| 19 | + /** | |
| 20 | + * 订单类型 | |
| 21 | + * | |
| 22 | + * 枚举 {@link TradeOrderTypeEnum} | |
| 23 | + */ | |
| 24 | + private Integer orderType; | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * 用户编号 | |
| 28 | + * | |
| 29 | + * 对应 MemberUserDO 的 id 编号 | |
| 30 | + */ | |
| 31 | + private Long userId; | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 优惠劵编号 | |
| 35 | + * | |
| 36 | + * 对应 CouponDO 的 id 编号 | |
| 37 | + */ | |
| 38 | + private Long couponId; | |
| 39 | + | |
| 40 | + /** | |
| 41 | + * 收货地址编号 | |
| 42 | + * | |
| 43 | + * 对应 MemberAddressDO 的 id 编号 | |
| 44 | + */ | |
| 45 | + private Long addressId; | |
| 46 | + | |
| 47 | + /** | |
| 48 | + * 商品 SKU 数组 | |
| 49 | + */ | |
| 50 | + @NotNull(message = "商品数组不能为空") | |
| 51 | + private List<Item> items; | |
| 52 | + | |
| 53 | + /** | |
| 54 | + * 商品 SKU | |
| 55 | + */ | |
| 56 | + @Data | |
| 57 | + @Valid | |
| 58 | + public static class Item { | |
| 59 | + | |
| 60 | + /** | |
| 61 | + * SKU 编号 | |
| 62 | + */ | |
| 63 | + @NotNull(message = "商品 SKU 编号不能为空") | |
| 64 | + private Long skuId; | |
| 65 | + | |
| 66 | + /** | |
| 67 | + * SKU 数量 | |
| 68 | + */ | |
| 69 | + @NotNull(message = "商品 SKU 数量不能为空") | |
| 70 | + @Min(value = 0L, message = "商品 SKU 数量必须大于等于 0") | |
| 71 | + private Integer count; | |
| 72 | + | |
| 73 | + /** | |
| 74 | + * 购物车项的编号 | |
| 75 | + */ | |
| 76 | + private Long cartId; | |
| 77 | + | |
| 78 | + /** | |
| 79 | + * 是否选中 | |
| 80 | + */ | |
| 81 | + @NotNull(message = "是否选中不能为空") | |
| 82 | + private Boolean selected; | |
| 83 | + | |
| 84 | + } | |
| 85 | + | |
| 86 | +} | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.price.bo; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionLevelEnum; | |
| 4 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | |
| 5 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | |
| 6 | +import lombok.Data; | |
| 7 | + | |
| 8 | +import java.util.List; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * 价格计算 Response BO | |
| 12 | + * | |
| 13 | + * 整体设计,参考 taobao 的技术文档: | |
| 14 | + * 1. <a href="https://developer.alibaba.com/docs/doc.htm?treeId=1&articleId=1029&docType=1">订单管理</a> | |
| 15 | + * 2. <a href="https://open.taobao.com/docV3.htm?docId=108471&docType=1">常用订单金额说明</a> | |
| 16 | + * | |
| 17 | + * @author 芋道源码 | |
| 18 | + */ | |
| 19 | +@Data | |
| 20 | +public class TradePriceCalculateRespBO { | |
| 21 | + | |
| 22 | + /** | |
| 23 | + * 订单类型 | |
| 24 | + * | |
| 25 | + * 枚举 {@link TradeOrderTypeEnum} | |
| 26 | + */ | |
| 27 | + private Integer orderType; | |
| 28 | + | |
| 29 | + /** | |
| 30 | + * 订单价格 | |
| 31 | + */ | |
| 32 | + private Price price; | |
| 33 | + | |
| 34 | + /** | |
| 35 | + * 订单项数组 | |
| 36 | + */ | |
| 37 | + private List<OrderItem> items; | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * 营销活动数组 | |
| 41 | + * | |
| 42 | + * 只对应 {@link Price#items} 商品匹配的活动 | |
| 43 | + */ | |
| 44 | + private List<Promotion> promotions; | |
| 45 | + | |
| 46 | + /** | |
| 47 | + * 优惠劵编号 | |
| 48 | + */ | |
| 49 | + private Long couponId; | |
| 50 | + | |
| 51 | + /** | |
| 52 | + * 订单价格 | |
| 53 | + */ | |
| 54 | + @Data | |
| 55 | + public static class Price { | |
| 56 | + | |
| 57 | + /** | |
| 58 | + * 商品原价(总),单位:分 | |
| 59 | + * | |
| 60 | + * 基于 {@link OrderItem#getPrice()} * {@link OrderItem#getCount()} 求和 | |
| 61 | + * | |
| 62 | + * 对应 taobao 的 trade.total_fee 字段 | |
| 63 | + */ | |
| 64 | + private Integer totalPrice; | |
| 65 | + /** | |
| 66 | + * 订单优惠(总),单位:分 | |
| 67 | + * | |
| 68 | + * 对应 taobao 的 order.discount_fee 字段 | |
| 69 | + */ | |
| 70 | + private Integer discountPrice; | |
| 71 | + /** | |
| 72 | + * 运费金额,单位:分 | |
| 73 | + */ | |
| 74 | + private Integer deliveryPrice; | |
| 75 | + /** | |
| 76 | + * 优惠劵减免金额(总),单位:分 | |
| 77 | + * | |
| 78 | + * 对应 taobao 的 trade.coupon_fee 字段 | |
| 79 | + */ | |
| 80 | + private Integer couponPrice; | |
| 81 | + /** | |
| 82 | + * 积分抵扣的金额,单位:分 | |
| 83 | + * | |
| 84 | + * 对应 taobao 的 trade.point_fee 字段 | |
| 85 | + */ | |
| 86 | + private Integer pointPrice; | |
| 87 | + /** | |
| 88 | + * 最终购买金额(总),单位:分 | |
| 89 | + * | |
| 90 | + * = {@link #totalPrice} | |
| 91 | + * - {@link #couponPrice} | |
| 92 | + * - {@link #pointPrice} | |
| 93 | + * - {@link #discountPrice} | |
| 94 | + * + {@link #deliveryPrice} | |
| 95 | + */ | |
| 96 | + private Integer payPrice; | |
| 97 | + | |
| 98 | + } | |
| 99 | + | |
| 100 | + /** | |
| 101 | + * 订单商品 SKU | |
| 102 | + */ | |
| 103 | + @Data | |
| 104 | + public static class OrderItem { | |
| 105 | + | |
| 106 | + /** | |
| 107 | + * SPU 编号 | |
| 108 | + */ | |
| 109 | + private Long spuId; | |
| 110 | + /** | |
| 111 | + * SKU 编号 | |
| 112 | + */ | |
| 113 | + private Long skuId; | |
| 114 | + /** | |
| 115 | + * 购买数量 | |
| 116 | + */ | |
| 117 | + private Integer count; | |
| 118 | + /** | |
| 119 | + * 购物车项的编号 | |
| 120 | + */ | |
| 121 | + private Long cartId; | |
| 122 | + /** | |
| 123 | + * 是否选中 | |
| 124 | + */ | |
| 125 | + private Boolean selected; | |
| 126 | + | |
| 127 | + /** | |
| 128 | + * 商品原价(单),单位:分 | |
| 129 | + * | |
| 130 | + * 对应 ProductSkuDO 的 price 字段 | |
| 131 | + * 对应 taobao 的 order.price 字段 | |
| 132 | + */ | |
| 133 | + private Integer price; | |
| 134 | + /** | |
| 135 | + * 优惠金额(总),单位:分 | |
| 136 | + * | |
| 137 | + * 对应 taobao 的 order.discount_fee 字段 | |
| 138 | + */ | |
| 139 | + private Integer discountPrice; | |
| 140 | + /** | |
| 141 | + * 运费金额(总),单位:分 | |
| 142 | + */ | |
| 143 | + private Integer deliveryPrice; | |
| 144 | + /** | |
| 145 | + * 优惠劵减免金额,单位:分 | |
| 146 | + * | |
| 147 | + * 对应 taobao 的 trade.coupon_fee 字段 | |
| 148 | + */ | |
| 149 | + private Integer couponPrice; | |
| 150 | + /** | |
| 151 | + * 积分抵扣的金额,单位:分 | |
| 152 | + * | |
| 153 | + * 对应 taobao 的 trade.point_fee 字段 | |
| 154 | + */ | |
| 155 | + private Integer pointPrice; | |
| 156 | + /** | |
| 157 | + * 应付金额(总),单位:分 | |
| 158 | + * | |
| 159 | + * = {@link #price} * {@link #count} | |
| 160 | + * - {@link #couponPrice} | |
| 161 | + * - {@link #pointPrice} | |
| 162 | + * - {@link #discountPrice} | |
| 163 | + * + {@link #deliveryPrice} | |
| 164 | + */ | |
| 165 | + private Integer payPrice; | |
| 166 | + | |
| 167 | + // TODO 芋艿:这里补充下基本信息,简单一点。 | |
| 168 | + | |
| 169 | + } | |
| 170 | + | |
| 171 | + /** | |
| 172 | + * 营销明细 | |
| 173 | + */ | |
| 174 | + @Data | |
| 175 | + public static class Promotion { | |
| 176 | + | |
| 177 | + /** | |
| 178 | + * 营销编号 | |
| 179 | + * | |
| 180 | + * 例如说:营销活动的编号、优惠劵的编号 | |
| 181 | + */ | |
| 182 | + private Long id; | |
| 183 | + /** | |
| 184 | + * 营销名字 | |
| 185 | + */ | |
| 186 | + private String name; | |
| 187 | + /** | |
| 188 | + * 营销类型 | |
| 189 | + * | |
| 190 | + * 枚举 {@link PromotionTypeEnum} | |
| 191 | + */ | |
| 192 | + private Integer type; | |
| 193 | + /** | |
| 194 | + * 营销级别 | |
| 195 | + * | |
| 196 | + * 枚举 {@link PromotionLevelEnum} | |
| 197 | + */ | |
| 198 | + private Integer level; | |
| 199 | + /** | |
| 200 | + * 计算时的原价(总),单位:分 | |
| 201 | + */ | |
| 202 | + private Integer totalPrice; | |
| 203 | + /** | |
| 204 | + * 计算时的优惠(总),单位:分 | |
| 205 | + */ | |
| 206 | + private Integer discountPrice; | |
| 207 | + /** | |
| 208 | + * 匹配的商品 SKU 数组 | |
| 209 | + */ | |
| 210 | + private List<PromotionItem> items; | |
| 211 | + | |
| 212 | + // ========== 匹配情况 ========== | |
| 213 | + | |
| 214 | + /** | |
| 215 | + * 是否满足优惠条件 | |
| 216 | + */ | |
| 217 | + private Boolean match; | |
| 218 | + /** | |
| 219 | + * 满足条件的提示 | |
| 220 | + * | |
| 221 | + * 如果 {@link #match} = true 满足,则提示“圣诞价:省 150.00 元” | |
| 222 | + * 如果 {@link #match} = false 不满足,则提示“购满 85 元,可减 40 元” | |
| 223 | + */ | |
| 224 | + private String description; | |
| 225 | + | |
| 226 | + } | |
| 227 | + | |
| 228 | + /** | |
| 229 | + * 营销匹配的商品 SKU | |
| 230 | + */ | |
| 231 | + @Data | |
| 232 | + public static class PromotionItem { | |
| 233 | + | |
| 234 | + /** | |
| 235 | + * 商品 SKU 编号 | |
| 236 | + */ | |
| 237 | + private Long skuId; | |
| 238 | + /** | |
| 239 | + * 计算时的原价(总),单位:分 | |
| 240 | + */ | |
| 241 | + private Integer totalPrice; | |
| 242 | + /** | |
| 243 | + * 计算时的优惠(总),单位:分 | |
| 244 | + */ | |
| 245 | + private Integer discountPrice; | |
| 246 | + | |
| 247 | + } | |
| 248 | + | |
| 249 | +} | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.price.calculator; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.hutool.core.lang.Assert; | |
| 5 | +import cn.hutool.core.util.StrUtil; | |
| 6 | +import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; | |
| 7 | +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; | |
| 8 | +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; | |
| 9 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; | |
| 10 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; | |
| 11 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | |
| 12 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | |
| 13 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | |
| 14 | +import org.springframework.core.annotation.Order; | |
| 15 | +import org.springframework.stereotype.Component; | |
| 16 | + | |
| 17 | +import javax.annotation.Resource; | |
| 18 | +import java.util.List; | |
| 19 | +import java.util.function.Predicate; | |
| 20 | + | |
| 21 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 22 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; | |
| 23 | +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_NO_MATCH_MIN_PRICE; | |
| 24 | +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_NO_MATCH_SPU; | |
| 25 | + | |
| 26 | +/** | |
| 27 | + * 优惠劵的 {@link TradePriceCalculator} 实现类 | |
| 28 | + * | |
| 29 | + * @author 芋道源码 | |
| 30 | + */ | |
| 31 | +@Component | |
| 32 | +@Order(TradePriceCalculator.ORDER_COUPON) | |
| 33 | +public class TradeCouponPriceCalculator implements TradePriceCalculator { | |
| 34 | + | |
| 35 | + @Resource | |
| 36 | + private CouponApi couponApi; | |
| 37 | + | |
| 38 | + @Override | |
| 39 | + public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { | |
| 40 | + // 1.1 校验优惠劵 | |
| 41 | + if (param.getCouponId() == null) { | |
| 42 | + return; | |
| 43 | + } | |
| 44 | + CouponRespDTO coupon = couponApi.validateCoupon(new CouponValidReqDTO() | |
| 45 | + .setId(param.getCouponId()).setUserId(param.getUserId())); | |
| 46 | + Assert.notNull(coupon, "校验通过的优惠劵({}),不能为空", param.getCouponId()); | |
| 47 | + | |
| 48 | + // 2.1 获得匹配的商品 SKU 数组 | |
| 49 | + List<TradePriceCalculateRespBO.OrderItem> orderItems = filterMatchCouponOrderItems(result, coupon); | |
| 50 | + if (CollUtil.isEmpty(orderItems)) { | |
| 51 | + throw exception(COUPON_NO_MATCH_SPU); | |
| 52 | + } | |
| 53 | + // 2.2 计算是否满足优惠劵的使用金额 | |
| 54 | + Integer totalPayPrice = TradePriceCalculatorHelper.calculateTotalPayPrice(orderItems); | |
| 55 | + if (totalPayPrice < coupon.getUsePrice()) { | |
| 56 | + throw exception(COUPON_NO_MATCH_MIN_PRICE); | |
| 57 | + } | |
| 58 | + | |
| 59 | + // 3.1 计算可以优惠的金额 | |
| 60 | + Integer couponPrice = getCouponPrice(coupon, totalPayPrice); | |
| 61 | + Assert.isTrue(couponPrice < totalPayPrice, | |
| 62 | + "优惠劵({}) 的优惠金额({}),不能大于订单总金额({})", coupon.getId(), couponPrice, totalPayPrice); | |
| 63 | + // 3.2 计算分摊的优惠金额 | |
| 64 | + List<Integer> divideCouponPrices = TradePriceCalculatorHelper.dividePrice(orderItems, couponPrice); | |
| 65 | + | |
| 66 | + // 4.1 记录使用的优惠劵 | |
| 67 | + result.setCouponId(param.getCouponId()); | |
| 68 | + // 4.2 记录优惠明细 | |
| 69 | + TradePriceCalculatorHelper.addPromotion(result, orderItems, | |
| 70 | + param.getCouponId(), coupon.getName(), PromotionTypeEnum.COUPON.getType(), | |
| 71 | + StrUtil.format("优惠劵:省 {} 元", TradePriceCalculatorHelper.formatPrice(couponPrice)), | |
| 72 | + divideCouponPrices); | |
| 73 | + // 4.3 更新 SKU 优惠金额 | |
| 74 | + for (int i = 0; i < orderItems.size(); i++) { | |
| 75 | + TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i); | |
| 76 | + orderItem.setCouponPrice(divideCouponPrices.get(i)); | |
| 77 | + TradePriceCalculatorHelper.recountPayPrice(orderItem); | |
| 78 | + } | |
| 79 | + TradePriceCalculatorHelper.recountAllPrice(result); | |
| 80 | + } | |
| 81 | + | |
| 82 | + private Integer getCouponPrice(CouponRespDTO coupon, Integer totalPayPrice) { | |
| 83 | + if (PromotionDiscountTypeEnum.PRICE.getType().equals(coupon.getDiscountType())) { // 减价 | |
| 84 | + return coupon.getDiscountPrice(); | |
| 85 | + } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(coupon.getDiscountType())) { // 打折 | |
| 86 | + int couponPrice = totalPayPrice * coupon.getDiscountPercent() / 100; | |
| 87 | + return coupon.getDiscountLimitPrice() == null ? couponPrice | |
| 88 | + : Math.min(couponPrice, coupon.getDiscountLimitPrice()); // 优惠上限 | |
| 89 | + } | |
| 90 | + throw new IllegalArgumentException(String.format("优惠劵(%s) 的优惠类型不正确", coupon)); | |
| 91 | + } | |
| 92 | + | |
| 93 | + /** | |
| 94 | + * 获得优惠劵可使用的订单项(商品)列表 | |
| 95 | + * | |
| 96 | + * @param result 计算结果 | |
| 97 | + * @param coupon 优惠劵 | |
| 98 | + * @return 订单项(商品)列表 | |
| 99 | + */ | |
| 100 | + private List<TradePriceCalculateRespBO.OrderItem> filterMatchCouponOrderItems(TradePriceCalculateRespBO result, | |
| 101 | + CouponRespDTO coupon) { | |
| 102 | + Predicate<TradePriceCalculateRespBO.OrderItem> matchPredicate = TradePriceCalculateRespBO.OrderItem::getSelected; | |
| 103 | + if (PromotionProductScopeEnum.SPU.getScope().equals(coupon.getProductScope())) { | |
| 104 | + matchPredicate = orderItem -> coupon.getProductSpuIds().contains(orderItem.getSpuId()); | |
| 105 | + } | |
| 106 | + return filterList(result.getItems(), matchPredicate); | |
| 107 | + } | |
| 108 | + | |
| 109 | +} | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.price.calculator; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.hutool.core.util.StrUtil; | |
| 5 | +import cn.iocoder.yudao.module.promotion.api.discount.DiscountActivityApi; | |
| 6 | +import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; | |
| 7 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; | |
| 8 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | |
| 9 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | |
| 10 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | |
| 11 | +import org.springframework.core.annotation.Order; | |
| 12 | +import org.springframework.stereotype.Component; | |
| 13 | + | |
| 14 | +import javax.annotation.Resource; | |
| 15 | +import java.util.List; | |
| 16 | +import java.util.Map; | |
| 17 | + | |
| 18 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | |
| 19 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | |
| 20 | +import static cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper.formatPrice; | |
| 21 | + | |
| 22 | +/** | |
| 23 | + * 限时折扣的 {@link TradePriceCalculator} 实现类 | |
| 24 | + * | |
| 25 | + * @author 芋道源码 | |
| 26 | + */ | |
| 27 | +@Component | |
| 28 | +@Order(TradePriceCalculator.ORDER_DISCOUNT_ACTIVITY) | |
| 29 | +public class TradeDiscountActivityPriceCalculator implements TradePriceCalculator { | |
| 30 | + | |
| 31 | + @Resource | |
| 32 | + private DiscountActivityApi discountActivityApi; | |
| 33 | + | |
| 34 | + @Override | |
| 35 | + public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { | |
| 36 | + // 获得 SKU 对应的限时折扣活动 | |
| 37 | + List<DiscountProductRespDTO> discountProducts = discountActivityApi.getMatchDiscountProductList( | |
| 38 | + convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSkuId)); | |
| 39 | + if (CollUtil.isEmpty(discountProducts)) { | |
| 40 | + return; | |
| 41 | + } | |
| 42 | + Map<Long, DiscountProductRespDTO> discountProductMap = convertMap(discountProducts, DiscountProductRespDTO::getSkuId); | |
| 43 | + | |
| 44 | + // 处理每个 SKU 的限时折扣 | |
| 45 | + result.getItems().forEach(orderItem -> { | |
| 46 | + // 1. 获取该 SKU 的优惠信息 | |
| 47 | + DiscountProductRespDTO discountProduct = discountProductMap.get(orderItem.getSkuId()); | |
| 48 | + if (discountProduct == null) { | |
| 49 | + return; | |
| 50 | + } | |
| 51 | + // 2. 计算优惠金额 | |
| 52 | + Integer newPayPrice = calculatePayPrice(discountProduct, orderItem); | |
| 53 | + Integer newDiscountPrice = orderItem.getPayPrice() - newPayPrice; | |
| 54 | + | |
| 55 | + // 3.1 记录优惠明细 | |
| 56 | + TradePriceCalculatorHelper.addPromotion(result, orderItem, | |
| 57 | + discountProduct.getActivityId(), discountProduct.getActivityName(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType(), | |
| 58 | + StrUtil.format("限时折扣:省 {} 元", formatPrice(newDiscountPrice)), | |
| 59 | + newDiscountPrice); | |
| 60 | + // 3.2 更新 SKU 优惠金额 | |
| 61 | + orderItem.setDiscountPrice(orderItem.getDiscountPrice() + newDiscountPrice); | |
| 62 | + TradePriceCalculatorHelper.recountPayPrice(orderItem); | |
| 63 | + }); | |
| 64 | + TradePriceCalculatorHelper.recountAllPrice(result); | |
| 65 | + } | |
| 66 | + | |
| 67 | + private Integer calculatePayPrice(DiscountProductRespDTO discountProduct, | |
| 68 | + TradePriceCalculateRespBO.OrderItem orderItem) { | |
| 69 | + Integer price = orderItem.getPayPrice(); | |
| 70 | + if (PromotionDiscountTypeEnum.PRICE.getType().equals(discountProduct.getDiscountType())) { // 减价 | |
| 71 | + price -= discountProduct.getDiscountPrice() * orderItem.getCount(); | |
| 72 | + } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(discountProduct.getDiscountType())) { // 打折 | |
| 73 | + price = price * discountProduct.getDiscountPercent() / 100; | |
| 74 | + } else { | |
| 75 | + throw new IllegalArgumentException(String.format("优惠活动的商品(%s) 的优惠类型不正确", discountProduct)); | |
| 76 | + } | |
| 77 | + return price; | |
| 78 | + } | |
| 79 | + | |
| 80 | +} | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculator.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.price.calculator; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | |
| 4 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * 价格计算的计算器接口 | |
| 8 | + * | |
| 9 | + * @author 芋道源码 | |
| 10 | + */ | |
| 11 | +public interface TradePriceCalculator { | |
| 12 | + | |
| 13 | + int ORDER_DISCOUNT_ACTIVITY = 10; | |
| 14 | + int ORDER_REWARD_ACTIVITY = 20; | |
| 15 | + int ORDER_COUPON = 30; | |
| 16 | + | |
| 17 | + void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result); | |
| 18 | + | |
| 19 | +} | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.price.calculator; | |
| 2 | + | |
| 3 | +import cn.hutool.core.lang.Assert; | |
| 4 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 5 | +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | |
| 6 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | |
| 7 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | |
| 8 | + | |
| 9 | +import java.util.ArrayList; | |
| 10 | +import java.util.List; | |
| 11 | +import java.util.Map; | |
| 12 | + | |
| 13 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | |
| 14 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; | |
| 15 | +import static java.util.Collections.singletonList; | |
| 16 | + | |
| 17 | +/** | |
| 18 | + * {@link TradePriceCalculator} 的工具类 | |
| 19 | + * | |
| 20 | + * 主要实现对 {@link TradePriceCalculateRespBO} 计算结果的操作 | |
| 21 | + * | |
| 22 | + * @author 芋道源码 | |
| 23 | + */ | |
| 24 | +public class TradePriceCalculatorHelper { | |
| 25 | + | |
| 26 | + public static TradePriceCalculateRespBO buildCalculateResp(TradePriceCalculateReqBO param, | |
| 27 | + List<ProductSkuRespDTO> skuList) { | |
| 28 | + // 创建 PriceCalculateRespDTO 对象 | |
| 29 | + TradePriceCalculateRespBO result = new TradePriceCalculateRespBO(); | |
| 30 | + result.setOrderType(param.getOrderType()); | |
| 31 | + // 创建它的 OrderItem 属性 | |
| 32 | + Map<Long, TradePriceCalculateReqBO.Item> skuItemMap = convertMap(param.getItems(), | |
| 33 | + TradePriceCalculateReqBO.Item::getSkuId); | |
| 34 | + result.setItems(new ArrayList<>(skuItemMap.size())); | |
| 35 | + skuList.forEach(sku -> { | |
| 36 | + TradePriceCalculateReqBO.Item skuItem = skuItemMap.get(sku.getId()); | |
| 37 | + TradePriceCalculateRespBO.OrderItem orderItem = new TradePriceCalculateRespBO.OrderItem() | |
| 38 | + // SKU 字段 | |
| 39 | + .setSpuId(sku.getSpuId()).setSkuId(sku.getId()) | |
| 40 | + .setCount(skuItem.getCount()).setCartId(skuItem.getCartId()).setSelected(skuItem.getSelected()) | |
| 41 | + // 价格字段 | |
| 42 | + .setPrice(sku.getPrice()).setPayPrice(sku.getPrice() * skuItem.getCount()) | |
| 43 | + .setDiscountPrice(0).setDeliveryPrice(0).setCouponPrice(0).setPointPrice(0); | |
| 44 | + result.getItems().add(orderItem); | |
| 45 | + }); | |
| 46 | + // 创建它的 Price 属性 | |
| 47 | + result.setPrice(new TradePriceCalculateRespBO.Price()); | |
| 48 | + recountAllPrice(result); | |
| 49 | + return result; | |
| 50 | + } | |
| 51 | + | |
| 52 | + /** | |
| 53 | + * 基于订单项,重新计算 price 总价 | |
| 54 | + * | |
| 55 | + * @param result 计算结果 | |
| 56 | + */ | |
| 57 | + public static void recountAllPrice(TradePriceCalculateRespBO result) { | |
| 58 | + // 先重置 | |
| 59 | + TradePriceCalculateRespBO.Price price = result.getPrice(); | |
| 60 | + price.setTotalPrice(0).setDiscountPrice(0).setDeliveryPrice(0) | |
| 61 | + .setCouponPrice(0).setPointPrice(0).setPayPrice(0); | |
| 62 | + // 再合计 item | |
| 63 | + result.getItems().forEach(item -> { | |
| 64 | + if (!item.getSelected()) { | |
| 65 | + return; | |
| 66 | + } | |
| 67 | + price.setTotalPrice(price.getTotalPrice() + item.getPrice() * item.getCount()); | |
| 68 | + price.setDiscountPrice(price.getDiscountPrice() + item.getDiscountPrice()); | |
| 69 | + price.setDeliveryPrice(price.getDeliveryPrice() + item.getDeliveryPrice()); | |
| 70 | + price.setCouponPrice(price.getCouponPrice() + item.getCouponPrice()); | |
| 71 | + price.setPointPrice(price.getPointPrice() + item.getPointPrice()); | |
| 72 | + price.setPayPrice(price.getPayPrice() + item.getPayPrice()); | |
| 73 | + }); | |
| 74 | + } | |
| 75 | + | |
| 76 | + /** | |
| 77 | + * 重新计算单个订单项的支付金额 | |
| 78 | + * | |
| 79 | + * @param orderItem 订单项 | |
| 80 | + */ | |
| 81 | + public static void recountPayPrice(TradePriceCalculateRespBO.OrderItem orderItem) { | |
| 82 | + orderItem.setPayPrice(orderItem.getPrice()* orderItem.getCount() | |
| 83 | + - orderItem.getDiscountPrice() | |
| 84 | + + orderItem.getDeliveryPrice() | |
| 85 | + - orderItem.getCouponPrice() | |
| 86 | + - orderItem.getPointPrice()); | |
| 87 | + } | |
| 88 | + | |
| 89 | + /** | |
| 90 | + * 计算已选中的订单项,总支付金额 | |
| 91 | + * | |
| 92 | + * @param orderItems 订单项数组 | |
| 93 | + * @return 总支付金额 | |
| 94 | + */ | |
| 95 | + public static Integer calculateTotalPayPrice(List<TradePriceCalculateRespBO.OrderItem> orderItems) { | |
| 96 | + return getSumValue(orderItems, | |
| 97 | + orderItem -> orderItem.getSelected() ? orderItem.getPayPrice() : 0, // 未选中的情况下,不计算支付金额 | |
| 98 | + Integer::sum); | |
| 99 | + } | |
| 100 | + | |
| 101 | + /** | |
| 102 | + * 计算已选中的订单项,总商品数 | |
| 103 | + * | |
| 104 | + * @param orderItems 订单项数组 | |
| 105 | + * @return 总商品数 | |
| 106 | + */ | |
| 107 | + public static Integer calculateTotalCount(List<TradePriceCalculateRespBO.OrderItem> orderItems) { | |
| 108 | + return getSumValue(orderItems, | |
| 109 | + orderItem -> orderItem.getSelected() ? orderItem.getCount() : 0, // 未选中的情况下,不计算数量 | |
| 110 | + Integer::sum); | |
| 111 | + } | |
| 112 | + | |
| 113 | + /** | |
| 114 | + * 按照支付金额,返回每个订单项的分摊金额数组 | |
| 115 | + * | |
| 116 | + * @param orderItems 订单项数组 | |
| 117 | + * @param price 金额 | |
| 118 | + * @return 分摊金额数组,和传入的 orderItems 一一对应 | |
| 119 | + */ | |
| 120 | + public static List<Integer> dividePrice(List<TradePriceCalculateRespBO.OrderItem> orderItems, Integer price) { | |
| 121 | + Integer total = calculateTotalPayPrice(orderItems); | |
| 122 | + assert total != null; | |
| 123 | + // 遍历每一个,进行分摊 | |
| 124 | + List<Integer> prices = new ArrayList<>(orderItems.size()); | |
| 125 | + int remainPrice = price; | |
| 126 | + for (int i = 0; i < orderItems.size(); i++) { | |
| 127 | + TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i); | |
| 128 | + // 1. 如果是未选中,则分摊为 0 | |
| 129 | + if (!orderItem.getSelected()) { | |
| 130 | + prices.add(0); | |
| 131 | + continue; | |
| 132 | + } | |
| 133 | + // 2. 如果选中,则按照百分比,进行分摊 | |
| 134 | + int partPrice; | |
| 135 | + if (i < orderItems.size() - 1) { // 减一的原因,是因为拆分时,如果按照比例,可能会出现.所以最后一个,使用反减 | |
| 136 | + partPrice = (int) (price * (1.0D * orderItem.getPayPrice() / total)); | |
| 137 | + remainPrice -= partPrice; | |
| 138 | + } else { | |
| 139 | + partPrice = remainPrice; | |
| 140 | + } | |
| 141 | + Assert.isTrue(partPrice >= 0, "分摊金额必须大于等于 0"); | |
| 142 | + prices.add(partPrice); | |
| 143 | + } | |
| 144 | + return prices; | |
| 145 | + } | |
| 146 | + | |
| 147 | + /** | |
| 148 | + * 添加【匹配】单个 OrderItem 的营销明细 | |
| 149 | + * | |
| 150 | + * @param result 价格计算结果 | |
| 151 | + * @param orderItem 单个订单商品 SKU | |
| 152 | + * @param id 营销编号 | |
| 153 | + * @param name 营销名字 | |
| 154 | + * @param description 满足条件的提示 | |
| 155 | + * @param type 营销类型 | |
| 156 | + * @param discountPrice 单个订单商品 SKU 的优惠价格(总) | |
| 157 | + */ | |
| 158 | + public static void addPromotion(TradePriceCalculateRespBO result, TradePriceCalculateRespBO.OrderItem orderItem, | |
| 159 | + Long id, String name, Integer type, String description, Integer discountPrice) { | |
| 160 | + addPromotion(result, singletonList(orderItem), id, name, type, description, singletonList(discountPrice)); | |
| 161 | + } | |
| 162 | + | |
| 163 | + /** | |
| 164 | + * 添加【匹配】多个 OrderItem 的营销明细 | |
| 165 | + * | |
| 166 | + * @param result 价格计算结果 | |
| 167 | + * @param orderItems 多个订单商品 SKU | |
| 168 | + * @param id 营销编号 | |
| 169 | + * @param name 营销名字 | |
| 170 | + * @param description 满足条件的提示 | |
| 171 | + * @param type 营销类型 | |
| 172 | + * @param discountPrices 多个订单商品 SKU 的优惠价格(总),和 orderItems 一一对应 | |
| 173 | + */ | |
| 174 | + public static void addPromotion(TradePriceCalculateRespBO result, List<TradePriceCalculateRespBO.OrderItem> orderItems, | |
| 175 | + Long id, String name, Integer type, String description, List<Integer> discountPrices) { | |
| 176 | + // 创建营销明细 Item | |
| 177 | + List<TradePriceCalculateRespBO.PromotionItem> promotionItems = new ArrayList<>(discountPrices.size()); | |
| 178 | + for (int i = 0; i < orderItems.size(); i++) { | |
| 179 | + TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i); | |
| 180 | + promotionItems.add(new TradePriceCalculateRespBO.PromotionItem().setSkuId(orderItem.getSkuId()) | |
| 181 | + .setTotalPrice(orderItem.getPayPrice()).setDiscountPrice(discountPrices.get(i))); | |
| 182 | + } | |
| 183 | + // 创建营销明细 | |
| 184 | + TradePriceCalculateRespBO.Promotion promotion = new TradePriceCalculateRespBO.Promotion() | |
| 185 | + .setId(id).setName(name).setType(type) | |
| 186 | + .setTotalPrice(calculateTotalPayPrice(orderItems)) | |
| 187 | + .setDiscountPrice(getSumValue(discountPrices, value -> value, Integer::sum)) | |
| 188 | + .setItems(promotionItems).setMatch(true).setDescription(description); | |
| 189 | + result.getPromotions().add(promotion); | |
| 190 | + } | |
| 191 | + | |
| 192 | + /** | |
| 193 | + * 添加【不匹配】多个 OrderItem 的营销明细 | |
| 194 | + * | |
| 195 | + * @param result 价格计算结果 | |
| 196 | + * @param orderItems 多个订单商品 SKU | |
| 197 | + * @param id 营销编号 | |
| 198 | + * @param name 营销名字 | |
| 199 | + * @param description 满足条件的提示 | |
| 200 | + * @param type 营销类型 | |
| 201 | + */ | |
| 202 | + public static void addNotMatchPromotion(TradePriceCalculateRespBO result, List<TradePriceCalculateRespBO.OrderItem> orderItems, | |
| 203 | + Long id, String name, Integer type, String description) { | |
| 204 | + // 创建营销明细 Item | |
| 205 | + List<TradePriceCalculateRespBO.PromotionItem> promotionItems = CollectionUtils.convertList(orderItems, | |
| 206 | + orderItem -> new TradePriceCalculateRespBO.PromotionItem().setSkuId(orderItem.getSkuId()) | |
| 207 | + .setTotalPrice(orderItem.getPayPrice()).setDiscountPrice(0)); | |
| 208 | + // 创建营销明细 | |
| 209 | + TradePriceCalculateRespBO.Promotion promotion = new TradePriceCalculateRespBO.Promotion() | |
| 210 | + .setId(id).setName(name).setType(type) | |
| 211 | + .setTotalPrice(calculateTotalPayPrice(orderItems)) | |
| 212 | + .setDiscountPrice(0) | |
| 213 | + .setItems(promotionItems).setMatch(false).setDescription(description); | |
| 214 | + result.getPromotions().add(promotion); | |
| 215 | + } | |
| 216 | + | |
| 217 | + public static String formatPrice(Integer price) { | |
| 218 | + return String.format("%.2f", price / 100d); | |
| 219 | + } | |
| 220 | + | |
| 221 | +} | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.price.calculator; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.hutool.core.util.StrUtil; | |
| 5 | +import cn.iocoder.yudao.module.promotion.api.reward.RewardActivityApi; | |
| 6 | +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; | |
| 7 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum; | |
| 8 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | |
| 9 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | |
| 10 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | |
| 11 | +import org.springframework.core.annotation.Order; | |
| 12 | +import org.springframework.stereotype.Component; | |
| 13 | + | |
| 14 | +import javax.annotation.Resource; | |
| 15 | +import java.util.List; | |
| 16 | + | |
| 17 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | |
| 18 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; | |
| 19 | +import static cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper.formatPrice; | |
| 20 | + | |
| 21 | +/** | |
| 22 | + * 满减送活动的 {@link TradePriceCalculator} 实现类 | |
| 23 | + * | |
| 24 | + * @author 芋道源码 | |
| 25 | + */ | |
| 26 | +@Component | |
| 27 | +@Order(TradePriceCalculator.ORDER_REWARD_ACTIVITY) | |
| 28 | +public class TradeRewardActivityPriceCalculator implements TradePriceCalculator { | |
| 29 | + | |
| 30 | + @Resource | |
| 31 | + private RewardActivityApi rewardActivityApi; | |
| 32 | + | |
| 33 | + @Override | |
| 34 | + public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { | |
| 35 | + // 获得 SKU 对应的满减送活动 | |
| 36 | + List<RewardActivityMatchRespDTO> rewardActivities = rewardActivityApi.getMatchRewardActivityList( | |
| 37 | + convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSpuId)); | |
| 38 | + if (CollUtil.isEmpty(rewardActivities)) { | |
| 39 | + return; | |
| 40 | + } | |
| 41 | + | |
| 42 | + // 处理每个满减送活动 | |
| 43 | + rewardActivities.forEach(rewardActivity -> calculate(param, result, rewardActivity)); | |
| 44 | + } | |
| 45 | + | |
| 46 | + private void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result, | |
| 47 | + RewardActivityMatchRespDTO rewardActivity) { | |
| 48 | + // 1.1 获得满减送的订单项(商品)列表 | |
| 49 | + List<TradePriceCalculateRespBO.OrderItem> orderItems = filterMatchCouponOrderItems(result, rewardActivity); | |
| 50 | + if (CollUtil.isEmpty(orderItems)) { | |
| 51 | + return; | |
| 52 | + } | |
| 53 | + // 1.2 获得最大匹配的满减送活动的规则 | |
| 54 | + RewardActivityMatchRespDTO.Rule rule = getMaxMatchRewardActivityRule(rewardActivity, orderItems); | |
| 55 | + if (rule == null) { | |
| 56 | + return; | |
| 57 | + } | |
| 58 | + | |
| 59 | + // 2.1 计算可以优惠的金额 | |
| 60 | + Integer newDiscountPrice = rule.getDiscountPrice(); | |
| 61 | + // 2.2 计算分摊的优惠金额 | |
| 62 | + List<Integer> divideDiscountPrices = TradePriceCalculatorHelper.dividePrice(orderItems, newDiscountPrice); | |
| 63 | + | |
| 64 | + // 3.1 记录使用的优惠劵 | |
| 65 | + result.setCouponId(param.getCouponId()); | |
| 66 | + // 3.2 记录优惠明细 | |
| 67 | + TradePriceCalculatorHelper.addPromotion(result, orderItems, | |
| 68 | + rewardActivity.getId(), rewardActivity.getName(), PromotionTypeEnum.REWARD_ACTIVITY.getType(), | |
| 69 | + StrUtil.format("满减送:省 {} 元", formatPrice(rule.getDiscountPrice())), | |
| 70 | + divideDiscountPrices); | |
| 71 | + // 3.3 更新 SKU 优惠金额 | |
| 72 | + for (int i = 0; i < orderItems.size(); i++) { | |
| 73 | + TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i); | |
| 74 | + orderItem.setDiscountPrice(orderItem.getDiscountPrice() + divideDiscountPrices.get(i)); | |
| 75 | + TradePriceCalculatorHelper.recountPayPrice(orderItem); | |
| 76 | + } | |
| 77 | + TradePriceCalculatorHelper.recountAllPrice(result); | |
| 78 | + } | |
| 79 | + | |
| 80 | + /** | |
| 81 | + * 获得满减送的订单项(商品)列表 | |
| 82 | + * | |
| 83 | + * @param result 计算结果 | |
| 84 | + * @param rewardActivity 满减送活动 | |
| 85 | + * @return 订单项(商品)列表 | |
| 86 | + */ | |
| 87 | + private List<TradePriceCalculateRespBO.OrderItem> filterMatchCouponOrderItems(TradePriceCalculateRespBO result, | |
| 88 | + RewardActivityMatchRespDTO rewardActivity) { | |
| 89 | + return filterList(result.getItems(), | |
| 90 | + orderItem -> CollUtil.contains(rewardActivity.getSpuIds(), orderItem.getSpuId())); | |
| 91 | + } | |
| 92 | + | |
| 93 | + /** | |
| 94 | + * 获得最大匹配的满减送活动的规则 | |
| 95 | + * | |
| 96 | + * @param rewardActivity 满减送活动 | |
| 97 | + * @param orderItems 商品项 | |
| 98 | + * @return 匹配的活动规则 | |
| 99 | + */ | |
| 100 | + private RewardActivityMatchRespDTO.Rule getMaxMatchRewardActivityRule(RewardActivityMatchRespDTO rewardActivity, | |
| 101 | + List<TradePriceCalculateRespBO.OrderItem> orderItems) { | |
| 102 | + // 1. 计算数量和价格 | |
| 103 | + Integer count = TradePriceCalculatorHelper.calculateTotalCount(orderItems); | |
| 104 | + Integer price = TradePriceCalculatorHelper.calculateTotalPayPrice(orderItems); | |
| 105 | + assert count != null && price != null; | |
| 106 | + | |
| 107 | + // 2. 倒序找一个最大优惠的规则 | |
| 108 | + for (int i = rewardActivity.getRules().size() - 1; i >= 0; i--) { | |
| 109 | + RewardActivityMatchRespDTO.Rule rule = rewardActivity.getRules().get(i); | |
| 110 | + if (PromotionConditionTypeEnum.PRICE.getType().equals(rewardActivity.getConditionType()) | |
| 111 | + && price >= rule.getLimit()) { | |
| 112 | + return rule; | |
| 113 | + } | |
| 114 | + if (PromotionConditionTypeEnum.COUNT.getType().equals(rewardActivity.getConditionType()) | |
| 115 | + && count >= rule.getLimit()) { | |
| 116 | + return rule; | |
| 117 | + } | |
| 118 | + } | |
| 119 | + return null; | |
| 120 | + } | |
| 121 | + | |
| 122 | + /** | |
| 123 | + * 获得满减送活动部匹配时的提示 | |
| 124 | + * | |
| 125 | + * @param rewardActivity 满减送活动 | |
| 126 | + * @return 提示 | |
| 127 | + */ | |
| 128 | + private String getRewardActivityNotMeetTip(RewardActivityMatchRespDTO rewardActivity) { | |
| 129 | + // TODO 芋艿:后面再想想;应该找第一个规则,算下还差多少即可。 | |
| 130 | + return "TODO"; | |
| 131 | + } | |
| 132 | + | |
| 133 | +} | ... | ... |
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 { |
| 124 | 124 | .setSpuId(21L).setSkuId(2L).setCount(4).setOriginalPrice(80).setOriginalUnitPrice(20) |
| 125 | 125 | .setDiscountPrice(40).setPayPrice(40).setOrderPartPrice(15).setOrderDividePrice(25); |
| 126 | 126 | PriceCalculateRespDTO.Order priceOrder = new PriceCalculateRespDTO.Order() |
| 127 | - .setOriginalPrice(230).setOrderPrice(100).setDiscountPrice(0).setCouponPrice(30) | |
| 127 | + .setTotalPrice(230).setDiscountPrice(0).setCouponPrice(30) | |
| 128 | 128 | .setPointPrice(10).setDeliveryPrice(20).setPayPrice(80).setCouponId(101L).setCouponPrice(30) |
| 129 | 129 | .setItems(Arrays.asList(priceOrderItem01, priceOrderItem02)); |
| 130 | 130 | when(priceApi.calculatePrice(argThat(priceCalculateReqDTO -> { |
| ... | ... | @@ -170,7 +170,6 @@ public class TradeOrderServiceTest extends BaseDbUnitTest { |
| 170 | 170 | assertFalse(tradeOrderDO.getPayed()); |
| 171 | 171 | assertNull(tradeOrderDO.getPayTime()); |
| 172 | 172 | assertEquals(tradeOrderDO.getTotalPrice(), 230); |
| 173 | - assertEquals(tradeOrderDO.getOrderPrice(), 100); | |
| 174 | 173 | assertEquals(tradeOrderDO.getDiscountPrice(), 0); |
| 175 | 174 | assertEquals(tradeOrderDO.getAdjustPrice(), 0); |
| 176 | 175 | assertEquals(tradeOrderDO.getPayPrice(), 80); |
| ... | ... | @@ -208,8 +207,6 @@ public class TradeOrderServiceTest extends BaseDbUnitTest { |
| 208 | 207 | assertEquals(tradeOrderItemDO01.getPrice(), 50); |
| 209 | 208 | assertEquals(tradeOrderItemDO01.getDiscountPrice(), 20); |
| 210 | 209 | assertEquals(tradeOrderItemDO01.getPayPrice(), 130); |
| 211 | - assertEquals(tradeOrderItemDO01.getOrderPartPrice(), 7); | |
| 212 | - assertEquals(tradeOrderItemDO01.getOrderDividePrice(), 35); | |
| 213 | 210 | assertEquals(tradeOrderItemDO01.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); |
| 214 | 211 | // 断言 TradeOrderItemDO 订单(第 2 个) |
| 215 | 212 | TradeOrderItemDO tradeOrderItemDO02 = tradeOrderItemDOs.get(1); |
| ... | ... | @@ -228,8 +225,6 @@ public class TradeOrderServiceTest extends BaseDbUnitTest { |
| 228 | 225 | assertEquals(tradeOrderItemDO02.getPrice(), 20); |
| 229 | 226 | assertEquals(tradeOrderItemDO02.getDiscountPrice(), 40); |
| 230 | 227 | assertEquals(tradeOrderItemDO02.getPayPrice(), 40); |
| 231 | - assertEquals(tradeOrderItemDO02.getOrderPartPrice(), 15); | |
| 232 | - assertEquals(tradeOrderItemDO02.getOrderDividePrice(), 25); | |
| 233 | 228 | assertEquals(tradeOrderItemDO02.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); |
| 234 | 229 | // 校验调用 |
| 235 | 230 | verify(productSkuApi).updateSkuStock(argThat(updateStockReqDTO -> { | ... | ... |
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 |
| 5 | 5 | import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressRespVO; |
| 6 | 6 | import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; |
| 7 | 7 | import cn.iocoder.yudao.module.member.convert.address.AddressConvert; |
| 8 | -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; | |
| 8 | +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; | |
| 9 | 9 | import cn.iocoder.yudao.module.member.service.address.AddressService; |
| 10 | 10 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 11 | 11 | import io.swagger.v3.oas.annotations.Parameter; |
| ... | ... | @@ -54,21 +54,21 @@ public class AppAddressController { |
| 54 | 54 | @Operation(summary = "获得用户收件地址") |
| 55 | 55 | @Parameter(name = "id", description = "编号", required = true, example = "1024") |
| 56 | 56 | public CommonResult<AppAddressRespVO> getAddress(@RequestParam("id") Long id) { |
| 57 | - AddressDO address = addressService.getAddress(getLoginUserId(), id); | |
| 57 | + MemberAddressDO address = addressService.getAddress(getLoginUserId(), id); | |
| 58 | 58 | return success(AddressConvert.INSTANCE.convert(address)); |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | 61 | @GetMapping("/get-default") |
| 62 | 62 | @Operation(summary = "获得默认的用户收件地址") |
| 63 | 63 | public CommonResult<AppAddressRespVO> getDefaultUserAddress() { |
| 64 | - AddressDO address = addressService.getDefaultUserAddress(getLoginUserId()); | |
| 64 | + MemberAddressDO address = addressService.getDefaultUserAddress(getLoginUserId()); | |
| 65 | 65 | return success(AddressConvert.INSTANCE.convert(address)); |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | 68 | @GetMapping("/list") |
| 69 | 69 | @Operation(summary = "获得用户收件地址列表") |
| 70 | 70 | public CommonResult<List<AppAddressRespVO>> getAddressList() { |
| 71 | - List<AddressDO> list = addressService.getAddressList(getLoginUserId()); | |
| 71 | + List<MemberAddressDO> list = addressService.getAddressList(getLoginUserId()); | |
| 72 | 72 | return success(AddressConvert.INSTANCE.convertList(list)); |
| 73 | 73 | } |
| 74 | 74 | ... | ... |
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; |
| 5 | 5 | import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; |
| 6 | 6 | import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressRespVO; |
| 7 | 7 | import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; |
| 8 | -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; | |
| 8 | +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; | |
| 9 | 9 | import org.mapstruct.Mapper; |
| 10 | 10 | import org.mapstruct.factory.Mappers; |
| 11 | 11 | |
| ... | ... | @@ -21,16 +21,16 @@ public interface AddressConvert { |
| 21 | 21 | |
| 22 | 22 | AddressConvert INSTANCE = Mappers.getMapper(AddressConvert.class); |
| 23 | 23 | |
| 24 | - AddressDO convert(AppAddressCreateReqVO bean); | |
| 24 | + MemberAddressDO convert(AppAddressCreateReqVO bean); | |
| 25 | 25 | |
| 26 | - AddressDO convert(AppAddressUpdateReqVO bean); | |
| 26 | + MemberAddressDO convert(AppAddressUpdateReqVO bean); | |
| 27 | 27 | |
| 28 | - AppAddressRespVO convert(AddressDO bean); | |
| 28 | + AppAddressRespVO convert(MemberAddressDO bean); | |
| 29 | 29 | |
| 30 | - List<AppAddressRespVO> convertList(List<AddressDO> list); | |
| 30 | + List<AppAddressRespVO> convertList(List<MemberAddressDO> list); | |
| 31 | 31 | |
| 32 | - PageResult<AppAddressRespVO> convertPage(PageResult<AddressDO> page); | |
| 32 | + PageResult<AppAddressRespVO> convertPage(PageResult<MemberAddressDO> page); | |
| 33 | 33 | |
| 34 | - AddressRespDTO convert02(AddressDO bean); | |
| 34 | + AddressRespDTO convert02(MemberAddressDO bean); | |
| 35 | 35 | |
| 36 | 36 | } | ... | ... |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/AddressDO.java renamed to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/address/MemberAddressDO.java
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; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 4 | 4 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 5 | -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; | |
| 5 | +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; | |
| 6 | 6 | import org.apache.ibatis.annotations.Mapper; |
| 7 | 7 | |
| 8 | 8 | import java.util.List; |
| 9 | 9 | |
| 10 | 10 | @Mapper |
| 11 | -public interface AddressMapper extends BaseMapperX<AddressDO> { | |
| 11 | +public interface AddressMapper extends BaseMapperX<MemberAddressDO> { | |
| 12 | 12 | |
| 13 | - default AddressDO selectByIdAndUserId(Long id, Long userId) { | |
| 14 | - return selectOne(AddressDO::getId, id, AddressDO::getUserId, userId); | |
| 13 | + default MemberAddressDO selectByIdAndUserId(Long id, Long userId) { | |
| 14 | + return selectOne(MemberAddressDO::getId, id, MemberAddressDO::getUserId, userId); | |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | - default List<AddressDO> selectListByUserIdAndDefaulted(Long userId, Boolean defaulted) { | |
| 18 | - return selectList(new LambdaQueryWrapperX<AddressDO>().eq(AddressDO::getUserId, userId) | |
| 19 | - .eqIfPresent(AddressDO::getDefaulted, defaulted)); | |
| 17 | + default List<MemberAddressDO> selectListByUserIdAndDefaulted(Long userId, Boolean defaulted) { | |
| 18 | + return selectList(new LambdaQueryWrapperX<MemberAddressDO>().eq(MemberAddressDO::getUserId, userId) | |
| 19 | + .eqIfPresent(MemberAddressDO::getDefaulted, defaulted)); | |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | 22 | } | ... | ... |
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; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; |
| 4 | 4 | import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; |
| 5 | -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; | |
| 5 | +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; | |
| 6 | 6 | |
| 7 | 7 | import javax.validation.Valid; |
| 8 | 8 | import java.util.List; |
| ... | ... | @@ -46,7 +46,7 @@ public interface AddressService { |
| 46 | 46 | * @param id 编号 |
| 47 | 47 | * @return 用户收件地址 |
| 48 | 48 | */ |
| 49 | - AddressDO getAddress(Long userId, Long id); | |
| 49 | + MemberAddressDO getAddress(Long userId, Long id); | |
| 50 | 50 | |
| 51 | 51 | /** |
| 52 | 52 | * 获得用户收件地址列表 |
| ... | ... | @@ -54,7 +54,7 @@ public interface AddressService { |
| 54 | 54 | * @param userId 用户编号 |
| 55 | 55 | * @return 用户收件地址列表 |
| 56 | 56 | */ |
| 57 | - List<AddressDO> getAddressList(Long userId); | |
| 57 | + List<MemberAddressDO> getAddressList(Long userId); | |
| 58 | 58 | |
| 59 | 59 | /** |
| 60 | 60 | * 获得用户默认的收件地址 |
| ... | ... | @@ -62,6 +62,6 @@ public interface AddressService { |
| 62 | 62 | * @param userId 用户编号 |
| 63 | 63 | * @return 用户收件地址 |
| 64 | 64 | */ |
| 65 | - AddressDO getDefaultUserAddress(Long userId); | |
| 65 | + MemberAddressDO getDefaultUserAddress(Long userId); | |
| 66 | 66 | |
| 67 | 67 | } | ... | ... |
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; |
| 4 | 4 | import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; |
| 5 | 5 | import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; |
| 6 | 6 | import cn.iocoder.yudao.module.member.convert.address.AddressConvert; |
| 7 | -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; | |
| 7 | +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; | |
| 8 | 8 | import cn.iocoder.yudao.module.member.dal.mysql.address.AddressMapper; |
| 9 | 9 | import org.springframework.stereotype.Service; |
| 10 | 10 | import org.springframework.transaction.annotation.Transactional; |
| ... | ... | @@ -33,12 +33,12 @@ public class AddressServiceImpl implements AddressService { |
| 33 | 33 | public Long createAddress(Long userId, AppAddressCreateReqVO createReqVO) { |
| 34 | 34 | // 如果添加的是默认收件地址,则将原默认地址修改为非默认 |
| 35 | 35 | if (Boolean.TRUE.equals(createReqVO.getDefaulted())) { |
| 36 | - List<AddressDO> addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); | |
| 37 | - addresses.forEach(address -> addressMapper.updateById(new AddressDO().setId(address.getId()).setDefaulted(false))); | |
| 36 | + List<MemberAddressDO> addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); | |
| 37 | + addresses.forEach(address -> addressMapper.updateById(new MemberAddressDO().setId(address.getId()).setDefaulted(false))); | |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | 40 | // 插入 |
| 41 | - AddressDO address = AddressConvert.INSTANCE.convert(createReqVO); | |
| 41 | + MemberAddressDO address = AddressConvert.INSTANCE.convert(createReqVO); | |
| 42 | 42 | address.setUserId(userId); |
| 43 | 43 | addressMapper.insert(address); |
| 44 | 44 | // 返回 |
| ... | ... | @@ -53,13 +53,13 @@ public class AddressServiceImpl implements AddressService { |
| 53 | 53 | |
| 54 | 54 | // 如果修改的是默认收件地址,则将原默认地址修改为非默认 |
| 55 | 55 | if (Boolean.TRUE.equals(updateReqVO.getDefaulted())) { |
| 56 | - List<AddressDO> addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); | |
| 56 | + List<MemberAddressDO> addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); | |
| 57 | 57 | addresses.stream().filter(u -> !u.getId().equals(updateReqVO.getId())) // 排除自己 |
| 58 | - .forEach(address -> addressMapper.updateById(new AddressDO().setId(address.getId()).setDefaulted(false))); | |
| 58 | + .forEach(address -> addressMapper.updateById(new MemberAddressDO().setId(address.getId()).setDefaulted(false))); | |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | 61 | // 更新 |
| 62 | - AddressDO updateObj = AddressConvert.INSTANCE.convert(updateReqVO); | |
| 62 | + MemberAddressDO updateObj = AddressConvert.INSTANCE.convert(updateReqVO); | |
| 63 | 63 | addressMapper.updateById(updateObj); |
| 64 | 64 | } |
| 65 | 65 | |
| ... | ... | @@ -72,25 +72,25 @@ public class AddressServiceImpl implements AddressService { |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | 74 | private void validAddressExists(Long userId, Long id) { |
| 75 | - AddressDO addressDO = getAddress(userId, id); | |
| 75 | + MemberAddressDO addressDO = getAddress(userId, id); | |
| 76 | 76 | if (addressDO == null) { |
| 77 | 77 | throw exception(ADDRESS_NOT_EXISTS); |
| 78 | 78 | } |
| 79 | 79 | } |
| 80 | 80 | |
| 81 | 81 | @Override |
| 82 | - public AddressDO getAddress(Long userId, Long id) { | |
| 82 | + public MemberAddressDO getAddress(Long userId, Long id) { | |
| 83 | 83 | return addressMapper.selectByIdAndUserId(id, userId); |
| 84 | 84 | } |
| 85 | 85 | |
| 86 | 86 | @Override |
| 87 | - public List<AddressDO> getAddressList(Long userId) { | |
| 87 | + public List<MemberAddressDO> getAddressList(Long userId) { | |
| 88 | 88 | return addressMapper.selectListByUserIdAndDefaulted(userId, null); |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | 91 | @Override |
| 92 | - public AddressDO getDefaultUserAddress(Long userId) { | |
| 93 | - List<AddressDO> addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); | |
| 92 | + public MemberAddressDO getDefaultUserAddress(Long userId) { | |
| 93 | + List<MemberAddressDO> addresses = addressMapper.selectListByUserIdAndDefaulted(userId, true); | |
| 94 | 94 | return CollUtil.getFirst(addresses); |
| 95 | 95 | } |
| 96 | 96 | ... | ... |
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; |
| 3 | 3 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 4 | 4 | import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; |
| 5 | 5 | import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; |
| 6 | -import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; | |
| 6 | +import cn.iocoder.yudao.module.member.dal.dataobject.address.MemberAddressDO; | |
| 7 | 7 | import cn.iocoder.yudao.module.member.dal.mysql.address.AddressMapper; |
| 8 | 8 | import org.junit.jupiter.api.Test; |
| 9 | 9 | import org.springframework.context.annotation.Import; |
| ... | ... | @@ -42,14 +42,14 @@ public class AddressServiceImplTest extends BaseDbUnitTest { |
| 42 | 42 | // 断言 |
| 43 | 43 | assertNotNull(addressId); |
| 44 | 44 | // 校验记录的属性是否正确 |
| 45 | - AddressDO address = addressMapper.selectById(addressId); | |
| 45 | + MemberAddressDO address = addressMapper.selectById(addressId); | |
| 46 | 46 | assertPojoEquals(reqVO, address); |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | 49 | @Test |
| 50 | 50 | public void testUpdateAddress_success() { |
| 51 | 51 | // mock 数据 |
| 52 | - AddressDO dbAddress = randomPojo(AddressDO.class); | |
| 52 | + MemberAddressDO dbAddress = randomPojo(MemberAddressDO.class); | |
| 53 | 53 | addressMapper.insert(dbAddress);// @Sql: 先插入出一条存在的数据 |
| 54 | 54 | // 准备参数 |
| 55 | 55 | AppAddressUpdateReqVO reqVO = randomPojo(AppAddressUpdateReqVO.class, o -> { |
| ... | ... | @@ -59,7 +59,7 @@ public class AddressServiceImplTest extends BaseDbUnitTest { |
| 59 | 59 | // 调用 |
| 60 | 60 | addressService.updateAddress(dbAddress.getUserId(), reqVO); |
| 61 | 61 | // 校验是否更新正确 |
| 62 | - AddressDO address = addressMapper.selectById(reqVO.getId()); // 获取最新的 | |
| 62 | + MemberAddressDO address = addressMapper.selectById(reqVO.getId()); // 获取最新的 | |
| 63 | 63 | assertPojoEquals(reqVO, address); |
| 64 | 64 | } |
| 65 | 65 | |
| ... | ... | @@ -75,7 +75,7 @@ public class AddressServiceImplTest extends BaseDbUnitTest { |
| 75 | 75 | @Test |
| 76 | 76 | public void testDeleteAddress_success() { |
| 77 | 77 | // mock 数据 |
| 78 | - AddressDO dbAddress = randomPojo(AddressDO.class); | |
| 78 | + MemberAddressDO dbAddress = randomPojo(MemberAddressDO.class); | |
| 79 | 79 | addressMapper.insert(dbAddress);// @Sql: 先插入出一条存在的数据 |
| 80 | 80 | // 准备参数 |
| 81 | 81 | Long id = dbAddress.getId(); | ... | ... |
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; |
| 6 | 6 | import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; |
| 7 | 7 | import cn.iocoder.yudao.framework.ip.core.utils.IPUtils; |
| 8 | 8 | import cn.iocoder.yudao.module.system.controller.admin.ip.vo.AreaNodeRespVO; |
| 9 | -import cn.iocoder.yudao.module.system.controller.admin.ip.vo.LazyAreaNodeRespVO; | |
| 9 | +import cn.iocoder.yudao.module.system.controller.admin.ip.vo.AreaNodeSimpleRespVO; | |
| 10 | 10 | import cn.iocoder.yudao.module.system.convert.ip.AreaConvert; |
| 11 | 11 | import io.swagger.v3.oas.annotations.Operation; |
| 12 | 12 | import io.swagger.v3.oas.annotations.Parameter; |
| ... | ... | @@ -15,7 +15,6 @@ import org.springframework.validation.annotation.Validated; |
| 15 | 15 | import org.springframework.web.bind.annotation.*; |
| 16 | 16 | |
| 17 | 17 | import java.util.ArrayList; |
| 18 | -import java.util.Arrays; | |
| 19 | 18 | import java.util.List; |
| 20 | 19 | import java.util.Set; |
| 21 | 20 | |
| ... | ... | @@ -35,19 +34,23 @@ public class AreaController { |
| 35 | 34 | return success(AreaConvert.INSTANCE.convertList(area.getChildren())); |
| 36 | 35 | } |
| 37 | 36 | |
| 38 | - @GetMapping("/getChildrenArea") | |
| 37 | + @GetMapping("/get-children") | |
| 39 | 38 | @Operation(summary = "获得地区的下级区域") |
| 40 | - public CommonResult<List<LazyAreaNodeRespVO>> getChildrenArea(Integer id) { | |
| 39 | + @Parameter(name = "id", description = "区域编号", required = true, example = "150000") | |
| 40 | + public CommonResult<List<AreaNodeSimpleRespVO>> getChildren(@RequestParam("id") Integer id) { | |
| 41 | 41 | Area area = AreaUtils.getArea(id); |
| 42 | - Assert.notNull(area, String.format("获取不到 id : %d的区域", id)); | |
| 42 | + Assert.notNull(area, String.format("获取不到 id : %d 的区域", id)); | |
| 43 | 43 | return success(AreaConvert.INSTANCE.convertList2(area.getChildren())); |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | - @PostMapping("/list") | |
| 47 | - @Operation(summary = "通过区域ids获得地区列表") | |
| 48 | - public CommonResult<List<LazyAreaNodeRespVO>> list(@RequestBody Set<Integer> areaIds) { | |
| 49 | - List<Area> areaList = new ArrayList<>(areaIds.size()); | |
| 50 | - for (Integer areaId : areaIds) { | |
| 46 | + // 4)方法改成 getAreaChildrenList 获得子节点们;5)url 可以已改成 children-list | |
| 47 | + //@芋艿 是不是叫 getAreaListByIds 更合适。 因为不一定是子节点。 用于前端树选择获取缓存数据。 见 <el-tree-select :cache-data="areaCache"> | |
| 48 | + @GetMapping("/get-by-ids") | |
| 49 | + @Operation(summary = "通过区域 ids 获得地区列表") | |
| 50 | + @Parameter(name = "ids", description = "区域编号 ids", required = true, example = "1,150000") | |
| 51 | + public CommonResult<List<AreaNodeSimpleRespVO>> getAreaListByIds(@RequestParam("ids") Set<Integer> ids) { | |
| 52 | + List<Area> areaList = new ArrayList<>(ids.size()); | |
| 53 | + for (Integer areaId : ids) { | |
| 51 | 54 | areaList.add(AreaUtils.getArea(areaId)); |
| 52 | 55 | } |
| 53 | 56 | return success(AreaConvert.INSTANCE.convertList2(areaList)); | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/LazyAreaNodeRespVO.java renamed to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/ip/vo/AreaNodeSimpleRespVO.java
| ... | ... | @@ -3,12 +3,9 @@ package cn.iocoder.yudao.module.system.controller.admin.ip.vo; |
| 3 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | 4 | import lombok.Data; |
| 5 | 5 | |
| 6 | -/** | |
| 7 | - * @author jason | |
| 8 | - */ | |
| 9 | -@Schema(description = "管理后台 - 懒加载地区节点 Response VO") | |
| 6 | +@Schema(description = "管理后台 - 简洁的地区节点 Response VO") | |
| 10 | 7 | @Data |
| 11 | -public class LazyAreaNodeRespVO { | |
| 8 | +public class AreaNodeSimpleRespVO { | |
| 12 | 9 | |
| 13 | 10 | @Schema(description = "编号", required = true, example = "110000") |
| 14 | 11 | private Integer id; |
| ... | ... | @@ -16,6 +13,7 @@ public class LazyAreaNodeRespVO { |
| 16 | 13 | @Schema(description = "名字", required = true, example = "北京") |
| 17 | 14 | private String name; |
| 18 | 15 | |
| 19 | - @Schema(description = "是否叶子节点", required = true, example = "false") | |
| 20 | - private Boolean leaf = Boolean.FALSE; | |
| 16 | + @Schema(description = "是否叶子节点", required = false, example = "false") | |
| 17 | + private Boolean leaf; | |
| 18 | + | |
| 21 | 19 | } | ... | ... |
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; |
| 3 | 3 | import cn.iocoder.yudao.framework.ip.core.Area; |
| 4 | 4 | import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; |
| 5 | 5 | import cn.iocoder.yudao.module.system.controller.admin.ip.vo.AreaNodeRespVO; |
| 6 | -import cn.iocoder.yudao.module.system.controller.admin.ip.vo.LazyAreaNodeRespVO; | |
| 6 | +import cn.iocoder.yudao.module.system.controller.admin.ip.vo.AreaNodeSimpleRespVO; | |
| 7 | 7 | import org.mapstruct.Mapper; |
| 8 | 8 | import org.mapstruct.Mapping; |
| 9 | -import org.mapstruct.Named; | |
| 10 | 9 | import org.mapstruct.factory.Mappers; |
| 11 | -import org.springframework.context.annotation.Lazy; | |
| 12 | 10 | |
| 13 | 11 | import java.util.List; |
| 14 | 12 | import java.util.Objects; |
| ... | ... | @@ -20,12 +18,13 @@ public interface AreaConvert { |
| 20 | 18 | |
| 21 | 19 | List<AreaNodeRespVO> convertList(List<Area> list); |
| 22 | 20 | |
| 23 | - List<LazyAreaNodeRespVO> convertList2(List<Area> list); | |
| 21 | + List<AreaNodeSimpleRespVO> convertList2(List<Area> list); | |
| 24 | 22 | |
| 25 | 23 | @Mapping(source = "type", target = "leaf") |
| 26 | - LazyAreaNodeRespVO convert(Area area); | |
| 24 | + AreaNodeSimpleRespVO convert(Area area); | |
| 27 | 25 | |
| 28 | - default Boolean convertAreaType(Integer type){ | |
| 29 | - return Objects.equals(AreaTypeEnum.DISTRICT.getType(),type); | |
| 26 | + default Boolean convertAreaType(Integer type) { | |
| 27 | + return Objects.equals(AreaTypeEnum.DISTRICT.getType(), type); | |
| 30 | 28 | } |
| 29 | + | |
| 31 | 30 | } | ... | ... |