Commit d4417d2474b460bf5fccf807596609f01da5fe7d

Authored by YunaiV
1 parent 057952bd

code review:积分、优惠劵、佣金等逻辑

Showing 27 changed files with 47 additions and 74 deletions
sql/mysql/member.sql deleted
1   --- 查询上级菜单、排序
2   -SELECT parent_id, sort
3   -INTO @parentId, @sort
4   -FROM system_menu
5   -WHERE name = '用户等级修改'
6   -LIMIT 1;
7   --- 新增 按钮权限
8   -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
9   -VALUES ('用户积分修改', 'member:user:update-point', 3, @sort + 1, @parentId, '', '', '', 0);
10   -INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status)
11   -VALUES ('用户余额修改', 'member:user:update-balance', 3, @sort + 2, @parentId, '', '', '', 0);
sql/mysql/trade_order.sql deleted
1   --- 增加字段
2   -ALTER TABLE trade_order
3   - ADD COLUMN brokerage_user_id bigint NULL COMMENT '推广人编号' AFTER comment_status;
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
... ... @@ -146,9 +146,7 @@ public class LocalDateTimeUtils {
146 146 * @return 月份的开始时间
147 147 */
148 148 public static LocalDateTime beginOfMonth(LocalDateTime date) {
149   - return date
150   - .with(TemporalAdjusters.firstDayOfMonth())
151   - .with(LocalTime.MIN);
  149 + return date.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
152 150 }
153 151  
154 152 /**
... ... @@ -159,8 +157,7 @@ public class LocalDateTimeUtils {
159 157 * @return 月份的结束时间
160 158 */
161 159 public static LocalDateTime endOfMonth(LocalDateTime date) {
162   - return date
163   - .with(TemporalAdjusters.lastDayOfMonth())
164   - .with(LocalTime.MAX);
  160 + return date.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
165 161 }
  162 +
166 163 }
... ...
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java
... ... @@ -22,12 +22,16 @@ public interface ProductSpuApi {
22 22 List<ProductSpuRespDTO> getSpuList(Collection<Long> ids);
23 23  
24 24 /**
25   - * 批量查询 SPU 数组,并且校验是否 SPU 是否有效
  25 + * 批量查询 SPU 数组,并且校验是否 SPU 是否有效。
  26 + *
  27 + * 如下情况,视为无效:
  28 + * 1. 商品编号不存在
  29 + * 2. 商品被禁用
26 30 *
27 31 * @param ids SPU 编号列表
28 32 * @return SPU 数组
29 33 */
30   - List<ProductSpuRespDTO> getSpuListAndValidate(Collection<Long> ids);
  34 + List<ProductSpuRespDTO> validateSpuList(Collection<Long> ids);
31 35  
32 36 /**
33 37 * 获得 SPU
... ... @@ -36,12 +40,4 @@ public interface ProductSpuApi {
36 40 */
37 41 ProductSpuRespDTO getSpu(Long id);
38 42  
39   - /**
40   - * 校验商品是否有效。如下情况,视为无效:
41   - * 1. 商品编号不存在
42   - * 2. 商品被禁用
43   - *
44   - * @param ids 商品编号数组
45   - */
46   - void validateSpuList(Collection<Long> ids);
47 43 }
... ...
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
... ... @@ -34,7 +34,7 @@ public interface ErrorCodeConstants {
34 34 // ========== 商品 SPU 1-008-005-000 ==========
35 35 ErrorCode SPU_NOT_EXISTS = new ErrorCode(1_008_005_000, "商品 SPU 不存在");
36 36 ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1_008_005_001, "商品分类不正确,原因:必须使用第二级的商品分类及以下");
37   - ErrorCode SPU_NOT_ENABLE = new ErrorCode(1_008_005_002, "商品 SPU【[]】不处于上架状态");
  37 + ErrorCode SPU_NOT_ENABLE = new ErrorCode(1_008_005_002, "商品 SPU【{}】不处于上架状态");
