Commit d874346d4298f66c14da529277eed7254f3b5a30
Committed by
Gitee
!649 Review代码修改
Merge pull request !649 from 疯狂的世界/feature/mall_product
Showing
15 changed files
with
139 additions
and
158 deletions
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
| ... | ... | @@ -78,6 +78,13 @@ public class CollectionUtils { |
| 78 | 78 | return from.stream().filter(filter).map(func).filter(Objects::nonNull).collect(Collectors.toSet()); |
| 79 | 79 | } |
| 80 | 80 | |
| 81 | + public static <T, K> Map<K, T> convertMapByFilter(Collection<T> from, Predicate<T> filter, Function<T, K> keyFunc) { | |
| 82 | + if (CollUtil.isEmpty(from)) { | |
| 83 | + return new HashMap<>(); | |
| 84 | + } | |
| 85 | + return from.stream().filter(filter).collect(Collectors.toMap(keyFunc, v -> v)); | |
| 86 | + } | |
| 87 | + | |
| 81 | 88 | public static <T, K> Map<K, T> convertMap(Collection<T> from, Function<T, K> keyFunc) { |
| 82 | 89 | if (CollUtil.isEmpty(from)) { |
| 83 | 90 | return new HashMap<>(); | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/mq/consumer/coupon/RegisterCouponSendConsumer.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/mq/consumer/coupon/UserCreateConsumer.java
| 1 | 1 | package cn.iocoder.yudao.module.promotion.mq.consumer.coupon; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener; |
| 4 | -import cn.iocoder.yudao.module.member.mq.message.user.RegisterCouponSendMessage; | |
| 4 | +import cn.iocoder.yudao.module.promotion.mq.message.coupon.UserCreateMessage; | |
| 5 | 5 | import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; |
| 6 | 6 | import lombok.extern.slf4j.Slf4j; |
| 7 | 7 | import org.springframework.stereotype.Component; |
| ... | ... | @@ -9,19 +9,19 @@ import org.springframework.stereotype.Component; |
| 9 | 9 | import javax.annotation.Resource; |
| 10 | 10 | |
| 11 | 11 | /** |
| 12 | - * 针对 {@link RegisterCouponSendMessage} 的消费者 | |
| 12 | + * 针对 {@link UserCreateMessage} 的消费者 | |
| 13 | 13 | * |
| 14 | 14 | * @author owen |
| 15 | 15 | */ |
| 16 | 16 | @Component |
| 17 | 17 | @Slf4j |
| 18 | -public class RegisterCouponSendConsumer extends AbstractStreamMessageListener<RegisterCouponSendMessage> { | |
| 18 | +public class UserCreateConsumer extends AbstractStreamMessageListener<UserCreateMessage> { | |
| 19 | 19 | |
| 20 | 20 | @Resource |
| 21 | 21 | private CouponService couponService; |
| 22 | 22 | |
| 23 | 23 | @Override |
| 24 | - public void onMessage(RegisterCouponSendMessage message) { | |
| 24 | + public void onMessage(UserCreateMessage message) { | |
| 25 | 25 | log.info("[onMessage][消息内容({})]", message); |
| 26 | 26 | couponService.takeCouponByRegister(message.getUserId()); |
| 27 | 27 | } | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/mq/message/coupon/UserCreateMessage.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.mq.message.coupon; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage; | |
| 4 | +import lombok.Data; | |
| 5 | +import lombok.EqualsAndHashCode; | |
| 6 | + | |
| 7 | +import javax.validation.constraints.NotNull; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * 会员用户创建消息 | |
| 11 | + * | |
| 12 | + * @author owen | |
| 13 | + */ | |
| 14 | +@Data | |
| 15 | +@EqualsAndHashCode(callSuper = true) | |
| 16 | +public class UserCreateMessage extends AbstractStreamMessage { | |
| 17 | + | |
| 18 | + /** | |
| 19 | + * 用户编号 | |
| 20 | + */ | |
| 21 | + @NotNull(message = "用户编号不能为空") | |
| 22 | + private Long userId; | |
| 23 | + | |
| 24 | + @Override | |
| 25 | + public String getStreamKey() { | |
| 26 | + return "member.create.send"; | |
| 27 | + } | |
| 28 | + | |
| 29 | +} | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
| ... | ... | @@ -178,7 +178,7 @@ public class CouponServiceImpl implements CouponService { |
| 178 | 178 | } |
| 179 | 179 | |
| 180 | 180 | @Override |
| 181 | - // TODO @疯狂:搞个事务; | |
| 181 | + @Transactional(rollbackFor = Exception.class) | |
| 182 | 182 | public void takeCouponByRegister(Long userId) { |
| 183 | 183 | List<CouponTemplateDO> templates = couponTemplateService.getCouponTemplateListByTakeType(CouponTakeTypeEnum.REGISTER); |
| 184 | 184 | for (CouponTemplateDO template : templates) { | ... | ... |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
| ... | ... | @@ -81,6 +81,7 @@ public interface ErrorCodeConstants { |
| 81 | 81 | ErrorCode BROKERAGE_BIND_MODE_REGISTER = new ErrorCode(1_011_007_005, "只有在注册时可以绑定"); |
| 82 | 82 | ErrorCode BROKERAGE_BIND_OVERRIDE = new ErrorCode(1_011_007_006, "已绑定了推广人"); |
| 83 | 83 | ErrorCode BROKERAGE_BIND_LOOP = new ErrorCode(1_011_007_007, "下级不能绑定自己的上级"); |
| 84 | + ErrorCode BROKERAGE_USER_LEVEL_NOT_SUPPORT = new ErrorCode(1_011_007_008, "目前只支持 level 小于等于 2"); | |
| 84 | 85 | |
| 85 | 86 | |
| 86 | 87 | // ========== 分销提现 模块 1-011-008-000 ========== | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/BrokerageUserMapper.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.dal.mysql.brokerage; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.convert.Convert; | |
| 3 | 4 | import cn.hutool.core.lang.Assert; |
| 4 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | 6 | import cn.iocoder.yudao.framework.common.pojo.SortingField; |
| ... | ... | @@ -17,6 +18,8 @@ import org.apache.ibatis.annotations.Param; |
| 17 | 18 | import org.apache.ibatis.annotations.Select; |
| 18 | 19 | |
| 19 | 20 | import java.time.LocalDateTime; |
| 21 | +import java.util.Collection; | |
| 22 | +import java.util.Collections; | |
| 20 | 23 | import java.util.List; |
| 21 | 24 | |
| 22 | 25 | /** |
| ... | ... | @@ -27,12 +30,12 @@ import java.util.List; |
| 27 | 30 | @Mapper |
| 28 | 31 | public interface BrokerageUserMapper extends BaseMapperX<BrokerageUserDO> { |
| 29 | 32 | |
| 30 | - default PageResult<BrokerageUserDO> selectPage(BrokerageUserPageReqVO reqVO, List<Long> bindUserIds) { | |
| 33 | + default PageResult<BrokerageUserDO> selectPage(BrokerageUserPageReqVO reqVO, List<Long> ids) { | |
| 31 | 34 | return selectPage(reqVO, new LambdaQueryWrapperX<BrokerageUserDO>() |
| 35 | + .inIfPresent(BrokerageUserDO::getId, ids) | |
| 32 | 36 | .eqIfPresent(BrokerageUserDO::getBrokerageEnabled, reqVO.getBrokerageEnabled()) |
| 33 | 37 | .betweenIfPresent(BrokerageUserDO::getCreateTime, reqVO.getCreateTime()) |
| 34 | 38 | .betweenIfPresent(BrokerageUserDO::getBindUserTime, reqVO.getBindUserTime()) |
| 35 | - .inIfPresent(BrokerageUserDO::getBindUserId, bindUserIds) | |
| 36 | 39 | .orderByDesc(BrokerageUserDO::getId)); |
| 37 | 40 | } |
| 38 | 41 | |
| ... | ... | @@ -124,11 +127,6 @@ public interface BrokerageUserMapper extends BaseMapperX<BrokerageUserDO> { |
| 124 | 127 | .set(BrokerageUserDO::getBrokerageEnabled, false).set(BrokerageUserDO::getBrokerageTime, null)); |
| 125 | 128 | } |
| 126 | 129 | |
| 127 | - default Long selectCountByBindUserIdIn(List<Long> bindUserIds) { | |
| 128 | - return selectCount(new LambdaQueryWrapperX<BrokerageUserDO>() | |
| 129 | - .inIfPresent(BrokerageUserDO::getBindUserId, bindUserIds)); | |
| 130 | - } | |
| 131 | - | |
| 132 | 130 | @Select("SELECT bind_user_id AS id, COUNT(1) AS brokerageUserCount FROM trade_brokerage_user " + |
| 133 | 131 | "WHERE bind_user_id IS NOT NULL AND deleted = FALSE " + |
| 134 | 132 | "AND bind_user_time BETWEEN #{beginTime} AND #{endTime} " + |
| ... | ... | @@ -143,32 +141,21 @@ public interface BrokerageUserMapper extends BaseMapperX<BrokerageUserDO> { |
| 143 | 141 | * |
| 144 | 142 | * @param bizType 业务类型 |
| 145 | 143 | * @param status 状态 |
| 146 | - * @param bindUserIds 绑定用户编号列表 | |
| 144 | + * @param ids 用户编号列表 | |
| 147 | 145 | * @param sortingField 排序字段 |
| 148 | 146 | * @return 下级分销统计分页列表 |
| 149 | 147 | */ |
| 150 | 148 | IPage<AppBrokerageUserChildSummaryRespVO> selectSummaryPageByUserId(Page<?> page, |
| 151 | 149 | @Param("bizType") Integer bizType, |
| 152 | 150 | @Param("status") Integer status, |
| 153 | - @Param("bindUserIds") List<Long> bindUserIds, | |
| 151 | + @Param("ids") Collection<Long> ids, | |
| 154 | 152 | @Param("sortingField") SortingField sortingField); |
| 155 | 153 | |
| 156 | - /** | |
| 157 | - * 下级分销统计(不分页) | |
| 158 | - * | |
| 159 | - * @param bizType 业务类型 | |
| 160 | - * @param status 状态 | |
| 161 | - * @param bindUserIds 绑定用户编号列表 | |
| 162 | - * @param sortingField 排序字段 | |
| 163 | - * @return 下级分销统计列表 | |
| 164 | - */ | |
| 165 | - List<AppBrokerageUserChildSummaryRespVO> selectSummaryListByUserId(@Param("bizType") Integer bizType, | |
| 166 | - @Param("status") Integer status, | |
| 167 | - @Param("bindUserIds") List<Long> bindUserIds, | |
| 168 | - @Param("sortingField") SortingField sortingField); | |
| 169 | - | |
| 170 | - default List<BrokerageUserDO> selectListByBindUserId(Long bindUserId) { | |
| 171 | - return selectList(BrokerageUserDO::getBindUserId, bindUserId); | |
| 154 | + default List<Long> selectIdListByBindUserIdIn(Collection<Long> bindUserIds) { | |
| 155 | + return Convert.toList(Long.class, | |
| 156 | + selectObjs(new LambdaQueryWrapperX<BrokerageUserDO>() | |
| 157 | + .select(Collections.singletonList(BrokerageUserDO::getId)) | |
| 158 | + .in(BrokerageUserDO::getBindUserId, bindUserIds))); | |
| 172 | 159 | } |
| 173 | 160 | |
| 174 | 161 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageUserServiceImpl.java
| ... | ... | @@ -31,10 +31,9 @@ import org.springframework.validation.annotation.Validated; |
| 31 | 31 | import javax.annotation.Resource; |
| 32 | 32 | import java.time.LocalDateTime; |
| 33 | 33 | import java.util.*; |
| 34 | -import java.util.stream.Collectors; | |
| 35 | 34 | |
| 36 | 35 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 37 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | |
| 36 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMapByFilter; | |
| 38 | 37 | import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; |
| 39 | 38 | |
| 40 | 39 | /** |
| ... | ... | @@ -67,8 +66,12 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { |
| 67 | 66 | |
| 68 | 67 | @Override |
| 69 | 68 | public PageResult<BrokerageUserDO> getBrokerageUserPage(BrokerageUserPageReqVO pageReqVO) { |
| 70 | - List<Long> bindUserIds = buildBindUserIdsByLevel(pageReqVO.getBindUserId(), pageReqVO.getLevel()); | |
| 71 | - return brokerageUserMapper.selectPage(pageReqVO, bindUserIds); | |
| 69 | + List<Long> childIds = getChildUserIdsByLevel(pageReqVO.getBindUserId(), pageReqVO.getLevel()); | |
| 70 | + // 有”绑定用户编号“查询条件时,没有查到下级会员,直接返回空 | |
| 71 | + if (pageReqVO.getBindUserId() != null && CollUtil.isEmpty(childIds)) { | |
| 72 | + return PageResult.empty(); | |
| 73 | + } | |
| 74 | + return brokerageUserMapper.selectPage(pageReqVO, childIds); | |
| 72 | 75 | } |
| 73 | 76 | |
| 74 | 77 | @Override |
| ... | ... | @@ -154,11 +157,8 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { |
| 154 | 157 | |
| 155 | 158 | @Override |
| 156 | 159 | public Long getBrokerageUserCountByBindUserId(Long bindUserId, Integer level) { |
| 157 | - List<Long> bindUserIds = buildBindUserIdsByLevel(bindUserId, level); | |
| 158 | - if (CollUtil.isEmpty(bindUserIds)) { | |
| 159 | - return 0L; | |
| 160 | - } | |
| 161 | - return brokerageUserMapper.selectCountByBindUserIdIn(bindUserIds); | |
| 160 | + List<Long> childIds = getChildUserIdsByLevel(bindUserId, level); | |
| 161 | + return (long) CollUtil.size(childIds); | |
| 162 | 162 | } |
| 163 | 163 | |
| 164 | 164 | @Override |
| ... | ... | @@ -226,70 +226,29 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { |
| 226 | 226 | |
| 227 | 227 | @Override |
| 228 | 228 | public PageResult<AppBrokerageUserChildSummaryRespVO> getBrokerageUserChildSummaryPage(AppBrokerageUserChildSummaryPageReqVO pageReqVO, Long userId) { |
| 229 | - // 生成推广员编号列表 | |
| 230 | - List<Long> bindUserIds = buildBindUserIdsByLevel(userId, pageReqVO.getLevel()); | |
| 231 | - | |
| 232 | - // TODO @疯狂:情况一和情况二,可以合并哈; | |
| 233 | - // 如果有 nickname 的时候,相当于提前查询 users,然后 nickname 过滤掉 bindUserIds; | |
| 234 | - // 之后,继续使用 selectSummaryPageByUserId 里面 in bindUserIds 查询; | |
| 235 | - | |
| 236 | - // 情况一:没有昵称过滤条件时,直接使用数据库的分页查询 | |
| 237 | - if (StrUtil.isBlank(pageReqVO.getNickname())) { | |
| 238 | - // 1.1 分页查询 | |
| 239 | - IPage<AppBrokerageUserChildSummaryRespVO> pageResult = brokerageUserMapper.selectSummaryPageByUserId( | |
| 240 | - MyBatisUtils.buildPage(pageReqVO), BrokerageRecordBizTypeEnum.ORDER.getType(), | |
| 241 | - BrokerageRecordStatusEnum.SETTLEMENT.getStatus(), bindUserIds, pageReqVO.getSortingField() | |
| 242 | - ); | |
| 243 | - | |
| 244 | - // 1.2 拼接数据并返回 | |
| 245 | - List<Long> userIds = convertList(pageResult.getRecords(), AppBrokerageUserChildSummaryRespVO::getId); | |
| 246 | - Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds); | |
| 247 | - BrokerageUserConvert.INSTANCE.copyTo(pageResult.getRecords(), userMap); | |
| 248 | - return new PageResult<>(pageResult.getRecords(), pageResult.getTotal()); | |
| 249 | - } | |
| 250 | - | |
| 251 | - // 情况二:有昵称过滤条件时,需要跨模块(Member)过滤 | |
| 252 | - // 2.1 查询所有匹配的分销用户 | |
| 253 | - List<AppBrokerageUserChildSummaryRespVO> list = brokerageUserMapper.selectSummaryListByUserId( | |
| 254 | - BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus(), | |
| 255 | - bindUserIds, pageReqVO.getSortingField() | |
| 256 | - ); | |
| 257 | - if (CollUtil.isEmpty(list)) { | |
| 229 | + // 1.1 查询下级用户编号列表 | |
| 230 | + List<Long> childIds = getChildUserIdsByLevel(userId, pageReqVO.getLevel()); | |
| 231 | + if (CollUtil.isEmpty(childIds)) { | |
| 258 | 232 | return PageResult.empty(); |
| 259 | 233 | } |
| 260 | 234 | |
| 261 | - // 2.2 查出对应的用户信息 | |
| 262 | - List<MemberUserRespDTO> users = memberUserApi.getUserList(convertList(list, AppBrokerageUserChildSummaryRespVO::getId)); | |
| 263 | - if (CollUtil.isEmpty(users)) { | |
| 264 | - return PageResult.empty(); | |
| 265 | - } | |
| 266 | - | |
| 267 | - // 2.3 根据昵称过滤出用户编号 | |
| 268 | - Map<Long, MemberUserRespDTO> userMap = users.stream() | |
| 269 | - .filter(user -> StrUtil.contains(user.getNickname(), pageReqVO.getNickname())) | |
| 270 | - .collect(Collectors.toMap(MemberUserRespDTO::getId, dto -> dto)); | |
| 235 | + // 1.2 根据昵称过滤下级用户 | |
| 236 | + Map<Long, MemberUserRespDTO> userMap = convertMapByFilter(memberUserApi.getUserList(childIds), | |
| 237 | + user -> StrUtil.contains(user.getNickname(), pageReqVO.getNickname()), | |
| 238 | + MemberUserRespDTO::getId); | |
| 271 | 239 | if (CollUtil.isEmpty(userMap)) { |
| 272 | 240 | return PageResult.empty(); |
| 273 | 241 | } |
| 274 | 242 | |
| 275 | - // 2.4 根据用户编号过滤结果 | |
| 276 | - list.removeIf(vo -> !userMap.containsKey(vo.getId())); | |
| 277 | - if (CollUtil.isEmpty(list)) { | |
| 278 | - return PageResult.empty(); | |
| 279 | - } | |
| 280 | - | |
| 281 | - // 2.5 处理分页 | |
| 282 | - List<AppBrokerageUserChildSummaryRespVO> result = list.stream() | |
| 283 | - .skip((long) (pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize()) | |
| 284 | - .limit(pageReqVO.getPageSize()) | |
| 285 | - .collect(Collectors.toList()); | |
| 286 | - if (CollUtil.isEmpty(result)) { | |
| 287 | - return PageResult.empty(); | |
| 288 | - } | |
| 243 | + // 2 分页查询 | |
| 244 | + IPage<AppBrokerageUserChildSummaryRespVO> pageResult = brokerageUserMapper.selectSummaryPageByUserId( | |
| 245 | + MyBatisUtils.buildPage(pageReqVO), BrokerageRecordBizTypeEnum.ORDER.getType(), | |
| 246 | + BrokerageRecordStatusEnum.SETTLEMENT.getStatus(), userMap.keySet(), pageReqVO.getSortingField() | |
| 247 | + ); | |
| 289 | 248 | |
| 290 | - // 2.6 拼接数据并返回 | |
| 291 | - BrokerageUserConvert.INSTANCE.copyTo(result, userMap); | |
| 292 | - return new PageResult<>(result, (long) list.size()); | |
| 249 | + // 3 拼接数据并返回 | |
| 250 | + BrokerageUserConvert.INSTANCE.copyTo(pageResult.getRecords(), userMap); | |
| 251 | + return new PageResult<>(pageResult.getRecords(), pageResult.getTotal()); | |
| 293 | 252 | } |
| 294 | 253 | |
| 295 | 254 | private boolean isUserCanBind(BrokerageUserDO user) { |
| ... | ... | @@ -360,24 +319,35 @@ public class BrokerageUserServiceImpl implements BrokerageUserService { |
| 360 | 319 | } |
| 361 | 320 | |
| 362 | 321 | /** |
| 363 | - * 根据绑定用户编号,获得绑定用户编号列表 | |
| 322 | + * 根据绑定用户编号,获得下级用户编号列表 | |
| 364 | 323 | * |
| 365 | 324 | * @param bindUserId 绑定用户编号 |
| 366 | - * @param level 绑定用户的层级。 | |
| 325 | + * @param level 下级用户的层级。 | |
| 367 | 326 | * 如果 level 为空,则查询 1+2 两个层级 |
| 368 | - * @return 绑定用户编号列表 | |
| 327 | + * @return 下级用户编号列表 | |
| 369 | 328 | */ |
| 370 | - private List<Long> buildBindUserIdsByLevel(Long bindUserId, Integer level) { | |
| 329 | + private List<Long> getChildUserIdsByLevel(Long bindUserId, Integer level) { | |
| 371 | 330 | if (bindUserId == null) { |
| 372 | 331 | return Collections.emptyList(); |
| 373 | 332 | } |
| 374 | - Assert.isTrue(level == null || level <= 2, "目前只支持 level 小于等于 2"); | |
| 375 | - List<Long> bindUserIds = CollUtil.newArrayList(); | |
| 376 | - if (level == null || level == 1) { | |
| 377 | - bindUserIds.add(bindUserId); | |
| 333 | + | |
| 334 | + // 先查第 1 级 | |
| 335 | + List<Long> bindUserIds = brokerageUserMapper.selectIdListByBindUserIdIn(Collections.singleton(bindUserId)); | |
| 336 | + if (CollUtil.isEmpty(bindUserIds)) { | |
| 337 | + return Collections.emptyList(); | |
| 378 | 338 | } |
| 379 | - if (level == null || level == 2) { | |
| 380 | - bindUserIds.addAll(convertList(brokerageUserMapper.selectListByBindUserId(bindUserId), BrokerageUserDO::getId)); | |
| 339 | + | |
| 340 | + if (level == null) { | |
| 341 | + // level 为空,再查第 2 级,并合并结果 | |
| 342 | + bindUserIds.addAll(brokerageUserMapper.selectIdListByBindUserIdIn(bindUserIds)); | |
| 343 | + } else if (level == 2) { | |
| 344 | + // 只查第 2 级 | |
| 345 | + bindUserIds = brokerageUserMapper.selectIdListByBindUserIdIn(bindUserIds); | |
| 346 | + } else if (level == 1) { | |
| 347 | + // 只查第 1 级 | |
| 348 | + return bindUserIds; | |
| 349 | + } else { | |
| 350 | + throw exception(BROKERAGE_USER_LEVEL_NOT_SUPPORT); | |
| 381 | 351 | } |
| 382 | 352 | return bindUserIds; |
| 383 | 353 | } | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/resources/mapper/brokerage/BrokerageUserMapper.xml
| ... | ... | @@ -2,7 +2,9 @@ |
| 2 | 2 | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| 3 | 3 | <mapper namespace="cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageUserMapper"> |
| 4 | 4 | |
| 5 | - <sql id="selectSummaryListByUserId"> | |
| 5 | + <select id="selectSummaryPageByUserId" | |
| 6 | + resultType="cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO"> | |
| 7 | + | |
| 6 | 8 | SELECT bu.id, bu.bind_user_time AS brokerageTime, |
| 7 | 9 | (SELECT SUM(price) FROM trade_brokerage_record r |
| 8 | 10 | WHERE r.user_id = bu.id AND biz_type = #{bizType} AND r.status = #{status} AND r.deleted = FALSE) AS brokeragePrice, |
| ... | ... | @@ -13,10 +15,10 @@ |
| 13 | 15 | FROM trade_brokerage_user AS bu |
| 14 | 16 | <where> |
| 15 | 17 | bu.deleted = false |
| 16 | - <if test="bindUserIds != null and bindUserIds.size() > 0"> | |
| 17 | - and bu.bind_user_id in | |
| 18 | - <foreach collection="bindUserIds" open="(" item="bindUserId" separator="," close=")"> | |
| 19 | - #{bindUserId} | |
| 18 | + <if test="ids != null and ids.size() > 0"> | |
| 19 | + and bu.id in | |
| 20 | + <foreach collection="ids" open="(" item="id" separator="," close=")"> | |
| 21 | + #{id} | |
| 20 | 22 | </foreach> |
| 21 | 23 | </if> |
| 22 | 24 | </where> |
| ... | ... | @@ -34,15 +36,6 @@ |
| 34 | 36 | ORDER BY bu.bind_user_time DESC |
| 35 | 37 | </otherwise> |
| 36 | 38 | </choose> |
| 37 | - </sql> | |
| 38 | - | |
| 39 | - <select id="selectSummaryPageByUserId" | |
| 40 | - resultType="cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO"> | |
| 41 | - <include refid="selectSummaryListByUserId" /> | |
| 42 | - </select> | |
| 43 | - <select id="selectSummaryListByUserId" | |
| 44 | - resultType="cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO"> | |
| 45 | - <include refid="selectSummaryListByUserId" /> | |
| 46 | 39 | </select> |
| 47 | 40 | |
| 48 | 41 | </mapper> | ... | ... |
yudao-module-member/yudao-module-member-api/pom.xml
| ... | ... | @@ -22,13 +22,6 @@ |
| 22 | 22 | <artifactId>yudao-common</artifactId> |
| 23 | 23 | </dependency> |
| 24 | 24 | |
| 25 | - <!-- TODO @疯狂:biz 引入哈;api 保持低依赖 --> | |
| 26 | - <dependency> | |
| 27 | - <groupId>cn.iocoder.boot</groupId> | |
| 28 | - <artifactId>yudao-spring-boot-starter-mq</artifactId> | |
| 29 | - <scope>compile</scope> | |
| 30 | - </dependency> | |
| 31 | - | |
| 32 | 25 | <!-- 参数校验 --> |
| 33 | 26 | <dependency> |
| 34 | 27 | <groupId>org.springframework.boot</groupId> | ... | ... |
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java
| ... | ... | @@ -38,11 +38,9 @@ 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 注解的方式 | |
| 42 | - ErrorCode SIGN_IN_CONFIG_AWARD_EMPTY = new ErrorCode(1_004_009_002, "签到奖励积分和经验不能同时为空"); | |
| 43 | 41 | |
| 44 | 42 | //========== 签到配置 1-004-010-000 ========== |
| 45 | - ErrorCode SIGN_IN_RECORD_TODAY_EXISTS = new ErrorCode(1_004_010_000,"今日已签到,请勿重复签到"); | |
| 43 | + ErrorCode SIGN_IN_RECORD_TODAY_EXISTS = new ErrorCode(1_004_010_000, "今日已签到,请勿重复签到"); | |
| 46 | 44 | |
| 47 | 45 | //========== 用户等级 1-004-011-000 ========== |
| 48 | 46 | ErrorCode LEVEL_NOT_EXISTS = new ErrorCode(1_004_011_000, "用户等级不存在"); | ... | ... |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/signin/vo/config/MemberSignInConfigBaseVO.java
| 1 | 1 | package cn.iocoder.yudao.module.member.controller.admin.signin.vo.config; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.util.ObjUtil; | |
| 3 | 4 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | 5 | import cn.iocoder.yudao.framework.common.validation.InEnum; |
| 6 | +import com.fasterxml.jackson.annotation.JsonIgnore; | |
| 5 | 7 | import io.swagger.v3.oas.annotations.media.Schema; |
| 6 | 8 | import lombok.Data; |
| 7 | 9 | |
| 10 | +import javax.validation.constraints.AssertTrue; | |
| 8 | 11 | import javax.validation.constraints.NotNull; |
| 9 | 12 | import javax.validation.constraints.PositiveOrZero; |
| 10 | 13 | |
| ... | ... | @@ -34,4 +37,9 @@ public class MemberSignInConfigBaseVO { |
| 34 | 37 | @InEnum(CommonStatusEnum.class) |
| 35 | 38 | private Integer status; |
| 36 | 39 | |
| 40 | + @AssertTrue(message = "签到奖励积分和经验不能同时为空") | |
| 41 | + @JsonIgnore | |
| 42 | + public boolean isConfigAward() { | |
| 43 | + return ObjUtil.notEqual(point, 0) || ObjUtil.notEqual(experience, 0); | |
| 44 | + } | |
| 37 | 45 | } | ... | ... |
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/mq/message/user/RegisterCouponSendMessage.java renamed to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/message/user/UserCreateMessage.java
| ... | ... | @@ -7,13 +7,13 @@ import lombok.EqualsAndHashCode; |
| 7 | 7 | import javax.validation.constraints.NotNull; |
| 8 | 8 | |
| 9 | 9 | /** |
| 10 | - * 新人券发放消息 | |
| 10 | + * 会员用户创建消息 | |
| 11 | 11 | * |
| 12 | 12 | * @author owen |
| 13 | 13 | */ |
| 14 | 14 | @Data |
| 15 | 15 | @EqualsAndHashCode(callSuper = true) |
| 16 | -public class RegisterCouponSendMessage extends AbstractStreamMessage { | |
| 16 | +public class UserCreateMessage extends AbstractStreamMessage { | |
| 17 | 17 | |
| 18 | 18 | /** |
| 19 | 19 | * 用户编号 |
| ... | ... | @@ -23,7 +23,7 @@ public class RegisterCouponSendMessage extends AbstractStreamMessage { |
| 23 | 23 | |
| 24 | 24 | @Override |
| 25 | 25 | public String getStreamKey() { |
| 26 | - return "member.register-coupon.send"; | |
| 26 | + return "member.create.send"; | |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | 29 | } | ... | ... |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/producer/user/RegisterCouponProducer.java renamed to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/mq/producer/user/UserCreateProducer.java
| 1 | 1 | package cn.iocoder.yudao.module.member.mq.producer.user; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; |
| 4 | -import cn.iocoder.yudao.module.member.mq.message.user.RegisterCouponSendMessage; | |
| 4 | +import cn.iocoder.yudao.module.member.mq.message.user.UserCreateMessage; | |
| 5 | 5 | import lombok.extern.slf4j.Slf4j; |
| 6 | 6 | import org.springframework.stereotype.Component; |
| 7 | 7 | |
| 8 | 8 | import javax.annotation.Resource; |
| 9 | 9 | |
| 10 | -// TODO @疯狂:发 UserCreateMessage;解耦,然后优惠劵监听到,去发卷; | |
| 11 | 10 | /** |
| 12 | - * 新人券发放 Producer | |
| 11 | + * 会员用户创建 Producer | |
| 13 | 12 | * |
| 14 | 13 | * @author owen |
| 15 | 14 | */ |
| 16 | 15 | @Slf4j |
| 17 | 16 | @Component |
| 18 | -public class RegisterCouponProducer { | |
| 17 | +public class UserCreateProducer { | |
| 19 | 18 | |
| 20 | 19 | @Resource |
| 21 | 20 | private RedisMQTemplate redisMQTemplate; |
| 22 | 21 | |
| 23 | 22 | /** |
| 24 | - * 发送 {@link RegisterCouponSendMessage} 消息 | |
| 23 | + * 发送 {@link UserCreateMessage} 消息 | |
| 25 | 24 | * |
| 26 | 25 | * @param userId 用户编号 |
| 27 | 26 | */ |
| 28 | - public void sendMailSendMessage(Long userId) { | |
| 29 | - redisMQTemplate.send(new RegisterCouponSendMessage().setUserId(userId)); | |
| 27 | + public void sendUserCreateMessage(Long userId) { | |
| 28 | + redisMQTemplate.send(new UserCreateMessage().setUserId(userId)); | |
| 30 | 29 | } |
| 31 | 30 | |
| 32 | 31 | } | ... | ... |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInConfigServiceImpl.java
| ... | ... | @@ -11,10 +11,10 @@ import org.springframework.validation.annotation.Validated; |
| 11 | 11 | import javax.annotation.Resource; |
| 12 | 12 | import java.util.Comparator; |
| 13 | 13 | import java.util.List; |
| 14 | -import java.util.Objects; | |
| 15 | 14 | |
| 16 | 15 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 17 | -import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*; | |
| 16 | +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.SIGN_IN_CONFIG_EXISTS; | |
| 17 | +import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.SIGN_IN_CONFIG_NOT_EXISTS; | |
| 18 | 18 | |
| 19 | 19 | /** |
| 20 | 20 | * 签到规则 Service 实现类 |
| ... | ... | @@ -30,8 +30,6 @@ public class MemberSignInConfigServiceImpl implements MemberSignInConfigService |
| 30 | 30 | |
| 31 | 31 | @Override |
| 32 | 32 | public Long createSignInConfig(MemberSignInConfigCreateReqVO createReqVO) { |
| 33 | - // 校验奖励积分、奖励经验 | |
| 34 | - validatePointAndExperience(createReqVO.getPoint(), createReqVO.getExperience()); | |
| 35 | 33 | // 判断是否重复插入签到天数 |
| 36 | 34 | validateSignInConfigDayDuplicate(createReqVO.getDay(), null); |
| 37 | 35 | |
| ... | ... | @@ -44,8 +42,6 @@ public class MemberSignInConfigServiceImpl implements MemberSignInConfigService |
| 44 | 42 | |
| 45 | 43 | @Override |
| 46 | 44 | public void updateSignInConfig(MemberSignInConfigUpdateReqVO updateReqVO) { |
| 47 | - // 校验奖励积分、奖励经验 | |
| 48 | - validatePointAndExperience(updateReqVO.getPoint(), updateReqVO.getExperience()); | |
| 49 | 45 | // 校验存在 |
| 50 | 46 | validateSignInConfigExists(updateReqVO.getId()); |
| 51 | 47 | // 判断是否重复插入签到天数 |
| ... | ... | @@ -88,13 +84,6 @@ public class MemberSignInConfigServiceImpl implements MemberSignInConfigService |
| 88 | 84 | } |
| 89 | 85 | } |
| 90 | 86 | |
| 91 | - private void validatePointAndExperience(Integer point, Integer experience) { | |
| 92 | - // 奖励积分、经验 至少要配置一个,否则没有意义 | |
| 93 | - if (Objects.equals(point, 0) && Objects.equals(experience, 0)) { | |
| 94 | - throw exception(SIGN_IN_CONFIG_AWARD_EMPTY); | |
| 95 | - } | |
| 96 | - } | |
| 97 | - | |
| 98 | 87 | @Override |
| 99 | 88 | public MemberSignInConfigDO getSignInConfig(Long id) { |
| 100 | 89 | return memberSignInConfigMapper.selectById(id); | ... | ... |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java
| ... | ... | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.member.service.user; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.collection.ListUtil; |
| 5 | +import cn.hutool.core.util.BooleanUtil; | |
| 5 | 6 | import cn.hutool.core.util.IdUtil; |
| 6 | 7 | import cn.hutool.core.util.ObjectUtil; |
| 7 | 8 | import cn.hutool.core.util.StrUtil; |
| ... | ... | @@ -18,7 +19,7 @@ import cn.iocoder.yudao.module.member.convert.auth.AuthConvert; |
| 18 | 19 | import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert; |
| 19 | 20 | import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; |
| 20 | 21 | import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper; |
| 21 | -import cn.iocoder.yudao.module.member.mq.producer.user.RegisterCouponProducer; | |
| 22 | +import cn.iocoder.yudao.module.member.mq.producer.user.UserCreateProducer; | |
| 22 | 23 | import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; |
| 23 | 24 | import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; |
| 24 | 25 | import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; |
| ... | ... | @@ -27,6 +28,7 @@ import lombok.extern.slf4j.Slf4j; |
| 27 | 28 | import org.springframework.security.crypto.password.PasswordEncoder; |
| 28 | 29 | import org.springframework.stereotype.Service; |
| 29 | 30 | import org.springframework.transaction.annotation.Transactional; |
| 31 | +import org.springframework.transaction.support.TransactionTemplate; | |
| 30 | 32 | |
| 31 | 33 | import javax.annotation.Resource; |
| 32 | 34 | import javax.validation.Valid; |
| ... | ... | @@ -60,7 +62,10 @@ public class MemberUserServiceImpl implements MemberUserService { |
| 60 | 62 | private PasswordEncoder passwordEncoder; |
| 61 | 63 | |
| 62 | 64 | @Resource |
| 63 | - private RegisterCouponProducer registerCouponProducer; | |
| 65 | + private UserCreateProducer registerCouponProducer; | |
| 66 | + | |
| 67 | + @Resource | |
| 68 | + private TransactionTemplate transactionTemplate; | |
| 64 | 69 | |
| 65 | 70 | @Override |
| 66 | 71 | public MemberUserDO getUserByMobile(String mobile) { |
| ... | ... | @@ -92,11 +97,13 @@ public class MemberUserServiceImpl implements MemberUserService { |
| 92 | 97 | user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 |
| 93 | 98 | user.setPassword(encodePassword(password)); // 加密密码 |
| 94 | 99 | user.setRegisterIp(registerIp); |
| 95 | - memberUserMapper.insert(user); | |
| 96 | 100 | |
| 97 | - // 发送 MQ 消息,发放新人券 | |
| 98 | - // TODO @疯狂:事务结束后,在发送 MQ 消息;避免出现消息已经发了,事务没提交,或者回滚了 | |
| 99 | - registerCouponProducer.sendMailSendMessage(user.getId()); | |
| 101 | + Boolean success = transactionTemplate.execute(status -> memberUserMapper.insert(user) > 0); | |
| 102 | + if (BooleanUtil.isTrue(success)) { | |
| 103 | + // 发送 MQ 消息:用户创建 | |
| 104 | + registerCouponProducer.sendUserCreateMessage(user.getId()); | |
| 105 | + } | |
| 106 | + | |
| 100 | 107 | return user; |
| 101 | 108 | } |
| 102 | 109 | ... | ... |