Commit 781ec1028f165ecb791a04742ebd9cf16ae2d38d
Committed by
Gitee
!656 拼团活动:完善 review 提到的问题
Merge pull request !656 from puhui999/feature/mall_product
Showing
30 changed files
with
343 additions
and
212 deletions
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
| @@ -25,15 +25,6 @@ public class CollectionUtils { | @@ -25,15 +25,6 @@ public class CollectionUtils { | ||
| 25 | return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty); | 25 | return Arrays.stream(collections).anyMatch(CollectionUtil::isEmpty); |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | - // TODO @puhui999: list.sort(); 可以替代呀; | ||
| 29 | - public static <T, U extends Comparable<? super U>> List<T> sortedAsc( | ||
| 30 | - Collection<T> from, Function<? super T, ? extends U> keyExtractor) { | ||
| 31 | - // 按照升序排序 | ||
| 32 | - return from.stream() | ||
| 33 | - .sorted(Comparator.comparing(keyExtractor)) | ||
| 34 | - .collect(Collectors.toList()); | ||
| 35 | - } | ||
| 36 | - | ||
| 37 | public static <T> boolean anyMatch(Collection<T> from, Predicate<T> predicate) { | 28 | public static <T> boolean anyMatch(Collection<T> from, Predicate<T> predicate) { |
| 38 | return from.stream().anyMatch(predicate); | 29 | return from.stream().anyMatch(predicate); |
| 39 | } | 30 | } |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java
| @@ -29,8 +29,9 @@ public interface CombinationRecordApi { | @@ -29,8 +29,9 @@ public interface CombinationRecordApi { | ||
| 29 | * 创建开团记录 | 29 | * 创建开团记录 |
| 30 | * | 30 | * |
| 31 | * @param reqDTO 请求 DTO | 31 | * @param reqDTO 请求 DTO |
| 32 | + * @return 开团记录编号 | ||
| 32 | */ | 33 | */ |
| 33 | - void createCombinationRecord(@Valid CombinationRecordCreateReqDTO reqDTO); | 34 | + Long createCombinationRecord(@Valid CombinationRecordCreateReqDTO reqDTO); |
| 34 | 35 | ||
| 35 | /** | 36 | /** |
| 36 | * 查询拼团记录是否成功 | 37 | * 查询拼团记录是否成功 |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java
| @@ -29,8 +29,8 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { | @@ -29,8 +29,8 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { | ||
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | @Override | 31 | @Override |
| 32 | - public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { | ||
| 33 | - recordService.createCombinationRecord(reqDTO); | 32 | + public Long createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { |
| 33 | + return recordService.createCombinationRecord(reqDTO); | ||
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | @Override | 36 | @Override |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationRecordController.java
| 1 | package cn.iocoder.yudao.module.promotion.controller.admin.combination; | 1 | package cn.iocoder.yudao.module.promotion.controller.admin.combination; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.map.MapUtil; | ||
| 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordPageItemRespVO; | ||
| 6 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPageVO; | 6 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPageVO; |
| 7 | -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordRespVO; | 7 | +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordSummaryVO; |
| 8 | import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; | 8 | import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; |
| 9 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; | ||
| 10 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; | ||
| 11 | +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; | ||
| 12 | +import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; | ||
| 9 | import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService; | 13 | import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService; |
| 10 | -import com.google.common.cache.CacheLoader; | ||
| 11 | -import com.google.common.cache.LoadingCache; | ||
| 12 | import io.swagger.v3.oas.annotations.Operation; | 14 | import io.swagger.v3.oas.annotations.Operation; |
| 13 | import io.swagger.v3.oas.annotations.tags.Tag; | 15 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 16 | +import org.springframework.context.annotation.Lazy; | ||
| 14 | import org.springframework.security.access.prepost.PreAuthorize; | 17 | import org.springframework.security.access.prepost.PreAuthorize; |
| 15 | import org.springframework.validation.annotation.Validated; | 18 | import org.springframework.validation.annotation.Validated; |
| 16 | import org.springframework.web.bind.annotation.GetMapping; | 19 | import org.springframework.web.bind.annotation.GetMapping; |
| @@ -19,11 +22,10 @@ import org.springframework.web.bind.annotation.RestController; | @@ -19,11 +22,10 @@ import org.springframework.web.bind.annotation.RestController; | ||
| 19 | 22 | ||
| 20 | import javax.annotation.Resource; | 23 | import javax.annotation.Resource; |
| 21 | import javax.validation.Valid; | 24 | import javax.validation.Valid; |
| 22 | -import java.time.Duration; | ||
| 23 | -import java.util.Map; | 25 | +import java.util.List; |
| 24 | 26 | ||
| 25 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 27 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 26 | -import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache; | 28 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 27 | 29 | ||
| 28 | @Tag(name = "管理后台 - 拼团记录") | 30 | @Tag(name = "管理后台 - 拼团记录") |
| 29 | @RestController | 31 | @RestController |
| @@ -32,44 +34,31 @@ import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsync | @@ -32,44 +34,31 @@ import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsync | ||
| 32 | public class CombinationRecordController { | 34 | public class CombinationRecordController { |
| 33 | 35 | ||
| 34 | @Resource | 36 | @Resource |
| 37 | + private CombinationActivityService combinationActivityService; | ||
| 38 | + @Resource | ||
| 39 | + @Lazy | ||
| 35 | private CombinationRecordService combinationRecordService; | 40 | private CombinationRecordService combinationRecordService; |
| 36 | 41 | ||
| 37 | - // TODO @puhui999:这个缓存不用做哈;主要管理后台,对性能要求不高;不像前段; | ||
| 38 | - /** | ||
| 39 | - * {@link Map} 缓存,通过它异步刷新 {@link #getCombinationRecordSummary0()} 所要的拼团记录统计数据 | ||
| 40 | - */ | ||
| 41 | - private final LoadingCache<String, Map<String, Long>> combinationRecordSummary = buildAsyncReloadingCache(Duration.ofSeconds(60L), | ||
| 42 | - new CacheLoader<String, Map<String, Long>>() { | ||
| 43 | - | ||
| 44 | - @Override | ||
| 45 | - public Map<String, Long> load(String key) { | ||
| 46 | - return getCombinationRecordSummary0(); | ||
| 47 | - } | ||
| 48 | - | ||
| 49 | - }); | ||
| 50 | - | ||
| 51 | @GetMapping("/page") | 42 | @GetMapping("/page") |
| 52 | @Operation(summary = "获得拼团记录分页") | 43 | @Operation(summary = "获得拼团记录分页") |
| 53 | @PreAuthorize("@ss.hasPermission('promotion:combination-record:query')") | 44 | @PreAuthorize("@ss.hasPermission('promotion:combination-record:query')") |
| 54 | - public CommonResult<PageResult<CombinationRecordRespVO>> getBargainRecordPage(@Valid CombinationRecordReqPageVO pageVO) { | ||
| 55 | - return success(CombinationActivityConvert.INSTANCE.convert( | ||
| 56 | - combinationRecordService.getCombinationRecordPage(pageVO))); | 45 | + public CommonResult<PageResult<CombinationRecordPageItemRespVO>> getBargainRecordPage(@Valid CombinationRecordReqPageVO pageVO) { |
| 46 | + PageResult<CombinationRecordDO> recordPage = combinationRecordService.getCombinationRecordPage(pageVO); | ||
| 47 | + List<CombinationActivityDO> activities = combinationActivityService.getCombinationActivityListByIds( | ||
| 48 | + convertSet(recordPage.getList(), CombinationRecordDO::getActivityId)); | ||
| 49 | + return success(CombinationActivityConvert.INSTANCE.convert(recordPage, activities)); | ||
| 57 | } | 50 | } |
| 58 | 51 | ||
| 59 | - // TODO @puhui999:Map 改成对象,尽量避免 Map 返回结果哈;然后 getCombinationRecordCount、getCombinationRecordsSuccessCount、getRecordsVirtualGroupCount 三个方法,可以合并成一个方法哈,返回这个 vo | ||
| 60 | @GetMapping("/get-summary") | 52 | @GetMapping("/get-summary") |
| 61 | @Operation(summary = "获得拼团记录的概要信息", description = "用于拼团记录页面展示") | 53 | @Operation(summary = "获得拼团记录的概要信息", description = "用于拼团记录页面展示") |
| 62 | @PreAuthorize("@ss.hasPermission('promotion:combination-record:query')") | 54 | @PreAuthorize("@ss.hasPermission('promotion:combination-record:query')") |
| 63 | - public CommonResult<Map<String, Long>> getCombinationRecordSummary() { | ||
| 64 | - return success(combinationRecordSummary.getUnchecked("")); // 缓存 | ||
| 65 | - } | ||
| 66 | - | ||
| 67 | - private Map<String, Long> getCombinationRecordSummary0() { | ||
| 68 | - Map<String, Long> hashMap = MapUtil.newHashMap(3); // TODO @puhui999:Maps.newHashMapWithExpectedSize() | ||
| 69 | - hashMap.put("userCount", combinationRecordService.getCombinationRecordCount()); // 获取所有拼团记录 | ||
| 70 | - hashMap.put("successCount", combinationRecordService.getCombinationRecordsSuccessCount()); // 获取成团记录 | ||
| 71 | - hashMap.put("virtualGroupCount", combinationRecordService.getRecordsVirtualGroupCount()); // 获取虚拟成团记录 | ||
| 72 | - return hashMap; | 55 | + public CommonResult<CombinationRecordSummaryVO> getCombinationRecordSummary() { |
| 56 | + CombinationRecordSummaryVO summaryVO = new CombinationRecordSummaryVO(); | ||
| 57 | + summaryVO.setUserCount(combinationRecordService.getCombinationRecordCount(null, null)); // 获取所有拼团记录 | ||
| 58 | + summaryVO.setSuccessCount(combinationRecordService.getCombinationRecordCount( | ||
| 59 | + CombinationRecordStatusEnum.SUCCESS.getStatus(), null));// 获取成团记录 | ||
| 60 | + summaryVO.setVirtualGroupCount(combinationRecordService.getCombinationRecordCount(null, Boolean.TRUE));// 获取虚拟成团记录 | ||
| 61 | + return success(summaryVO); | ||
| 73 | } | 62 | } |
| 74 | 63 | ||
| 75 | } | 64 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/recrod/CombinationRecordRespVO.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/recrod/CombinationRecordBaseVO.java
| @@ -4,14 +4,19 @@ import io.swagger.v3.oas.annotations.media.Schema; | @@ -4,14 +4,19 @@ import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | import lombok.Data; | 4 | import lombok.Data; |
| 5 | import org.springframework.format.annotation.DateTimeFormat; | 5 | import org.springframework.format.annotation.DateTimeFormat; |
| 6 | 6 | ||
| 7 | +import javax.validation.constraints.NotNull; | ||
| 7 | import java.time.LocalDateTime; | 8 | import java.time.LocalDateTime; |
| 8 | 9 | ||
| 9 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | 10 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; |
| 10 | 11 | ||
| 11 | -// TODO @puhui999:可以参考 BargainRecordPageItemRespVO、BargainRecordRespVO 分成两个;一个给记录列表,一个给记录分页 | ||
| 12 | -@Schema(description = "管理后台 - 拼团记录 Response VO") | 12 | +/** |
| 13 | + * 拼团记录 Base VO,提供给添加、修改、详细的子 VO 使用 | ||
| 14 | + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | ||
| 15 | + * | ||
| 16 | + * @author HUIHUI | ||
| 17 | + */ | ||
| 13 | @Data | 18 | @Data |
| 14 | -public class CombinationRecordRespVO { | 19 | +public class CombinationRecordBaseVO { |
| 15 | 20 | ||
| 16 | @Schema(description = "拼团记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | 21 | @Schema(description = "拼团记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 17 | private Long id; | 22 | private Long id; |
| @@ -19,14 +24,36 @@ public class CombinationRecordRespVO { | @@ -19,14 +24,36 @@ public class CombinationRecordRespVO { | ||
| 19 | @Schema(description = "拼团活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | 24 | @Schema(description = "拼团活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 20 | private Long activityId; | 25 | private Long activityId; |
| 21 | 26 | ||
| 22 | - @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "花开富贵") | 27 | + @Schema(description = "团长编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 28 | + private Long headId; | ||
| 29 | + | ||
| 30 | + // ========== 用户相关 ========== | ||
| 31 | + | ||
| 32 | + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "9430") | ||
| 33 | + @NotNull(message = "用户编号不能为空") | ||
| 34 | + private Long userId; | ||
| 35 | + | ||
| 36 | + @Schema(description = "用户昵称", example = "老芋艿") | ||
| 23 | private String nickname; | 37 | private String nickname; |
| 24 | 38 | ||
| 25 | - @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") | 39 | + @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.jpg") |
| 26 | private String avatar; | 40 | private String avatar; |
| 27 | 41 | ||
| 28 | - @Schema(description = "团长编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 29 | - private Long headId; | 42 | + // ========== 商品相关 ========== |
| 43 | + | ||
| 44 | + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23622") | ||
| 45 | + @NotNull(message = "商品 SPU 编号不能为空") | ||
| 46 | + private Long spuId; | ||
| 47 | + | ||
| 48 | + @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29950") | ||
| 49 | + @NotNull(message = "商品 SKU 编号不能为空") | ||
| 50 | + private Long skuId; | ||
| 51 | + | ||
| 52 | + @Schema(description = "商品名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是大黄豆") | ||
| 53 | + private String spuName; | ||
| 54 | + | ||
| 55 | + @Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") | ||
| 56 | + private String picUrl; | ||
| 30 | 57 | ||
| 31 | @Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED) | 58 | @Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 32 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | 59 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| @@ -41,12 +68,6 @@ public class CombinationRecordRespVO { | @@ -41,12 +68,6 @@ public class CombinationRecordRespVO { | ||
| 41 | @Schema(description = "拼团状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 68 | @Schema(description = "拼团状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 42 | private Integer status; | 69 | private Integer status; |
| 43 | 70 | ||
| 44 | - @Schema(description = "商品名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是大黄豆") | ||
| 45 | - private String spuName; | ||
| 46 | - | ||
| 47 | - @Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") | ||
| 48 | - private String picUrl; | ||
| 49 | - | ||
| 50 | @Schema(description = "是否虚拟成团", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") | 71 | @Schema(description = "是否虚拟成团", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") |
| 51 | private Boolean virtualGroup; | 72 | private Boolean virtualGroup; |
| 52 | 73 |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/recrod/CombinationRecordPageItemRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityRespVO; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.EqualsAndHashCode; | ||
| 7 | +import lombok.ToString; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - 拼团记录的分页项 Response VO") | ||
| 10 | +@Data | ||
| 11 | +@EqualsAndHashCode(callSuper = true) | ||
| 12 | +@ToString(callSuper = true) | ||
| 13 | +public class CombinationRecordPageItemRespVO extends CombinationRecordBaseVO { | ||
| 14 | + | ||
| 15 | + // ========== 活动相关 ========== | ||
| 16 | + | ||
| 17 | + private CombinationActivityRespVO activity; | ||
| 18 | + | ||
| 19 | +} |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/recrod/CombinationRecordSummaryVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +@Schema(description = "管理后台 - 拼团记录信息统计 Response VO") | ||
| 7 | +@Data | ||
| 8 | +public class CombinationRecordSummaryVO { | ||
| 9 | + | ||
| 10 | + @Schema(description = "所有拼团记录", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 11 | + private Long userCount; | ||
| 12 | + | ||
| 13 | + @Schema(description = "成团记录", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 14 | + private Long successCount; | ||
| 15 | + | ||
| 16 | + @Schema(description = "虚拟成团记录", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 17 | + private Long virtualGroupCount; | ||
| 18 | + | ||
| 19 | +} |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.controller.app.activity; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.controller.app.activity; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.core.map.MapUtil; | 4 | import cn.hutool.core.map.MapUtil; |
| 5 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 6 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 6 | import cn.iocoder.yudao.module.promotion.controller.app.activity.vo.AppActivityRespVO; | 7 | import cn.iocoder.yudao.module.promotion.controller.app.activity.vo.AppActivityRespVO; |
| 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; |
| @@ -21,12 +22,10 @@ import org.springframework.web.bind.annotation.RequestParam; | @@ -21,12 +22,10 @@ import org.springframework.web.bind.annotation.RequestParam; | ||
| 21 | import org.springframework.web.bind.annotation.RestController; | 22 | import org.springframework.web.bind.annotation.RestController; |
| 22 | 23 | ||
| 23 | import javax.annotation.Resource; | 24 | import javax.annotation.Resource; |
| 24 | -import java.util.ArrayList; | ||
| 25 | -import java.util.HashMap; | ||
| 26 | -import java.util.List; | ||
| 27 | -import java.util.Map; | 25 | +import java.util.*; |
| 28 | 26 | ||
| 29 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 27 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 28 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; | ||
| 30 | 29 | ||
| 31 | @Tag(name = "用户 APP - 营销活动") // 用于提供跨多个活动的 HTTP 接口 | 30 | @Tag(name = "用户 APP - 营销活动") // 用于提供跨多个活动的 HTTP 接口 |
| 32 | @RestController | 31 | @RestController |
| @@ -42,59 +41,72 @@ public class AppActivityController { | @@ -42,59 +41,72 @@ public class AppActivityController { | ||
| 42 | private BargainActivityService bargainActivityService; | 41 | private BargainActivityService bargainActivityService; |
| 43 | 42 | ||
| 44 | @GetMapping("/list-by-spu-id") | 43 | @GetMapping("/list-by-spu-id") |
| 45 | - @Operation(summary = "获得单个商品,近期参与的每个活动") // 每种活动,只返回一个 | 44 | + @Operation(summary = "获得单个商品,近期参与的每个活动") |
| 46 | @Parameter(name = "spuId", description = "商品编号", required = true) | 45 | @Parameter(name = "spuId", description = "商品编号", required = true) |
| 47 | public CommonResult<List<AppActivityRespVO>> getActivityListBySpuId(@RequestParam("spuId") Long spuId) { | 46 | public CommonResult<List<AppActivityRespVO>> getActivityListBySpuId(@RequestParam("spuId") Long spuId) { |
| 48 | - return success(getAppActivityRespVOList(spuId)); | 47 | + // 每种活动,只返回一个 |
| 48 | + return success(getAppActivityRespVOList(Collections.singletonList(spuId))); | ||
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | @GetMapping("/list-by-spu-ids") | 51 | @GetMapping("/list-by-spu-ids") |
| 52 | - @Operation(summary = "获得多个商品,近期参与的每个活动") // 每种活动,只返回一个;key 为 SPU 编号 | 52 | + @Operation(summary = "获得多个商品,近期参与的每个活动") |
| 53 | @Parameter(name = "spuIds", description = "商品编号数组", required = true) | 53 | @Parameter(name = "spuIds", description = "商品编号数组", required = true) |
| 54 | public CommonResult<Map<Long, List<AppActivityRespVO>>> getActivityListBySpuIds(@RequestParam("spuIds") List<Long> spuIds) { | 54 | public CommonResult<Map<Long, List<AppActivityRespVO>>> getActivityListBySpuIds(@RequestParam("spuIds") List<Long> spuIds) { |
| 55 | if (CollUtil.isEmpty(spuIds)) { | 55 | if (CollUtil.isEmpty(spuIds)) { |
| 56 | return success(MapUtil.empty()); | 56 | return success(MapUtil.empty()); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | - // TODO @puhui999:要避免这种 1+n 的查询 | ||
| 60 | - Map<Long, List<AppActivityRespVO>> map = new HashMap<>(spuIds.size()); | ||
| 61 | - spuIds.forEach(spuId -> { | ||
| 62 | - map.put(spuId, getAppActivityRespVOList(spuId)); | ||
| 63 | - }); | ||
| 64 | - return success(map); | 59 | + // 每种活动,只返回一个;key 为 SPU 编号 |
| 60 | + return success(convertMultiMap(getAppActivityRespVOList(spuIds), AppActivityRespVO::getSpuId)); | ||
| 65 | } | 61 | } |
| 66 | 62 | ||
| 67 | - private List<AppActivityRespVO> getAppActivityRespVOList(Long spuId) { | 63 | + private List<AppActivityRespVO> getAppActivityRespVOList(Collection<Long> spuIds) { |
| 64 | + if (CollUtil.isEmpty(spuIds)) { | ||
| 65 | + return new ArrayList<>(); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | List<AppActivityRespVO> activityList = new ArrayList<>(); | 68 | List<AppActivityRespVO> activityList = new ArrayList<>(); |
| 69 | // 拼团活动 | 69 | // 拼团活动 |
| 70 | - CombinationActivityDO combination = combinationActivityService.getCombinationActivityBySpuId(spuId); | ||
| 71 | - if (combination != null) { | ||
| 72 | - activityList.add(new AppActivityRespVO() | ||
| 73 | - .setId(combination.getId()) | ||
| 74 | - .setType(PromotionTypeEnum.COMBINATION_ACTIVITY.getType()) | ||
| 75 | - .setName(combination.getName()) | ||
| 76 | - .setStartTime(combination.getStartTime()) | ||
| 77 | - .setEndTime(combination.getEndTime())); | 70 | + List<CombinationActivityDO> combinationActivities = combinationActivityService.getCombinationActivityBySpuIdsAndStatus( |
| 71 | + spuIds, CommonStatusEnum.ENABLE.getStatus()); | ||
| 72 | + if (CollUtil.isNotEmpty(combinationActivities)) { | ||
| 73 | + combinationActivities.forEach(item -> { | ||
| 74 | + activityList.add(new AppActivityRespVO() | ||
| 75 | + .setId(item.getId()) | ||
| 76 | + .setType(PromotionTypeEnum.COMBINATION_ACTIVITY.getType()) | ||
| 77 | + .setName(item.getName()) | ||
| 78 | + .setSpuId(item.getSpuId()) | ||
| 79 | + .setStartTime(item.getStartTime()) | ||
| 80 | + .setEndTime(item.getEndTime())); | ||
| 81 | + }); | ||
| 78 | } | 82 | } |
| 79 | // 秒杀活动 | 83 | // 秒杀活动 |
| 80 | - SeckillActivityDO seckill = seckillActivityService.getSeckillActivityBySpuId(spuId); | ||
| 81 | - if (seckill != null) { | ||
| 82 | - activityList.add(new AppActivityRespVO() | ||
| 83 | - .setId(seckill.getId()) | ||
| 84 | - .setType(PromotionTypeEnum.SECKILL_ACTIVITY.getType()) | ||
| 85 | - .setName(seckill.getName()) | ||
| 86 | - .setStartTime(seckill.getStartTime()) | ||
| 87 | - .setEndTime(seckill.getEndTime())); | 84 | + List<SeckillActivityDO> seckillActivities = seckillActivityService.getSeckillActivityBySpuIdsAndStatus( |
| 85 | + spuIds, CommonStatusEnum.ENABLE.getStatus()); | ||
| 86 | + if (CollUtil.isNotEmpty(seckillActivities)) { | ||
| 87 | + seckillActivities.forEach(item -> { | ||
| 88 | + activityList.add(new AppActivityRespVO() | ||
| 89 | + .setId(item.getId()) | ||
| 90 | + .setType(PromotionTypeEnum.SECKILL_ACTIVITY.getType()) | ||
| 91 | + .setName(item.getName()) | ||
| 92 | + .setSpuId(item.getSpuId()) | ||
| 93 | + .setStartTime(item.getStartTime()) | ||
| 94 | + .setEndTime(item.getEndTime())); | ||
| 95 | + }); | ||
| 88 | } | 96 | } |
| 89 | - // 秒杀活动 | ||
| 90 | - BargainActivityDO bargain = bargainActivityService.getBargainActivityBySpuId(spuId); | ||
| 91 | - if (bargain != null) { | ||
| 92 | - activityList.add(new AppActivityRespVO() | ||
| 93 | - .setId(bargain.getId()) | ||
| 94 | - .setType(PromotionTypeEnum.BARGAIN_ACTIVITY.getType()) | ||
| 95 | - .setName(bargain.getName()) | ||
| 96 | - .setStartTime(bargain.getStartTime()) | ||
| 97 | - .setEndTime(bargain.getEndTime())); | 97 | + // 砍价活动 |
| 98 | + List<BargainActivityDO> bargainActivities = bargainActivityService.getBargainActivityBySpuIdsAndStatus( | ||
| 99 | + spuIds, CommonStatusEnum.ENABLE.getStatus()); | ||
| 100 | + if (CollUtil.isNotEmpty(bargainActivities)) { | ||
| 101 | + bargainActivities.forEach(item -> { | ||
| 102 | + activityList.add(new AppActivityRespVO() | ||
| 103 | + .setId(item.getId()) | ||
| 104 | + .setType(PromotionTypeEnum.BARGAIN_ACTIVITY.getType()) | ||
| 105 | + .setName(item.getName()) | ||
| 106 | + .setSpuId(item.getSpuId()) | ||
| 107 | + .setStartTime(item.getStartTime()) | ||
| 108 | + .setEndTime(item.getEndTime())); | ||
| 109 | + }); | ||
| 98 | } | 110 | } |
| 99 | return activityList; | 111 | return activityList; |
| 100 | } | 112 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/vo/AppActivityRespVO.java
| @@ -13,12 +13,14 @@ public class AppActivityRespVO { | @@ -13,12 +13,14 @@ public class AppActivityRespVO { | ||
| 13 | private Long id; | 13 | private Long id; |
| 14 | 14 | ||
| 15 | @Schema(description = "活动类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | 15 | @Schema(description = "活动类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 16 | - // 对应 PromotionTypeEnum 枚举 | ||
| 17 | - private Integer type; | 16 | + private Integer type; // 对应 PromotionTypeEnum 枚举 |
| 18 | 17 | ||
| 19 | @Schema(description = "活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618 大促") | 18 | @Schema(description = "活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618 大促") |
| 20 | private String name; | 19 | private String name; |
| 21 | 20 | ||
| 21 | + @Schema(description = "spu 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "618") | ||
| 22 | + private Long spuId; | ||
| 23 | + | ||
| 22 | @Schema(description = "活动开始时间", requiredMode = Schema.RequiredMode.REQUIRED) | 24 | @Schema(description = "活动开始时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 23 | private LocalDateTime startTime; | 25 | private LocalDateTime startTime; |
| 24 | 26 |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationRecordController.java
| @@ -47,7 +47,7 @@ public class AppCombinationRecordController { | @@ -47,7 +47,7 @@ public class AppCombinationRecordController { | ||
| 47 | public CommonResult<AppCombinationRecordSummaryRespVO> getCombinationRecordSummary() { | 47 | public CommonResult<AppCombinationRecordSummaryRespVO> getCombinationRecordSummary() { |
| 48 | AppCombinationRecordSummaryRespVO summary = new AppCombinationRecordSummaryRespVO(); | 48 | AppCombinationRecordSummaryRespVO summary = new AppCombinationRecordSummaryRespVO(); |
| 49 | // 1. 获得拼团记录数量 | 49 | // 1. 获得拼团记录数量 |
| 50 | - Long count = combinationRecordService.getCombinationRecordCount(); | 50 | + Long count = combinationRecordService.getCombinationRecordCount(null, null); |
| 51 | if (count == 0) { | 51 | if (count == 0) { |
| 52 | summary.setAvatars(Collections.emptyList()); | 52 | summary.setAvatars(Collections.emptyList()); |
| 53 | summary.setUserCount(count); | 53 | summary.setUserCount(count); |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java
| @@ -14,7 +14,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activit | @@ -14,7 +14,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activit | ||
| 14 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; | 14 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; |
| 15 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO; | 15 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO; |
| 16 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductRespVO; | 16 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductRespVO; |
| 17 | -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordRespVO; | 17 | +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordPageItemRespVO; |
| 18 | import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityDetailRespVO; | 18 | import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityDetailRespVO; |
| 19 | import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityRespVO; | 19 | import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityRespVO; |
| 20 | import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordDetailRespVO; | 20 | import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordDetailRespVO; |
| @@ -79,6 +79,7 @@ public interface CombinationActivityConvert { | @@ -79,6 +79,7 @@ public interface CombinationActivityConvert { | ||
| 79 | }); | 79 | }); |
| 80 | return pageResult; | 80 | return pageResult; |
| 81 | } | 81 | } |
| 82 | + | ||
| 82 | PageResult<CombinationActivityPageItemRespVO> convertPage(PageResult<CombinationActivityDO> page); | 83 | PageResult<CombinationActivityPageItemRespVO> convertPage(PageResult<CombinationActivityDO> page); |
| 83 | 84 | ||
| 84 | List<CombinationProductRespVO> convertList2(List<CombinationProductDO> productDOs); | 85 | List<CombinationProductRespVO> convertList2(List<CombinationProductDO> productDOs); |
| @@ -113,9 +114,8 @@ public interface CombinationActivityConvert { | @@ -113,9 +114,8 @@ public interface CombinationActivityConvert { | ||
| 113 | CombinationActivityDO activity, MemberUserRespDTO user, | 114 | CombinationActivityDO activity, MemberUserRespDTO user, |
| 114 | ProductSpuRespDTO spu, ProductSkuRespDTO sku) { | 115 | ProductSpuRespDTO spu, ProductSkuRespDTO sku) { |
| 115 | return convert(reqDTO) | 116 | return convert(reqDTO) |
| 116 | - .setHeadId(reqDTO.getHeadId()) // 显示性再设置一下 | ||
| 117 | .setCount(reqDTO.getCount()) | 117 | .setCount(reqDTO.getCount()) |
| 118 | - .setVirtualGroup(false) | 118 | + .setVirtualGroup(false) // 默认 false 拼团过期都还没有成功,则按照 CombinationActivityDO#virtualGroup 来如果为 true 则执行虚拟成团的逻辑 |
| 119 | .setStatus(CombinationRecordStatusEnum.IN_PROGRESS.getStatus()) // 创建后默认状态为进行中 | 119 | .setStatus(CombinationRecordStatusEnum.IN_PROGRESS.getStatus()) // 创建后默认状态为进行中 |
| 120 | .setStartTime(LocalDateTime.now()) | 120 | .setStartTime(LocalDateTime.now()) |
| 121 | .setExpireTime(activity.getStartTime().plusHours(activity.getLimitDuration())) | 121 | .setExpireTime(activity.getStartTime().plusHours(activity.getLimitDuration())) |
| @@ -176,7 +176,20 @@ public interface CombinationActivityConvert { | @@ -176,7 +176,20 @@ public interface CombinationActivityConvert { | ||
| 176 | 176 | ||
| 177 | AppCombinationRecordRespVO convert(CombinationRecordDO record); | 177 | AppCombinationRecordRespVO convert(CombinationRecordDO record); |
| 178 | 178 | ||
| 179 | - PageResult<CombinationRecordRespVO> convert(PageResult<CombinationRecordDO> result); | 179 | + PageResult<CombinationRecordPageItemRespVO> convert(PageResult<CombinationRecordDO> result); |
| 180 | + | ||
| 181 | + default PageResult<CombinationRecordPageItemRespVO> convert(PageResult<CombinationRecordDO> recordPage, List<CombinationActivityDO> activities) { | ||
| 182 | + PageResult<CombinationRecordPageItemRespVO> result = convert(recordPage); | ||
| 183 | + Map<Long, CombinationActivityDO> activityMap = convertMap(activities, CombinationActivityDO::getId); | ||
| 184 | + result.setList(CollectionUtils.convertList(result.getList(), item -> { | ||
| 185 | + findAndThen(activityMap, item.getActivityId(), activity -> { | ||
| 186 | + item.setActivity(convert(activity)); | ||
| 187 | + }); | ||
| 188 | + return item; | ||
| 189 | + })); | ||
| 190 | + return result; | ||
| 191 | + } | ||
| 192 | + | ||
| 180 | 193 | ||
| 181 | default AppCombinationRecordDetailRespVO convert(Long userId, CombinationRecordDO headRecord, List<CombinationRecordDO> memberRecords) { | 194 | default AppCombinationRecordDetailRespVO convert(Long userId, CombinationRecordDO headRecord, List<CombinationRecordDO> memberRecords) { |
| 182 | AppCombinationRecordDetailRespVO respVO = new AppCombinationRecordDetailRespVO() | 195 | AppCombinationRecordDetailRespVO respVO = new AppCombinationRecordDetailRespVO() |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java
| @@ -77,7 +77,6 @@ public class CombinationRecordDO extends BaseDO { | @@ -77,7 +77,6 @@ public class CombinationRecordDO extends BaseDO { | ||
| 77 | */ | 77 | */ |
| 78 | private Long userId; | 78 | private Long userId; |
| 79 | 79 | ||
| 80 | - // TODO @puhui999:要不去掉这 2 个字段,通过读取解决?如果去掉,相关接口都要处理下哈; | ||
| 81 | /** | 80 | /** |
| 82 | * 用户昵称 | 81 | * 用户昵称 |
| 83 | */ | 82 | */ |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java
| @@ -8,8 +8,10 @@ import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.activity.Ba | @@ -8,8 +8,10 @@ import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.activity.Ba | ||
| 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; |
| 9 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | 9 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| 10 | import org.apache.ibatis.annotations.Mapper; | 10 | import org.apache.ibatis.annotations.Mapper; |
| 11 | +import org.apache.ibatis.annotations.Select; | ||
| 11 | 12 | ||
| 12 | import java.time.LocalDateTime; | 13 | import java.time.LocalDateTime; |
| 14 | +import java.util.Collection; | ||
| 13 | import java.util.List; | 15 | import java.util.List; |
| 14 | 16 | ||
| 15 | /** | 17 | /** |
| @@ -83,12 +85,23 @@ public interface BargainActivityMapper extends BaseMapperX<BargainActivityDO> { | @@ -83,12 +85,23 @@ public interface BargainActivityMapper extends BaseMapperX<BargainActivityDO> { | ||
| 83 | .last("LIMIT " + count)); | 85 | .last("LIMIT " + count)); |
| 84 | } | 86 | } |
| 85 | 87 | ||
| 86 | - // TODO @puhui999:需要开启状态;另外,是不是可以 limit1,不用 throwEx = false 处理呀?另外,时间要满足噢 | ||
| 87 | - default BargainActivityDO selectOne(Long spuId) { | ||
| 88 | - return selectOne(new LambdaQueryWrapperX<BargainActivityDO>() | ||
| 89 | - .eq(BargainActivityDO::getSpuId, spuId) | ||
| 90 | - .orderByDesc(BargainActivityDO::getCreateTime) | ||
| 91 | - , false); | ||
| 92 | - } | 88 | + /** |
| 89 | + * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 | ||
| 90 | + * | ||
| 91 | + * @param spuIds spu 编号 | ||
| 92 | + * @param status 状态 | ||
| 93 | + * @return 砍价活动列表 | ||
| 94 | + */ | ||
| 95 | + @Select("SELECT p1.* " + | ||
| 96 | + "FROM promotion_bargain_activity p1 " + | ||
| 97 | + "INNER JOIN ( " + | ||
| 98 | + " SELECT spu_id, MAX(DISTINCT(create_time)) AS max_create_time " + | ||
| 99 | + " FROM promotion_bargain_activity " + | ||
| 100 | + " WHERE spu_id IN #{spuIds} " + | ||
| 101 | + " GROUP BY spu_id " + | ||
| 102 | + ") p2 " + | ||
| 103 | + "ON p1.spu_id = p2.spu_id AND p1.create_time = p2.max_create_time AND p1.status = #{status} " + | ||
| 104 | + "ORDER BY p1.create_time DESC;") | ||
| 105 | + List<BargainActivityDO> selectListBySpuIds(Collection<Long> spuIds, Integer status); | ||
| 93 | 106 | ||
| 94 | } | 107 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationActivityMapper.java
| @@ -7,7 +7,10 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | @@ -7,7 +7,10 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 7 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; | 7 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; |
| 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; |
| 9 | import org.apache.ibatis.annotations.Mapper; | 9 | import org.apache.ibatis.annotations.Mapper; |
| 10 | +import org.apache.ibatis.annotations.Param; | ||
| 11 | +import org.apache.ibatis.annotations.Select; | ||
| 10 | 12 | ||
| 13 | +import java.util.Collection; | ||
| 11 | import java.util.List; | 14 | import java.util.List; |
| 12 | 15 | ||
| 13 | /** | 16 | /** |
| @@ -40,12 +43,23 @@ public interface CombinationActivityMapper extends BaseMapperX<CombinationActivi | @@ -40,12 +43,23 @@ public interface CombinationActivityMapper extends BaseMapperX<CombinationActivi | ||
| 40 | .last("LIMIT " + count)); | 43 | .last("LIMIT " + count)); |
| 41 | } | 44 | } |
| 42 | 45 | ||
| 43 | - // TODO @puhui999:需要开启状态;另外,是不是可以 limit1,不用 throwEx = false 处理呀?另外,时间要满足噢 | ||
| 44 | - default CombinationActivityDO selectOne(Long spuId) { | ||
| 45 | - return selectOne(new LambdaQueryWrapperX<CombinationActivityDO>() | ||
| 46 | - .eq(CombinationActivityDO::getSpuId, spuId) | ||
| 47 | - .orderByDesc(CombinationActivityDO::getCreateTime) | ||
| 48 | - , false); | ||
| 49 | - } | 46 | + /** |
| 47 | + * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 | ||
| 48 | + * | ||
| 49 | + * @param spuIds spu 编号 | ||
| 50 | + * @param status 状态 | ||
| 51 | + * @return 拼团活动列表 | ||
| 52 | + */ | ||
| 53 | + @Select("SELECT p1.* " + | ||
| 54 | + "FROM promotion_combination_activity p1 " + | ||
| 55 | + "INNER JOIN ( " + | ||
| 56 | + " SELECT spu_id, MAX(DISTINCT(create_time)) AS max_create_time " + | ||
| 57 | + " FROM promotion_combination_activity " + | ||
| 58 | + " WHERE spu_id IN #{spuIds} " + | ||
| 59 | + " GROUP BY spu_id " + | ||
| 60 | + ") p2 " + | ||
| 61 | + "ON p1.spu_id = p2.spu_id AND p1.create_time = p2.max_create_time AND p1.status = #{status} " + | ||
| 62 | + "ORDER BY p1.create_time DESC;") | ||
| 63 | + List<CombinationActivityDO> selectListBySpuIds(@Param("spuIds") Collection<Long> spuIds, @Param("status") Integer status); | ||
| 50 | 64 | ||
| 51 | } | 65 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java
| @@ -100,4 +100,12 @@ public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO | @@ -100,4 +100,12 @@ public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO | ||
| 100 | .betweenIfPresent(CombinationRecordDO::getCreateTime, pageVO.getCreateTime())); | 100 | .betweenIfPresent(CombinationRecordDO::getCreateTime, pageVO.getCreateTime())); |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | + default Long selectRecordCount(Integer status, Boolean virtualGroup) { | ||
| 104 | + return selectCount(new LambdaQueryWrapperX<CombinationRecordDO>() | ||
| 105 | + .eq(status != null || virtualGroup != null, | ||
| 106 | + CombinationRecordDO::getHeadId, CombinationRecordDO.HEAD_ID_GROUP) // 统计团信息则指定团长 | ||
| 107 | + .eqIfPresent(CombinationRecordDO::getStatus, status) | ||
| 108 | + .eqIfPresent(CombinationRecordDO::getVirtualGroup, virtualGroup)); | ||
| 109 | + } | ||
| 110 | + | ||
| 103 | } | 111 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java
| @@ -9,7 +9,9 @@ import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppS | @@ -9,7 +9,9 @@ import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppS | ||
| 9 | import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO; | 9 | import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO; |
| 10 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | 10 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| 11 | import org.apache.ibatis.annotations.Mapper; | 11 | import org.apache.ibatis.annotations.Mapper; |
| 12 | +import org.apache.ibatis.annotations.Select; | ||
| 12 | 13 | ||
| 14 | +import java.util.Collection; | ||
| 13 | import java.util.List; | 15 | import java.util.List; |
| 14 | 16 | ||
| 15 | /** | 17 | /** |
| @@ -56,12 +58,23 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> { | @@ -56,12 +58,23 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> { | ||
| 56 | .apply(ObjectUtil.isNotNull(pageReqVO.getConfigId()), "FIND_IN_SET(" + pageReqVO.getConfigId() + ",config_ids) > 0")); | 58 | .apply(ObjectUtil.isNotNull(pageReqVO.getConfigId()), "FIND_IN_SET(" + pageReqVO.getConfigId() + ",config_ids) > 0")); |
| 57 | } | 59 | } |
| 58 | 60 | ||
| 59 | - // TODO @puhui999:需要开启状态;另外,是不是可以 limit1,不用 throwEx = false 处理呀?另外,时间要满足噢; | ||
| 60 | - default SeckillActivityDO selectOne(Long spuId) { | ||
| 61 | - return selectOne(new LambdaQueryWrapperX<SeckillActivityDO>() | ||
| 62 | - .eq(SeckillActivityDO::getSpuId, spuId) | ||
| 63 | - .orderByDesc(SeckillActivityDO::getCreateTime) | ||
| 64 | - , false); | ||
| 65 | - } | 61 | + /** |
| 62 | + * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 | ||
| 63 | + * | ||
| 64 | + * @param spuIds spu 编号 | ||
| 65 | + * @param status 状态 | ||
| 66 | + * @return 秒杀活动列表 | ||
| 67 | + */ | ||
| 68 | + @Select("SELECT p1.* " + | ||
| 69 | + "FROM promotion_seckill_activity p1 " + | ||
| 70 | + "INNER JOIN ( " + | ||
| 71 | + " SELECT spu_id, MAX(DISTINCT(create_time)) AS max_create_time " + | ||
| 72 | + " FROM promotion_seckill_activity " + | ||
| 73 | + " WHERE spu_id IN #{spuIds} " + | ||
| 74 | + " GROUP BY spu_id " + | ||
| 75 | + ") p2 " + | ||
| 76 | + "ON p1.spu_id = p2.spu_id AND p1.create_time = p2.max_create_time AND p1.status = #{status} " + | ||
| 77 | + "ORDER BY p1.create_time DESC;") | ||
| 78 | + List<SeckillActivityDO> selectListBySpuIds(Collection<Long> spuIds, Integer status); | ||
| 66 | 79 | ||
| 67 | } | 80 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityService.java
| @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.activity.Ba | @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.activity.Ba | ||
| 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; |
| 9 | 9 | ||
| 10 | import javax.validation.Valid; | 10 | import javax.validation.Valid; |
| 11 | +import java.util.Collection; | ||
| 11 | import java.util.List; | 12 | import java.util.List; |
| 12 | import java.util.Set; | 13 | import java.util.Set; |
| 13 | 14 | ||
| @@ -99,11 +100,12 @@ public interface BargainActivityService { | @@ -99,11 +100,12 @@ public interface BargainActivityService { | ||
| 99 | List<BargainActivityDO> getBargainActivityListByCount(Integer count); | 100 | List<BargainActivityDO> getBargainActivityListByCount(Integer count); |
| 100 | 101 | ||
| 101 | /** | 102 | /** |
| 102 | - * 获取指定 spu 编号的活动 | 103 | + * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 |
| 103 | * | 104 | * |
| 104 | - * @param spuId spu 编号 | ||
| 105 | - * @return 砍价活动 | 105 | + * @param spuIds spu 编号 |
| 106 | + * @param status 状态 | ||
| 107 | + * @return 砍价活动列表 | ||
| 106 | */ | 108 | */ |
| 107 | - BargainActivityDO getBargainActivityBySpuId(Long spuId); | 109 | + List<BargainActivityDO> getBargainActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status); |
| 108 | 110 | ||
| 109 | } | 111 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java
| @@ -20,6 +20,7 @@ import org.springframework.validation.annotation.Validated; | @@ -20,6 +20,7 @@ import org.springframework.validation.annotation.Validated; | ||
| 20 | 20 | ||
| 21 | import javax.annotation.Resource; | 21 | import javax.annotation.Resource; |
| 22 | import java.time.LocalDateTime; | 22 | import java.time.LocalDateTime; |
| 23 | +import java.util.Collection; | ||
| 23 | import java.util.List; | 24 | import java.util.List; |
| 24 | import java.util.Set; | 25 | import java.util.Set; |
| 25 | 26 | ||
| @@ -176,8 +177,8 @@ public class BargainActivityServiceImpl implements BargainActivityService { | @@ -176,8 +177,8 @@ public class BargainActivityServiceImpl implements BargainActivityService { | ||
| 176 | } | 177 | } |
| 177 | 178 | ||
| 178 | @Override | 179 | @Override |
| 179 | - public BargainActivityDO getBargainActivityBySpuId(Long spuId) { | ||
| 180 | - return bargainActivityMapper.selectOne(spuId); | 180 | + public List<BargainActivityDO> getBargainActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { |
| 181 | + return bargainActivityMapper.selectListBySpuIds(spuIds, status); | ||
| 181 | } | 182 | } |
| 182 | 183 | ||
| 183 | } | 184 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
| @@ -85,6 +85,14 @@ public interface CombinationActivityService { | @@ -85,6 +85,14 @@ public interface CombinationActivityService { | ||
| 85 | List<CombinationProductDO> getCombinationProductListByActivityIds(Collection<Long> activityIds); | 85 | List<CombinationProductDO> getCombinationProductListByActivityIds(Collection<Long> activityIds); |
| 86 | 86 | ||
| 87 | /** | 87 | /** |
| 88 | + * 获得拼团活动列表 | ||
| 89 | + * | ||
| 90 | + * @param ids 拼团活动 ids | ||
| 91 | + * @return 拼团活动的列表 | ||
| 92 | + */ | ||
| 93 | + List<CombinationActivityDO> getCombinationActivityListByIds(Collection<Long> ids); | ||
| 94 | + | ||
| 95 | + /** | ||
| 88 | * 获取正在进行的活动分页数据 | 96 | * 获取正在进行的活动分页数据 |
| 89 | * | 97 | * |
| 90 | * @param count 需要的数量 | 98 | * @param count 需要的数量 |
| @@ -110,11 +118,12 @@ public interface CombinationActivityService { | @@ -110,11 +118,12 @@ public interface CombinationActivityService { | ||
| 110 | CombinationProductDO selectByActivityIdAndSkuId(Long activityId, Long skuId); | 118 | CombinationProductDO selectByActivityIdAndSkuId(Long activityId, Long skuId); |
| 111 | 119 | ||
| 112 | /** | 120 | /** |
| 113 | - * 获取指定 spu 编号的活动 | 121 | + * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 |
| 114 | * | 122 | * |
| 115 | - * @param spuId spu 编号 | ||
| 116 | - * @return 拼团活动 | 123 | + * @param spuIds spu 编号 |
| 124 | + * @param status 状态 | ||
| 125 | + * @return 拼团活动列表 | ||
| 117 | */ | 126 | */ |
| 118 | - CombinationActivityDO getCombinationActivityBySpuId(Long spuId); | 127 | + List<CombinationActivityDO> getCombinationActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status); |
| 119 | 128 | ||
| 120 | } | 129 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
| @@ -205,6 +205,11 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic | @@ -205,6 +205,11 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic | ||
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | @Override | 207 | @Override |
| 208 | + public List<CombinationActivityDO> getCombinationActivityListByIds(Collection<Long> ids) { | ||
| 209 | + return combinationActivityMapper.selectList(CombinationActivityDO::getId, ids); | ||
| 210 | + } | ||
| 211 | + | ||
| 212 | + @Override | ||
| 208 | public List<CombinationActivityDO> getCombinationActivityListByCount(Integer count) { | 213 | public List<CombinationActivityDO> getCombinationActivityListByCount(Integer count) { |
| 209 | return combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus(), count); | 214 | return combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus(), count); |
| 210 | } | 215 | } |
| @@ -222,8 +227,8 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic | @@ -222,8 +227,8 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic | ||
| 222 | } | 227 | } |
| 223 | 228 | ||
| 224 | @Override | 229 | @Override |
| 225 | - public CombinationActivityDO getCombinationActivityBySpuId(Long spuId) { | ||
| 226 | - return combinationActivityMapper.selectOne(spuId); | 230 | + public List<CombinationActivityDO> getCombinationActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { |
| 231 | + return combinationActivityMapper.selectListBySpuIds(spuIds, status); | ||
| 227 | } | 232 | } |
| 228 | 233 | ||
| 229 | } | 234 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java
| @@ -49,8 +49,9 @@ public interface CombinationRecordService { | @@ -49,8 +49,9 @@ public interface CombinationRecordService { | ||
| 49 | * 创建拼团记录 | 49 | * 创建拼团记录 |
| 50 | * | 50 | * |
| 51 | * @param reqDTO 创建信息 | 51 | * @param reqDTO 创建信息 |
| 52 | + * @return 开团记录编号 | ||
| 52 | */ | 53 | */ |
| 53 | - void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO); | 54 | + Long createCombinationRecord(CombinationRecordCreateReqDTO reqDTO); |
| 54 | 55 | ||
| 55 | /** | 56 | /** |
| 56 | * 获得拼团记录 | 57 | * 获得拼团记录 |
| @@ -85,25 +86,13 @@ public interface CombinationRecordService { | @@ -85,25 +86,13 @@ public interface CombinationRecordService { | ||
| 85 | CombinationValidateJoinRespDTO validateJoinCombination(Long userId, Long activityId, Long headId, Long skuId, Integer count); | 86 | CombinationValidateJoinRespDTO validateJoinCombination(Long userId, Long activityId, Long headId, Long skuId, Integer count); |
| 86 | 87 | ||
| 87 | /** | 88 | /** |
| 88 | - * 获取所有拼团记录数 | 89 | + * 获取拼团记录数 |
| 89 | * | 90 | * |
| 91 | + * @param status 状态-允许为空 | ||
| 92 | + * @param virtualGroup 是否虚拟成团-允许为空 | ||
| 90 | * @return 记录数 | 93 | * @return 记录数 |
| 91 | */ | 94 | */ |
| 92 | - Long getCombinationRecordCount(); | ||
| 93 | - | ||
| 94 | - /** | ||
| 95 | - * 获取成功记录数 | ||
| 96 | - * | ||
| 97 | - * @return 记录数 | ||
| 98 | - */ | ||
| 99 | - Long getCombinationRecordsSuccessCount(); | ||
| 100 | - | ||
| 101 | - /** | ||
| 102 | - * 获取虚拟成团记录数 | ||
| 103 | - * | ||
| 104 | - * @return 记录数 | ||
| 105 | - */ | ||
| 106 | - Long getRecordsVirtualGroupCount(); | 95 | + Long getCombinationRecordCount(@Nullable Integer status, @Nullable Boolean virtualGroup); |
| 107 | 96 | ||
| 108 | /** | 97 | /** |
| 109 | * 获取最近的 count 条拼团记录 | 98 | * 获取最近的 count 条拼团记录 |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
| @@ -31,7 +31,8 @@ import javax.annotation.Resource; | @@ -31,7 +31,8 @@ import javax.annotation.Resource; | ||
| 31 | import java.util.*; | 31 | import java.util.*; |
| 32 | 32 | ||
| 33 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 33 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 34 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | 34 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.findFirst; |
| 35 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; | ||
| 35 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.afterNow; | 36 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.afterNow; |
| 36 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.beforeNow; | 37 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.beforeNow; |
| 37 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; | 38 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; |
| @@ -95,7 +96,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -95,7 +96,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 95 | if (ObjUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { | 96 | if (ObjUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { |
| 96 | throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); | 97 | throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); |
| 97 | } | 98 | } |
| 98 | - // 1.2 校验活动开始时间 | 99 | + // 1.2. 校验活动开始时间 |
| 99 | if (afterNow(activity.getStartTime())) { | 100 | if (afterNow(activity.getStartTime())) { |
| 100 | throw exception(COMBINATION_RECORD_FAILED_TIME_NOT_START); | 101 | throw exception(COMBINATION_RECORD_FAILED_TIME_NOT_START); |
| 101 | } | 102 | } |
| @@ -163,7 +164,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -163,7 +164,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 163 | 164 | ||
| 164 | @Override | 165 | @Override |
| 165 | @Transactional(rollbackFor = Exception.class) | 166 | @Transactional(rollbackFor = Exception.class) |
| 166 | - public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { | 167 | + public Long createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { |
| 167 | // 1. 校验拼团活动 | 168 | // 1. 校验拼团活动 |
| 168 | KeyValue<CombinationActivityDO, CombinationProductDO> keyValue = validateCombinationRecord(reqDTO.getUserId(), | 169 | KeyValue<CombinationActivityDO, CombinationProductDO> keyValue = validateCombinationRecord(reqDTO.getUserId(), |
| 169 | reqDTO.getActivityId(), reqDTO.getHeadId(), reqDTO.getSkuId(), reqDTO.getCount()); | 170 | reqDTO.getActivityId(), reqDTO.getHeadId(), reqDTO.getSkuId(), reqDTO.getCount()); |
| @@ -173,34 +174,19 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -173,34 +174,19 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 173 | ProductSpuRespDTO spu = productSpuApi.getSpu(reqDTO.getSpuId()); | 174 | ProductSpuRespDTO spu = productSpuApi.getSpu(reqDTO.getSpuId()); |
| 174 | ProductSkuRespDTO sku = productSkuApi.getSku(reqDTO.getSkuId()); | 175 | ProductSkuRespDTO sku = productSkuApi.getSku(reqDTO.getSkuId()); |
| 175 | CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO, keyValue.getKey(), user, spu, sku); | 176 | CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO, keyValue.getKey(), user, spu, sku); |
| 176 | - // TODO @puhui:有 head 的情况下,以 head 结束为准 | 177 | + // 3. 如果是团长需要设置 headId 为 CombinationRecordDO#HEAD_ID_GROUP |
| 178 | + record.setHeadId(record.getHeadId() == null ? CombinationRecordDO.HEAD_ID_GROUP : record.getHeadId()); | ||
| 177 | recordMapper.insert(record); | 179 | recordMapper.insert(record); |
| 178 | 180 | ||
| 179 | - // 3. 如果是团长需要设置 headId 为 CombinationRecordDO#HEAD_ID_GROUP | ||
| 180 | - // TODO @puhui999:是不是只要是团长,record 设置了就好啦,不用 update。。。。 | ||
| 181 | - if (ObjUtil.equal(CombinationRecordDO.HEAD_ID_GROUP, reqDTO.getHeadId())) { | ||
| 182 | - recordMapper.updateById(new CombinationRecordDO().setId(record.getId()).setHeadId(CombinationRecordDO.HEAD_ID_GROUP)); | ||
| 183 | - return; | 181 | + if (ObjUtil.equal(CombinationRecordDO.HEAD_ID_GROUP, record.getHeadId())) { |
| 182 | + return record.getId(); | ||
| 184 | } | 183 | } |
| 185 | 184 | ||
| 186 | - // TODO 这里要不要弄成异步的;不用异步哈,就是事务好了; | ||
| 187 | // 4、更新拼团相关信息到订单 | 185 | // 4、更新拼团相关信息到订单 |
| 188 | - updateOrderCombinationInfo(record.getOrderId(), record.getActivityId(), record.getId(), record.getHeadId()); | 186 | + tradeOrderApi.updateOrderCombinationInfo(record.getOrderId(), record.getActivityId(), record.getId(), record.getHeadId()); |
| 189 | // 4、更新拼团记录 | 187 | // 4、更新拼团记录 |
| 190 | updateCombinationRecordWhenCreate(reqDTO.getHeadId(), keyValue.getKey()); | 188 | updateCombinationRecordWhenCreate(reqDTO.getHeadId(), keyValue.getKey()); |
| 191 | - } | ||
| 192 | - | ||
| 193 | - // TODO @puhui999:这个更新,放到 trade 那就好了;createCombinationRecord 返回一个 recordId; | ||
| 194 | - /** | ||
| 195 | - * 更新拼团相关信息到订单 | ||
| 196 | - * | ||
| 197 | - * @param orderId 订单编号 | ||
| 198 | - * @param activityId 拼团活动编号 | ||
| 199 | - * @param combinationRecordId 拼团记录编号 | ||
| 200 | - * @param headId 团长编号 | ||
| 201 | - */ | ||
| 202 | - private void updateOrderCombinationInfo(Long orderId, Long activityId, Long combinationRecordId, Long headId) { | ||
| 203 | - tradeOrderApi.updateOrderCombinationInfo(orderId, activityId, combinationRecordId, headId); | 189 | + return record.getId(); |
| 204 | } | 190 | } |
| 205 | 191 | ||
| 206 | /** | 192 | /** |
| @@ -252,20 +238,8 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -252,20 +238,8 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 252 | } | 238 | } |
| 253 | 239 | ||
| 254 | @Override | 240 | @Override |
| 255 | - public Long getCombinationRecordCount() { | ||
| 256 | - return recordMapper.selectCount(); | ||
| 257 | - } | ||
| 258 | - | ||
| 259 | - @Override | ||
| 260 | - public Long getCombinationRecordsSuccessCount() { | ||
| 261 | - // TODO @puhui999:这个应该要多查询 headId | ||
| 262 | - return recordMapper.selectCount(CombinationRecordDO::getStatus, CombinationRecordStatusEnum.SUCCESS.getStatus()); | ||
| 263 | - } | ||
| 264 | - | ||
| 265 | - @Override | ||
| 266 | - public Long getRecordsVirtualGroupCount() { | ||
| 267 | - // TODO @puhui999:这个应该要多查询 headId;然后,recordMapper 要明确的查询哈,不要直接使用 mapper 来拼接查询条件 | ||
| 268 | - return recordMapper.selectCount(CombinationRecordDO::getVirtualGroup, true); | 241 | + public Long getCombinationRecordCount(@Nullable Integer status, @Nullable Boolean virtualGroup) { |
| 242 | + return recordMapper.selectRecordCount(status, virtualGroup); | ||
| 269 | } | 243 | } |
| 270 | 244 | ||
| 271 | @Override | 245 | @Override |
| @@ -321,9 +295,9 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -321,9 +295,9 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 321 | return; | 295 | return; |
| 322 | } | 296 | } |
| 323 | // 按照创建时间升序排序 | 297 | // 按照创建时间升序排序 |
| 324 | - List<CombinationRecordDO> recordsSort = sortedAsc(list, CombinationRecordDO::getCreateTime); | ||
| 325 | - CombinationRecordDO newHead = recordsSort.get(0); // 新团长继位 | ||
| 326 | - recordsSort.forEach(item -> { | 298 | + list.sort(Comparator.comparing(CombinationRecordDO::getCreateTime)); // 影响原 list |
| 299 | + CombinationRecordDO newHead = list.get(0); // 新团长继位 | ||
| 300 | + list.forEach(item -> { | ||
| 327 | CombinationRecordDO recordDO = new CombinationRecordDO(); | 301 | CombinationRecordDO recordDO = new CombinationRecordDO(); |
| 328 | recordDO.setId(item.getId()); | 302 | recordDO.setId(item.getId()); |
| 329 | if (ObjUtil.equal(item.getId(), newHead.getId())) { // 新团长 | 303 | if (ObjUtil.equal(item.getId(), newHead.getId())) { // 新团长 |
| @@ -331,7 +305,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -331,7 +305,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 331 | } else { | 305 | } else { |
| 332 | recordDO.setHeadId(newHead.getId()); | 306 | recordDO.setHeadId(newHead.getId()); |
| 333 | } | 307 | } |
| 334 | - recordDO.setUserCount(recordsSort.size()); | 308 | + recordDO.setUserCount(list.size()); |
| 335 | updateRecords.add(recordDO); | 309 | updateRecords.add(recordDO); |
| 336 | }); | 310 | }); |
| 337 | } else { // 情况二:团员 | 311 | } else { // 情况二:团员 |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java
| @@ -120,11 +120,12 @@ public interface SeckillActivityService { | @@ -120,11 +120,12 @@ public interface SeckillActivityService { | ||
| 120 | SeckillValidateJoinRespDTO validateJoinSeckill(Long activityId, Long skuId, Integer count); | 120 | SeckillValidateJoinRespDTO validateJoinSeckill(Long activityId, Long skuId, Integer count); |
| 121 | 121 | ||
| 122 | /** | 122 | /** |
| 123 | - * 获取指定 spu 编号的活动 | 123 | + * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 |
| 124 | * | 124 | * |
| 125 | - * @param spuId spu 编号 | ||
| 126 | - * @return 秒杀活动 | 125 | + * @param spuIds spu 编号 |
| 126 | + * @param status 状态 | ||
| 127 | + * @return 秒杀活动列表 | ||
| 127 | */ | 128 | */ |
| 128 | - SeckillActivityDO getSeckillActivityBySpuId(Long spuId); | 129 | + List<SeckillActivityDO> getSeckillActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status); |
| 129 | 130 | ||
| 130 | } | 131 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java
| @@ -311,8 +311,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | @@ -311,8 +311,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | ||
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | @Override | 313 | @Override |
| 314 | - public SeckillActivityDO getSeckillActivityBySpuId(Long spuId) { | ||
| 315 | - return seckillActivityMapper.selectOne(spuId); | 314 | + public List<SeckillActivityDO> getSeckillActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { |
| 315 | + return seckillActivityMapper.selectListBySpuIds(spuIds, status); | ||
| 316 | } | 316 | } |
| 317 | 317 | ||
| 318 | } | 318 | } |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
| @@ -33,6 +33,7 @@ public interface ErrorCodeConstants { | @@ -33,6 +33,7 @@ public interface ErrorCodeConstants { | ||
| 33 | ErrorCode ORDER_UPDATE_PRICE_FAIL_PRICE_ERROR = new ErrorCode(1_011_000_028, "支付订单调价失败,原因:调整后支付价格不能小于 0.01 元"); | 33 | ErrorCode ORDER_UPDATE_PRICE_FAIL_PRICE_ERROR = new ErrorCode(1_011_000_028, "支付订单调价失败,原因:调整后支付价格不能小于 0.01 元"); |
| 34 | ErrorCode ORDER_DELETE_FAIL_STATUS_NOT_CANCEL = new ErrorCode(1_011_000_029, "交易订单删除失败,订单不是【已取消】状态"); | 34 | ErrorCode ORDER_DELETE_FAIL_STATUS_NOT_CANCEL = new ErrorCode(1_011_000_029, "交易订单删除失败,订单不是【已取消】状态"); |
| 35 | ErrorCode ORDER_RECEIVE_FAIL_DELIVERY_TYPE_NOT_PICK_UP = new ErrorCode(1_011_000_030, "交易订单自提失败,收货方式不是【用户自提】"); | 35 | ErrorCode ORDER_RECEIVE_FAIL_DELIVERY_TYPE_NOT_PICK_UP = new ErrorCode(1_011_000_030, "交易订单自提失败,收货方式不是【用户自提】"); |
| 36 | + ErrorCode ORDER_UPDATE_ADDRESS_FAIL_STATUS_NOT_DELIVERED = new ErrorCode(1_011_000_031, "交易订单修改收货地址失败,原因:订单已发货"); | ||
| 36 | 37 | ||
| 37 | // ========== After Sale 模块 1-011-000-100 ========== | 38 | // ========== After Sale 模块 1-011-000-100 ========== |
| 38 | ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在"); | 39 | ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在"); |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/redis/RedisKeyConstants.java
| @@ -15,4 +15,12 @@ public interface RedisKeyConstants { | @@ -15,4 +15,12 @@ public interface RedisKeyConstants { | ||
| 15 | */ | 15 | */ |
| 16 | String TRADE_NO = "trade_no:"; | 16 | String TRADE_NO = "trade_no:"; |
| 17 | 17 | ||
| 18 | + /** | ||
| 19 | + * 交易序号的缓存 | ||
| 20 | + * | ||
| 21 | + * KEY 格式:express_track:{code-logisticsNo-receiverMobile} | ||
| 22 | + * VALUE 数据格式 String, 物流信息集合 | ||
| 23 | + */ | ||
| 24 | + String EXPRESS_TRACK = "express_track"; | ||
| 25 | + | ||
| 18 | } | 26 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java
| @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.service.order; | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.service.order; | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.core.util.ObjectUtil; | 4 | import cn.hutool.core.util.ObjectUtil; |
| 5 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 6 | +import cn.hutool.extra.spring.SpringUtil; | ||
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | import cn.iocoder.yudao.module.member.api.user.MemberUserApi; | 8 | import cn.iocoder.yudao.module.member.api.user.MemberUserApi; |
| 8 | import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; | 9 | import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; |
| @@ -14,11 +15,13 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | @@ -14,11 +15,13 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | ||
| 14 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | 15 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; |
| 15 | import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; | 16 | import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; |
| 16 | import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; | 17 | import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; |
| 18 | +import cn.iocoder.yudao.module.trade.dal.redis.RedisKeyConstants; | ||
| 17 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; | 19 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; |
| 18 | import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClientFactory; | 20 | import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClientFactory; |
| 19 | import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO; | 21 | import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO; |
| 20 | import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO; | 22 | import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO; |
| 21 | import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; | 23 | import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; |
| 24 | +import org.springframework.cache.annotation.Cacheable; | ||
| 22 | import org.springframework.stereotype.Service; | 25 | import org.springframework.stereotype.Service; |
| 23 | 26 | ||
| 24 | import javax.annotation.Resource; | 27 | import javax.annotation.Resource; |
| @@ -143,7 +146,6 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { | @@ -143,7 +146,6 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { | ||
| 143 | return tradeOrderItemMapper.selectProductSumByOrderId(convertSet(orders, TradeOrderDO::getId)); | 146 | return tradeOrderItemMapper.selectProductSumByOrderId(convertSet(orders, TradeOrderDO::getId)); |
| 144 | } | 147 | } |
| 145 | 148 | ||
| 146 | - // TODO @puhui999:可以加个 spring 缓存,30 分钟;主要考虑及时性要求不高,但是每次调用需要钱; | ||
| 147 | /** | 149 | /** |
| 148 | * 获得订单的物流轨迹 | 150 | * 获得订单的物流轨迹 |
| 149 | * | 151 | * |
| @@ -160,10 +162,25 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { | @@ -160,10 +162,25 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { | ||
| 160 | throw exception(EXPRESS_NOT_EXISTS); | 162 | throw exception(EXPRESS_NOT_EXISTS); |
| 161 | } | 163 | } |
| 162 | 164 | ||
| 165 | + return getSelf().getExpressTrackList(express.getCode(), order.getLogisticsNo(), order.getReceiverMobile()); | ||
| 166 | + } | ||
| 167 | + | ||
| 168 | + /** | ||
| 169 | + * 查询物流轨迹 | ||
| 170 | + * 加个 spring 缓存,30 分钟;主要考虑及时性要求不高,但是每次调用需要钱;TODO @艿艿:这个时间不会搞了。。。交给你了哈哈哈 | ||
| 171 | + * | ||
| 172 | + * @param code 快递公司编码 | ||
| 173 | + * @param logisticsNo 发货快递单号 | ||
| 174 | + * @param receiverMobile 收、寄件人的电话号码 | ||
| 175 | + * @return 物流轨迹 | ||
| 176 | + */ | ||
| 177 | + @Cacheable(cacheNames = RedisKeyConstants.EXPRESS_TRACK, key = "#code + '-' + #logisticsNo + '-' + #receiverMobile", | ||
| 178 | + condition = "#result != null") | ||
| 179 | + public List<ExpressTrackRespDTO> getExpressTrackList(String code, String logisticsNo, String receiverMobile) { | ||
| 163 | // 查询物流轨迹 | 180 | // 查询物流轨迹 |
| 164 | return expressClientFactory.getDefaultExpressClient().getExpressTrackList( | 181 | return expressClientFactory.getDefaultExpressClient().getExpressTrackList( |
| 165 | - new ExpressTrackQueryReqDTO().setExpressCode(express.getCode()).setLogisticsNo(order.getLogisticsNo()) | ||
| 166 | - .setPhone(order.getReceiverMobile())); | 182 | + new ExpressTrackQueryReqDTO().setExpressCode(code).setLogisticsNo(logisticsNo) |
| 183 | + .setPhone(receiverMobile)); | ||
| 167 | } | 184 | } |
| 168 | 185 | ||
| 169 | @Override | 186 | @Override |
| @@ -199,4 +216,13 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { | @@ -199,4 +216,13 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { | ||
| 199 | return tradeOrderItemMapper.selectListByOrderId(orderIds); | 216 | return tradeOrderItemMapper.selectListByOrderId(orderIds); |
| 200 | } | 217 | } |
| 201 | 218 | ||
| 219 | + /** | ||
| 220 | + * 获得自身的代理对象,解决 AOP 生效问题 | ||
| 221 | + * | ||
| 222 | + * @return 自己 | ||
| 223 | + */ | ||
| 224 | + private TradeOrderQueryServiceImpl getSelf() { | ||
| 225 | + return SpringUtil.getBean(getClass()); | ||
| 226 | + } | ||
| 227 | + | ||
| 202 | } | 228 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
| @@ -742,8 +742,10 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -742,8 +742,10 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 742 | public void updateOrderAddress(TradeOrderUpdateAddressReqVO reqVO) { | 742 | public void updateOrderAddress(TradeOrderUpdateAddressReqVO reqVO) { |
| 743 | // 校验交易订单 | 743 | // 校验交易订单 |
| 744 | TradeOrderDO order = validateOrderExists(reqVO.getId()); | 744 | TradeOrderDO order = validateOrderExists(reqVO.getId()); |
| 745 | - // TODO @puhui999:是否需要校验订单是否发货 | ||
| 746 | - // TODO 发货后是否支持修改收货地址;回答:发货后,不允许修改; | 745 | + // 发货后,不允许修改; |
| 746 | + if (TradeOrderStatusEnum.isDelivered(order.getStatus())) { | ||
| 747 | + throw exception(ORDER_UPDATE_ADDRESS_FAIL_STATUS_NOT_DELIVERED); | ||
| 748 | + } | ||
| 747 | 749 | ||
| 748 | // 更新 | 750 | // 更新 |
| 749 | tradeOrderMapper.updateById(TradeOrderConvert.INSTANCE.convert(reqVO)); | 751 | tradeOrderMapper.updateById(TradeOrderConvert.INSTANCE.convert(reqVO)); |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java
| @@ -176,7 +176,7 @@ public class DeptServiceImpl implements DeptService { | @@ -176,7 +176,7 @@ public class DeptServiceImpl implements DeptService { | ||
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | @Override | 178 | @Override |
| 179 | - @DataPermission(enable = false) // 禁用数据权限,避免简历不正确的缓存 | 179 | + @DataPermission(enable = false) // 禁用数据权限,避免建立不正确的缓存 |
| 180 | @Cacheable(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST, key = "#id") | 180 | @Cacheable(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST, key = "#id") |
| 181 | public Set<Long> getChildDeptIdListFromCache(Long id) { | 181 | public Set<Long> getChildDeptIdListFromCache(Long id) { |
| 182 | List<DeptDO> children = getChildDeptList(id); | 182 | List<DeptDO> children = getChildDeptList(id); |