38 38 ErrorCode SPU_NOT_RECYCLE = new ErrorCode(1_008_005_003, "商品 SPU 不处于回收站状态");
39 39  
40 40 // ========== 商品 SKU 1-008-006-000 ==========
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java
... ... @@ -34,7 +34,7 @@ public class ProductSpuApiImpl implements ProductSpuApi {
34 34 }
35 35  
36 36 @Override
37   - public List<ProductSpuRespDTO> getSpuListAndValidate(Collection<Long> ids) {
  37 + public List<ProductSpuRespDTO> validateSpuList(Collection<Long> ids) {
38 38 return ProductSpuConvert.INSTANCE.convertList2(spuService.validateSpuList(ids));
39 39 }
40 40  
... ... @@ -43,9 +43,4 @@ public class ProductSpuApiImpl implements ProductSpuApi {
43 43 return ProductSpuConvert.INSTANCE.convert02(spuService.getSpu(id));
44 44 }
45 45  
46   - @Override
47   - public void validateSpuList(Collection<Long> ids) {
48   - spuService.validateSpuList(ids);
49   - }
50   -
51 46 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java
... ... @@ -109,8 +109,8 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
109 109 return;
110 110 }
111 111 // 获得商品分类信息
112   - List<ProductCategoryDO> categoryList = productCategoryMapper.selectBatchIds(ids);
113   - Map<Long, ProductCategoryDO> categoryMap = CollectionUtils.convertMap(categoryList, ProductCategoryDO::getId);
  112 + List<ProductCategoryDO> list = productCategoryMapper.selectBatchIds(ids);
  113 + Map<Long, ProductCategoryDO> categoryMap = CollectionUtils.convertMap(list, ProductCategoryDO::getId);
114 114 // 校验
115 115 ids.forEach(id -> {
116 116 ProductCategoryDO category = categoryMap.get(id);
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
... ... @@ -146,8 +146,8 @@ public class ProductSpuServiceImpl implements ProductSpuService {
146 146 return Collections.emptyList();
147 147 }
148 148 // 获得商品信息
149   - List<ProductSpuDO> spuList = productSpuMapper.selectBatchIds(ids);
150   - Map<Long, ProductSpuDO> spuMap = CollectionUtils.convertMap(spuList, ProductSpuDO::getId);
  149 + List<ProductSpuDO> list = productSpuMapper.selectBatchIds(ids);
  150 + Map<Long, ProductSpuDO> spuMap = CollectionUtils.convertMap(list, ProductSpuDO::getId);
151 151 // 校验
152 152 ids.forEach(id -> {
153 153 ProductSpuDO spu = spuMap.get(id);
... ... @@ -158,8 +158,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
158 158 throw exception(SPU_NOT_ENABLE, spu.getName());
159 159 }
160 160 });
161   -
162   - return spuList;
  161 + return list;
163 162 }
164 163  
165 164 @Override
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
... ... @@ -178,8 +178,9 @@ public class CouponServiceImpl implements CouponService {
178 178 }
179 179  
180 180 @Override
  181 + // TODO @疯狂:搞个事务;
181 182 public void takeCouponByRegister(Long userId) {
182   - List<CouponTemplateDO> templates = couponTemplateService.getCouponTemplateByTakeType(CouponTakeTypeEnum.REGISTER);
  183 + List<CouponTemplateDO> templates = couponTemplateService.getCouponTemplateListByTakeType(CouponTakeTypeEnum.REGISTER);
183 184 for (CouponTemplateDO template : templates) {
184 185 takeCoupon(template.getId(), CollUtil.newHashSet(userId), CouponTakeTypeEnum.REGISTER);
185 186 }
... ... @@ -226,16 +227,15 @@ public class CouponServiceImpl implements CouponService {
226 227  
227 228 @Override
228 229 public Map<Long, Boolean> getUserCanCanTakeMap(Long userId, List<CouponTemplateDO> templates) {
  230 + // 1. 未登录时,都显示可以领取
229 231 Map<Long, Boolean> userCanTakeMap = convertMap(templates, CouponTemplateDO::getId, templateId -> true);
230   - // 未登录时,都显示可以领取
231 232 if (userId == null) {
232 233 return userCanTakeMap;
233 234 }
234 235  
235   - // 过滤领取数量无限制的
  236 + // 2.1 过滤领取数量无限制的
236 237 Set<Long> templateIds = convertSet(templates, CouponTemplateDO::getId, template -> template.getTakeLimitCount() != -1);
237   -
238   - // 检查用户领取的数量是否超过限制
  238 + // 2.2 检查用户领取的数量是否超过限制
239 239 if (CollUtil.isNotEmpty(templateIds)) {
240 240 Map<Long, Integer> couponTakeCountMap = this.getTakeCountMapByTemplateIds(templateIds, userId);
241 241 for (CouponTemplateDO template : templates) {
... ... @@ -243,7 +243,6 @@ public class CouponServiceImpl implements CouponService {
243 243 userCanTakeMap.put(template.getId(), takeCount == null || takeCount < template.getTakeLimitCount());
244 244 }
245 245 }
246   -
247 246 return userCanTakeMap;
248 247 }
249 248  
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateService.java
... ... @@ -77,7 +77,7 @@ public interface CouponTemplateService {
77 77 * @param takeType 领取方式
78 78 * @return 优惠券模板列表
79 79 */
80   - List<CouponTemplateDO> getCouponTemplateByTakeType(CouponTakeTypeEnum takeType);
  80 + List<CouponTemplateDO> getCouponTemplateListByTakeType(CouponTakeTypeEnum takeType);
81 81  
82 82 /**
83 83 * 获得优惠券模板列表
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java
... ... @@ -116,7 +116,7 @@ public class CouponTemplateServiceImpl implements CouponTemplateService {
116 116 }
117 117  
118 118 @Override
119   - public List<CouponTemplateDO> getCouponTemplateByTakeType(CouponTakeTypeEnum takeType) {
  119 + public List<CouponTemplateDO> getCouponTemplateListByTakeType(CouponTakeTypeEnum takeType) {
120 120 return couponTemplateMapper.selectListByTakeType(takeType.getValue());
121 121 }
122 122  
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java
... ... @@ -109,8 +109,8 @@ public class TradeOrderDO extends BaseDO {
109 109  
110 110 /**
111 111 * 推广人编号
112   - * {@link BrokerageUserDO#getId()}
113   - * {@link MemberUserRespDTO#getId()}
  112 + *
  113 + * 关联 {@link BrokerageUserDO#getId()} 字段,即 {@link MemberUserRespDTO#getId()} 字段
114 114 */
115 115 private Long brokerageUserId;
116 116  
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageUserServiceImpl.java
... ... @@ -229,6 +229,10 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
229 229 // 生成推广员编号列表
230 230 List<Long> bindUserIds = buildBindUserIdsByLevel(userId, pageReqVO.getLevel());
231 231  
  232 + // TODO @疯狂:情况一和情况二,可以合并哈;
  233 + // 如果有 nickname 的时候,相当于提前查询 users,然后 nickname 过滤掉 bindUserIds;
  234 + // 之后,继续使用 selectSummaryPageByUserId 里面 in bindUserIds 查询;
  235 +
232 236 // 情况一:没有昵称过滤条件时,直接使用数据库的分页查询
233 237 if (StrUtil.isBlank(pageReqVO.getNickname())) {
234 238 // 1.1 分页查询
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
... ... @@ -236,6 +236,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
236 236 order.setReceiverName(createReqVO.getReceiverName()).setReceiverMobile(createReqVO.getReceiverMobile());
237 237 order.setPickUpVerifyCode(RandomUtil.randomNumbers(8)); // 随机一个核销码,长度为 8 位
238 238 }
  239 + // TODO @疯狂:是不是可以在这里设置下推广人哈;
239 240 tradeOrderMapper.insert(order);
240 241 return order;
241 242 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImpl.java
... ... @@ -82,7 +82,7 @@ public class TradePriceServiceImpl implements TradePriceService {
82 82  
83 83 private List<ProductSpuRespDTO> checkSpuList(List<ProductSkuRespDTO> skuList) {
84 84 // 获得商品 SPU 数组
85   - return productSpuApi.getSpuListAndValidate(convertSet(skuList, ProductSkuRespDTO::getSpuId));
  85 + return productSpuApi.validateSpuList(convertSet(skuList, ProductSkuRespDTO::getSpuId));
86 86 }
87 87  
88 88 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePointGiveCalculatorTest.java
... ... @@ -17,6 +17,7 @@ import static java.util.Arrays.asList;
17 17 import static org.junit.jupiter.api.Assertions.assertEquals;
18 18 import static org.mockito.Mockito.when;
19 19  
  20 +// TODO 芋艿:晚点 review
20 21 /**
21 22 * {@link TradePointGiveCalculator} 的单元测试类
22 23 *
... ... @@ -95,4 +96,4 @@ public class TradePointGiveCalculatorTest extends BaseMockitoUnitTest {
95 96 assertEquals(orderItem04.getPrice(), 60);
96 97 assertEquals(orderItem04.getGivePoint(), 100); // 全局积分 + SKU 积分,但是未选中
97 98 }
98   -}
99 99 \ No newline at end of file
  100 +}
... ...
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePointUsePriceCalculatorTest.java
... ... @@ -21,6 +21,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
21 21 import static org.junit.jupiter.api.Assertions.assertTrue;
22 22 import static org.mockito.Mockito.when;
23 23  
  24 +// TODO 芋艿:晚点 review
24 25 /**
25 26 * {@link TradePointUsePriceCalculator } 的单元测试类
26 27 *
... ... @@ -329,4 +330,4 @@ public class TradePointUsePriceCalculatorTest extends BaseMockitoUnitTest {
329 330 // 断言:Promotion 部分
330 331 assertEquals(result.getPromotions().size(), 0);
331 332 }
332   -}
333 333 \ No newline at end of file
  334 +}
... ...
yudao-module-member/yudao-module-member-api/pom.xml
... ... @@ -22,11 +22,13 @@
22 22 <artifactId>yudao-common</artifactId>
23 23 </dependency>
24 24  
  25 + <!-- TODO @疯狂:biz 引入哈;api 保持低依赖 -->
25 26 <dependency>
26 27 <groupId>cn.iocoder.boot</groupId>
27 28 <artifactId>yudao-spring-boot-starter-mq</artifactId>
28 29 <scope>compile</scope>
29 30 </dependency>
  31 +
30 32 <!-- 参数校验 -->
31 33 <dependency>
32 34 <groupId>org.springframework.boot</groupId>
... ...
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java
... ... @@ -38,6 +38,7 @@ public interface ErrorCodeConstants {
38 38 //========== 签到配置 1-004-009-000 ==========
39 39 ErrorCode SIGN_IN_CONFIG_NOT_EXISTS = new ErrorCode(1_004_009_000, "签到天数规则不存在");
40 40 ErrorCode SIGN_IN_CONFIG_EXISTS = new ErrorCode(1_004_009_001, "签到天数规则已存在");
  41 + // TODO @疯狂:这个可以用 validator 去做;通过在 BaseVO 里,增加一个 @AssertTrue 注解的方式
41 42 ErrorCode SIGN_IN_CONFIG_AWARD_EMPTY = new ErrorCode(1_004_009_002, "签到奖励积分和经验不能同时为空");
42 43  
43 44 //========== 签到配置 1-004-010-000 ==========
... ...
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdateLevelReqVO.java
... ... @@ -7,7 +7,7 @@ import lombok.ToString;
7 7 import javax.validation.constraints.NotBlank;
8 8 import javax.validation.constraints.NotNull;
9 9  
10   -@Schema(description = "管理后台 - 会员用户 修改等级 Request VO")
  10 +@Schema(description = "管理后台 - 用户修改等级 Request VO")
11 11 @Data
12 12 @ToString(callSuper = true)
13 13 public class MemberUserUpdateLevelReqVO {
... ...
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/vo/MemberUserUpdatePointReqVO.java
... ... @@ -6,7 +6,7 @@ import lombok.ToString;
6 6  
7 7 import javax.validation.constraints.NotNull;
8 8  
9   -@Schema(description = "管理后台 - 会员用户 修改积分 Request VO")
  9 +@Schema(description = "管理后台 - 用户修改积分 Request VO")
10 10 @Data
11 11 @ToString(callSuper = true)
12 12 public class MemberUserUpdatePointReqVO {
... ...
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/producer/user/RegisterCouponProducer.java
... ... @@ -7,6 +7,7 @@ import org.springframework.stereotype.Component;
7 7  
8 8 import javax.annotation.Resource;
9 9  
  10 +// TODO @疯狂:发 UserCreateMessage;解耦,然后优惠劵监听到,去发卷;
10 11 /**
11 12 * 新人券发放 Producer
12 13 *
... ...
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java
... ... @@ -95,6 +95,7 @@ public class MemberUserServiceImpl implements MemberUserService {
95 95 memberUserMapper.insert(user);
96 96  
97 97 // 发送 MQ 消息,发放新人券
  98 + // TODO @疯狂:事务结束后,在发送 MQ 消息;避免出现消息已经发了,事务没提交,或者回滚了
98 99 registerCouponProducer.sendMailSendMessage(user.getId());
99 100 return user;
100 101 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/wallet/PayWalletController.java
... ... @@ -29,11 +29,12 @@ public class PayWalletController {
29 29 @Resource
30 30 private PayWalletService payWalletService;
31 31  
32   - @GetMapping("/user-wallet")
  32 + @GetMapping("/get")
33 33 @PreAuthorize("@ss.hasPermission('pay:wallet:query')")
34 34 @Operation(summary = "获得用户钱包明细")
35   - public CommonResult<PayWalletRespVO> getByUser(PayWalletUserReqVO reqVO) {
36   - PayWalletDO wallet = payWalletService.getWalletByUserIdAndType(reqVO.getUserId(), reqVO.getUserType());
  35 + public CommonResult<PayWalletRespVO> getWallet(PayWalletUserReqVO reqVO) {
  36 + PayWalletDO wallet = payWalletService.getOrCreateWallet(reqVO.getUserId(), reqVO.getUserType());
37 37 return success(PayWalletConvert.INSTANCE.convert02(wallet));
38 38 }
  39 +
39 40 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/wallet/vo/PayWalletUserReqVO.java
... ... @@ -19,4 +19,5 @@ public class PayWalletUserReqVO {
19 19 @NotNull(message = "用户类型不能为空")
20 20 @InEnum(value = UserTypeEnum.class, message = "用户类型必须是 {value}")
21 21 private Integer userType;
  22 +
22 23 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java
... ... @@ -87,12 +87,4 @@ public interface PayWalletService {
87 87 */
88 88 void unFreezePrice(Long id, Integer price);
89 89  
90   - /**
91   - * 获得用户的钱包明细
92   - *
93   - * @param userId 用户编号
94   - * @param userType 用户类型
95   - * @return 用户的钱包明细
96   - */
97   - PayWalletDO getWalletByUserIdAndType(Long userId, Integer userType);
98 90 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java
... ... @@ -195,9 +195,4 @@ public class PayWalletServiceImpl implements PayWalletService {
195 195 }
196 196 }
197 197  
198   - @Override
199   - public PayWalletDO getWalletByUserIdAndType(Long userId, Integer userType) {
200   - return walletMapper.selectByUserIdAndType(userId, userType);
201   - }
202   -
203 198 }
... ...