Commit 2e207019b3582e13d56e4c1aa2a169a97f471a18
Merge remote-tracking branch 'origin/feature/mall_product' into feature/mall_product
Showing
102 changed files
with
2146 additions
and
770 deletions
Too many changes.
To preserve performance only 100 of 102 files are displayed.
sql/mysql/statistics.sql
| @@ -28,16 +28,22 @@ CREATE INDEX trade_statistics_time_index | @@ -28,16 +28,22 @@ CREATE INDEX trade_statistics_time_index | ||
| 28 | ON trade_statistics (time); | 28 | ON trade_statistics (time); |
| 29 | 29 | ||
| 30 | -- 菜单 | 30 | -- 菜单 |
| 31 | -INSERT INTO `ruoyi-vue-pro`.system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name) | 31 | +INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name) |
| 32 | VALUES ('统计管理', '', 1, 4, 0, '/statistics', 'ep:data-line', '', ''); | 32 | VALUES ('统计管理', '', 1, 4, 0, '/statistics', 'ep:data-line', '', ''); |
| 33 | SELECT @parentId := LAST_INSERT_ID(); | 33 | SELECT @parentId := LAST_INSERT_ID(); |
| 34 | -INSERT INTO `ruoyi-vue-pro`.system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name) | ||
| 35 | -VALUES ('交易统计', '', 2, 4, @parentId, 'trade', 'fa-solid:credit-card', 'statistics/trade/index', 'TradeStatistics'); | 34 | +-- 交易统计 |
| 35 | +INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name) | ||
| 36 | +VALUES ('交易统计', '', 2, 1, @parentId, 'trade', 'fa-solid:credit-card', 'statistics/trade/index', 'TradeStatistics'); | ||
| 36 | SELECT @parentId := LAST_INSERT_ID(); | 37 | SELECT @parentId := LAST_INSERT_ID(); |
| 37 | --- 按钮 | ||
| 38 | INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | 38 | INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) |
| 39 | VALUES ('交易统计查询', 'statistics:trade:query', 3, 1, @parentId, '', '', '', 0); | 39 | VALUES ('交易统计查询', 'statistics:trade:query', 3, 1, @parentId, '', '', '', 0); |
| 40 | INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | 40 | INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) |
| 41 | VALUES ('交易统计导出', 'statistics:trade:export', 3, 2, @parentId, '', '', '', 0); | 41 | VALUES ('交易统计导出', 'statistics:trade:export', 3, 2, @parentId, '', '', '', 0); |
| 42 | +-- 会员统计 | ||
| 43 | +INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name) | ||
| 44 | +VALUES ('会员统计', '', 2, 2, @parentId, 'member', 'ep:avatar', 'statistics/member/index', 'MemberStatistics'); | ||
| 45 | +SELECT @parentId := LAST_INSERT_ID(); | ||
| 46 | +INSERT INTO system_menu(name, permission, type, sort, parent_id, path, icon, component, status) | ||
| 47 | +VALUES ('会员统计查询', 'statistics:member:query', 3, 1, @parentId, '', '', '', 0); | ||
| 42 | 48 | ||
| 43 | 49 |
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.common.util.collection; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.common.util.collection; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.core.collection.CollectionUtil; | 4 | import cn.hutool.core.collection.CollectionUtil; |
| 5 | +import cn.hutool.core.util.ArrayUtil; | ||
| 5 | import com.google.common.collect.ImmutableMap; | 6 | import com.google.common.collect.ImmutableMap; |
| 6 | 7 | ||
| 7 | import java.util.*; | 8 | import java.util.*; |
| @@ -50,6 +51,13 @@ public class CollectionUtils { | @@ -50,6 +51,13 @@ public class CollectionUtils { | ||
| 50 | return new ArrayList<>(convertMap(from, keyMapper, Function.identity(), cover).values()); | 51 | return new ArrayList<>(convertMap(from, keyMapper, Function.identity(), cover).values()); |
| 51 | } | 52 | } |
| 52 | 53 | ||
| 54 | + public static <T, U> List<U> convertList(T[] from, Function<T, U> func) { | ||
| 55 | + if (ArrayUtil.isEmpty(from)) { | ||
| 56 | + return new ArrayList<>(); | ||
| 57 | + } | ||
| 58 | + return convertList(Arrays.asList(from), func); | ||
| 59 | + } | ||
| 60 | + | ||
| 53 | public static <T, U> List<U> convertList(Collection<T> from, Function<T, U> func) { | 61 | public static <T, U> List<U> convertList(Collection<T> from, Function<T, U> func) { |
| 54 | if (CollUtil.isEmpty(from)) { | 62 | if (CollUtil.isEmpty(from)) { |
| 55 | return new ArrayList<>(); | 63 | return new ArrayList<>(); |
| @@ -64,6 +72,13 @@ public class CollectionUtils { | @@ -64,6 +72,13 @@ public class CollectionUtils { | ||
| 64 | return from.stream().filter(filter).map(func).filter(Objects::nonNull).collect(Collectors.toList()); | 72 | return from.stream().filter(filter).map(func).filter(Objects::nonNull).collect(Collectors.toList()); |
| 65 | } | 73 | } |
| 66 | 74 | ||
| 75 | + public static <K, V> List<V> mergeValuesFromMap(Map<K, List<V>> map) { | ||
| 76 | + return map.values() | ||
| 77 | + .stream() | ||
| 78 | + .flatMap(List::stream) | ||
| 79 | + .collect(Collectors.toList()); | ||
| 80 | + } | ||
| 81 | + | ||
| 67 | public static <T, U> Set<U> convertSet(Collection<T> from, Function<T, U> func) { | 82 | public static <T, U> Set<U> convertSet(Collection<T> from, Function<T, U> func) { |
| 68 | if (CollUtil.isEmpty(from)) { | 83 | if (CollUtil.isEmpty(from)) { |
| 69 | return new HashSet<>(); | 84 | return new HashSet<>(); |
| @@ -162,8 +177,8 @@ public class CollectionUtils { | @@ -162,8 +177,8 @@ public class CollectionUtils { | ||
| 162 | /** | 177 | /** |
| 163 | * 对比老、新两个列表,找出新增、修改、删除的数据 | 178 | * 对比老、新两个列表,找出新增、修改、删除的数据 |
| 164 | * | 179 | * |
| 165 | - * @param oldList 老列表 | ||
| 166 | - * @param newList 新列表 | 180 | + * @param oldList 老列表 |
| 181 | + * @param newList 新列表 | ||
| 167 | * @param sameFunc 对比函数,返回 true 表示相同,返回 false 表示不同 | 182 | * @param sameFunc 对比函数,返回 true 表示相同,返回 false 表示不同 |
| 168 | * 注意,same 是通过每个元素的“标识”,判断它们是不是同一个数据 | 183 | * 注意,same 是通过每个元素的“标识”,判断它们是不是同一个数据 |
| 169 | * @return [新增列表、修改列表、删除列表] | 184 | * @return [新增列表、修改列表、删除列表] |
yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtils.java
| @@ -7,12 +7,16 @@ import cn.hutool.core.text.csv.CsvUtil; | @@ -7,12 +7,16 @@ import cn.hutool.core.text.csv.CsvUtil; | ||
| 7 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | 7 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; |
| 8 | import cn.iocoder.yudao.framework.ip.core.Area; | 8 | import cn.iocoder.yudao.framework.ip.core.Area; |
| 9 | import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; | 9 | import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; |
| 10 | +import lombok.NonNull; | ||
| 10 | import lombok.extern.slf4j.Slf4j; | 11 | import lombok.extern.slf4j.Slf4j; |
| 11 | 12 | ||
| 12 | import java.util.ArrayList; | 13 | import java.util.ArrayList; |
| 13 | import java.util.HashMap; | 14 | import java.util.HashMap; |
| 14 | import java.util.List; | 15 | import java.util.List; |
| 15 | import java.util.Map; | 16 | import java.util.Map; |
| 17 | +import java.util.function.Function; | ||
| 18 | + | ||
| 19 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 16 | 20 | ||
| 17 | /** | 21 | /** |
| 18 | * 区域工具类 | 22 | * 区域工具类 |
| @@ -108,7 +112,7 @@ public class AreaUtils { | @@ -108,7 +112,7 @@ public class AreaUtils { | ||
| 108 | // “递归”父节点 | 112 | // “递归”父节点 |
| 109 | area = area.getParent(); | 113 | area = area.getParent(); |
| 110 | if (area == null | 114 | if (area == null |
| 111 | - || ObjectUtils.equalsAny(area.getId(), Area.ID_GLOBAL, Area.ID_CHINA)) { // 跳过父节点为中国的情况 | 115 | + || ObjectUtils.equalsAny(area.getId(), Area.ID_GLOBAL, Area.ID_CHINA)) { // 跳过父节点为中国的情况 |
| 112 | break; | 116 | break; |
| 113 | } | 117 | } |
| 114 | sb.insert(0, separator); | 118 | sb.insert(0, separator); |
| @@ -116,4 +120,37 @@ public class AreaUtils { | @@ -116,4 +120,37 @@ public class AreaUtils { | ||
| 116 | return sb.toString(); | 120 | return sb.toString(); |
| 117 | } | 121 | } |
| 118 | 122 | ||
| 123 | + /** | ||
| 124 | + * 获取指定类型的区域列表 | ||
| 125 | + * | ||
| 126 | + * @param type 区域类型 | ||
| 127 | + * @param func 转换函数 | ||
| 128 | + * @param <T> 结果类型 | ||
| 129 | + * @return 区域列表 | ||
| 130 | + */ | ||
| 131 | + public static <T> List<T> getByType(AreaTypeEnum type, Function<Area, T> func) { | ||
| 132 | + return convertList(areas.values(), func, area -> type.getType().equals(area.getType())); | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + // TODO @疯狂:注释写下; | ||
| 136 | + public static Integer getParentIdByType(Integer id, @NonNull AreaTypeEnum type) { | ||
| 137 | + // TODO @疯狂:这种不要用 while true;因为万一脏数据,可能会死循环;可以转换成 for (int i = 0; i < Byte.MAX; i++) 一般是优先层级; | ||
| 138 | + do { | ||
| 139 | + Area area = AreaUtils.getArea(id); | ||
| 140 | + if (area == null) { | ||
| 141 | + return null; | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | + if (type.getType().equals(area.getType())) { | ||
| 145 | + return area.getId(); | ||
| 146 | + } | ||
| 147 | + | ||
| 148 | + if (area.getParent() == null || area.getParent().getId() == null) { | ||
| 149 | + return null; | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + id = area.getParent().getId(); | ||
| 153 | + } while (true); | ||
| 154 | + } | ||
| 155 | + | ||
| 119 | } | 156 | } |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java
| 1 | package cn.iocoder.yudao.module.promotion.api.combination; | 1 | package cn.iocoder.yudao.module.promotion.api.combination; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.core.KeyValue; | ||
| 3 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; | 4 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; |
| 4 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO; | 5 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO; |
| 5 | 6 | ||
| 6 | import javax.validation.Valid; | 7 | import javax.validation.Valid; |
| 7 | 8 | ||
| 8 | -// TODO @芋艿:后面也再撸撸这几个接口 | ||
| 9 | - | ||
| 10 | /** | 9 | /** |
| 11 | * 拼团记录 API 接口 | 10 | * 拼团记录 API 接口 |
| 12 | * | 11 | * |
| @@ -29,9 +28,9 @@ public interface CombinationRecordApi { | @@ -29,9 +28,9 @@ public interface CombinationRecordApi { | ||
| 29 | * 创建开团记录 | 28 | * 创建开团记录 |
| 30 | * | 29 | * |
| 31 | * @param reqDTO 请求 DTO | 30 | * @param reqDTO 请求 DTO |
| 32 | - * @return 开团记录编号 | 31 | + * @return key 开团记录编号、value 团长编号 |
| 33 | */ | 32 | */ |
| 34 | - Long createCombinationRecord(@Valid CombinationRecordCreateReqDTO reqDTO); | 33 | + KeyValue<Long, Long> createCombinationRecord(@Valid CombinationRecordCreateReqDTO reqDTO); |
| 35 | 34 | ||
| 36 | /** | 35 | /** |
| 37 | * 查询拼团记录是否成功 | 36 | * 查询拼团记录是否成功 |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java
| @@ -10,13 +10,22 @@ import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillValidateJoinResp | @@ -10,13 +10,22 @@ import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillValidateJoinResp | ||
| 10 | public interface SeckillActivityApi { | 10 | public interface SeckillActivityApi { |
| 11 | 11 | ||
| 12 | /** | 12 | /** |
| 13 | - * 更新秒杀库存 | 13 | + * 更新秒杀库存(减少) |
| 14 | * | 14 | * |
| 15 | - * @param id 活动编号 | ||
| 16 | - * @param skuId sku 编号 | ||
| 17 | - * @param count 数量 | 15 | + * @param id 活动编号 |
| 16 | + * @param skuId sku 编号 | ||
| 17 | + * @param count 数量(正数) | ||
| 18 | + */ | ||
| 19 | + void updateSeckillStockDecr(Long id, Long skuId, Integer count); | ||
| 20 | + | ||
| 21 | + /** | ||
| 22 | + * 更新秒杀库存(增加) | ||
| 23 | + * | ||
| 24 | + * @param id 活动编号 | ||
| 25 | + * @param skuId sku 编号 | ||
| 26 | + * @param count 数量(正数) | ||
| 18 | */ | 27 | */ |
| 19 | - void updateSeckillStock(Long id, Long skuId, Integer count); | 28 | + void updateSeckillStockIncr(Long id, Long skuId, Integer count); |
| 20 | 29 | ||
| 21 | /** | 30 | /** |
| 22 | * 【下单前】校验是否参与秒杀活动 | 31 | * 【下单前】校验是否参与秒杀活动 |
| @@ -24,8 +33,8 @@ public interface SeckillActivityApi { | @@ -24,8 +33,8 @@ public interface SeckillActivityApi { | ||
| 24 | * 如果校验失败,则抛出业务异常 | 33 | * 如果校验失败,则抛出业务异常 |
| 25 | * | 34 | * |
| 26 | * @param activityId 活动编号 | 35 | * @param activityId 活动编号 |
| 27 | - * @param skuId SKU 编号 | ||
| 28 | - * @param count 数量 | 36 | + * @param skuId SKU 编号 |
| 37 | + * @param count 数量 | ||
| 29 | * @return 秒杀信息 | 38 | * @return 秒杀信息 |
| 30 | */ | 39 | */ |
| 31 | SeckillValidateJoinRespDTO validateJoinSeckill(Long activityId, Long skuId, Integer count); | 40 | SeckillValidateJoinRespDTO validateJoinSeckill(Long activityId, Long skuId, Integer count); |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java
| 1 | package cn.iocoder.yudao.module.promotion.api.combination; | 1 | package cn.iocoder.yudao.module.promotion.api.combination; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.core.KeyValue; | ||
| 3 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; | 4 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; |
| 4 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO; | 5 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO; |
| 5 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; | 6 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; |
| @@ -28,8 +29,9 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { | @@ -28,8 +29,9 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { | ||
| 28 | recordService.validateCombinationRecord(userId, activityId, headId, skuId, count); | 29 | recordService.validateCombinationRecord(userId, activityId, headId, skuId, count); |
| 29 | } | 30 | } |
| 30 | 31 | ||
| 32 | + // TODO @puhui999:搞个创建的 RespDTO 哈; | ||
| 31 | @Override | 33 | @Override |
| 32 | - public Long createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { | 34 | + public KeyValue<Long, Long> createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { |
| 33 | return recordService.createCombinationRecord(reqDTO); | 35 | return recordService.createCombinationRecord(reqDTO); |
| 34 | } | 36 | } |
| 35 | 37 |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java
| @@ -18,8 +18,13 @@ public class SeckillActivityApiImpl implements SeckillActivityApi { | @@ -18,8 +18,13 @@ public class SeckillActivityApiImpl implements SeckillActivityApi { | ||
| 18 | private SeckillActivityService activityService; | 18 | private SeckillActivityService activityService; |
| 19 | 19 | ||
| 20 | @Override | 20 | @Override |
| 21 | - public void updateSeckillStock(Long id, Long skuId, Integer count) { | ||
| 22 | - activityService.updateSeckillStock(id, skuId, count); | 21 | + public void updateSeckillStockDecr(Long id, Long skuId, Integer count) { |
| 22 | + activityService.updateSeckillStockDecr(id, skuId, count); | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + @Override | ||
| 26 | + public void updateSeckillStockIncr(Long id, Long skuId, Integer count) { | ||
| 27 | + activityService.updateSeckillStockIncr(id, skuId, count); | ||
| 23 | } | 28 | } |
| 24 | 29 | ||
| 25 | @Override | 30 | @Override |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationRecordController.java
| @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.controller.admin.combination; | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.controller.admin.combination; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | 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; | 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.CombinationRecordReqPage2VO; | ||
| 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.CombinationRecordReqPageVO; |
| 7 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordSummaryVO; | 8 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordSummaryVO; |
| 8 | import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; | 9 | import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; |
| @@ -39,6 +40,9 @@ public class CombinationRecordController { | @@ -39,6 +40,9 @@ public class CombinationRecordController { | ||
| 39 | @Lazy | 40 | @Lazy |
| 40 | private CombinationRecordService combinationRecordService; | 41 | private CombinationRecordService combinationRecordService; |
| 41 | 42 | ||
| 43 | + // TODO @puhui999:getBargainRecordPage 和 getBargainRecordPage 是不是可以合并;然后 CombinationRecordReqPageVO 加一个 headId; | ||
| 44 | + // 然后如果 headId 非空,并且第一页,单独多查询一条 head ;放到第 0 个位置;相当于说,第一页特殊一点; | ||
| 45 | + | ||
| 42 | @GetMapping("/page") | 46 | @GetMapping("/page") |
| 43 | @Operation(summary = "获得拼团记录分页") | 47 | @Operation(summary = "获得拼团记录分页") |
| 44 | @PreAuthorize("@ss.hasPermission('promotion:combination-record:query')") | 48 | @PreAuthorize("@ss.hasPermission('promotion:combination-record:query')") |
| @@ -46,6 +50,18 @@ public class CombinationRecordController { | @@ -46,6 +50,18 @@ public class CombinationRecordController { | ||
| 46 | PageResult<CombinationRecordDO> recordPage = combinationRecordService.getCombinationRecordPage(pageVO); | 50 | PageResult<CombinationRecordDO> recordPage = combinationRecordService.getCombinationRecordPage(pageVO); |
| 47 | List<CombinationActivityDO> activities = combinationActivityService.getCombinationActivityListByIds( | 51 | List<CombinationActivityDO> activities = combinationActivityService.getCombinationActivityListByIds( |
| 48 | convertSet(recordPage.getList(), CombinationRecordDO::getActivityId)); | 52 | convertSet(recordPage.getList(), CombinationRecordDO::getActivityId)); |
| 53 | + // TODO @puhui999:商品没读取 | ||
| 54 | + return success(CombinationActivityConvert.INSTANCE.convert(recordPage, activities)); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + @GetMapping("/page-by-headId") | ||
| 58 | + @Operation(summary = "获得拼团记录分页") | ||
| 59 | + @PreAuthorize("@ss.hasPermission('promotion:combination-record:query')") | ||
| 60 | + public CommonResult<PageResult<CombinationRecordPageItemRespVO>> getBargainRecordPage(@Valid CombinationRecordReqPage2VO pageVO) { | ||
| 61 | + // 包含团长和团员的分页记录 | ||
| 62 | + PageResult<CombinationRecordDO> recordPage = combinationRecordService.getCombinationRecordPage2(pageVO); | ||
| 63 | + List<CombinationActivityDO> activities = combinationActivityService.getCombinationActivityListByIds( | ||
| 64 | + convertSet(recordPage.getList(), CombinationRecordDO::getActivityId)); | ||
| 49 | return success(CombinationActivityConvert.INSTANCE.convert(recordPage, activities)); | 65 | return success(CombinationActivityConvert.INSTANCE.convert(recordPage, activities)); |
| 50 | } | 66 | } |
| 51 | 67 | ||
| @@ -54,10 +70,11 @@ public class CombinationRecordController { | @@ -54,10 +70,11 @@ public class CombinationRecordController { | ||
| 54 | @PreAuthorize("@ss.hasPermission('promotion:combination-record:query')") | 70 | @PreAuthorize("@ss.hasPermission('promotion:combination-record:query')") |
| 55 | public CommonResult<CombinationRecordSummaryVO> getCombinationRecordSummary() { | 71 | public CommonResult<CombinationRecordSummaryVO> getCombinationRecordSummary() { |
| 56 | CombinationRecordSummaryVO summaryVO = new CombinationRecordSummaryVO(); | 72 | CombinationRecordSummaryVO summaryVO = new CombinationRecordSummaryVO(); |
| 57 | - summaryVO.setUserCount(combinationRecordService.getCombinationRecordCount(null, null)); // 获取所有拼团记录 | 73 | + summaryVO.setUserCount(combinationRecordService.getCombinationRecordCount(null, null, null)); // 获取拼团用户参与数量 |
| 58 | summaryVO.setSuccessCount(combinationRecordService.getCombinationRecordCount( // 获取成团记录 | 74 | summaryVO.setSuccessCount(combinationRecordService.getCombinationRecordCount( // 获取成团记录 |
| 59 | - CombinationRecordStatusEnum.SUCCESS.getStatus(), null)); | ||
| 60 | - summaryVO.setVirtualGroupCount(combinationRecordService.getCombinationRecordCount(null, Boolean.TRUE));// 获取虚拟成团记录 | 75 | + CombinationRecordStatusEnum.SUCCESS.getStatus(), null, CombinationRecordDO.HEAD_ID_GROUP)); |
| 76 | + summaryVO.setVirtualGroupCount(combinationRecordService.getCombinationRecordCount(// 获取虚拟成团记录 | ||
| 77 | + null, Boolean.TRUE, CombinationRecordDO.HEAD_ID_GROUP)); | ||
| 61 | return success(summaryVO); | 78 | return success(summaryVO); |
| 62 | } | 79 | } |
| 63 | 80 |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/recrod/CombinationRecordReqPage2VO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.EqualsAndHashCode; | ||
| 7 | +import lombok.ToString; | ||
| 8 | + | ||
| 9 | +import javax.validation.constraints.NotNull; | ||
| 10 | + | ||
| 11 | +@Schema(description = "管理后台 - 拼团记录分页 Request VO") | ||
| 12 | +@Data | ||
| 13 | +@EqualsAndHashCode(callSuper = true) | ||
| 14 | +@ToString(callSuper = true) | ||
| 15 | +public class CombinationRecordReqPage2VO extends PageParam { | ||
| 16 | + | ||
| 17 | + @Schema(description = "团长编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 18 | + @NotNull(message = "团长编号不能为空") | ||
| 19 | + private Long headId; | ||
| 20 | + | ||
| 21 | +} |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.http
0 → 100644
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/AppBargainRecordController.java
| @@ -46,18 +46,18 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti | @@ -46,18 +46,18 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti | ||
| 46 | public class AppBargainRecordController { | 46 | public class AppBargainRecordController { |
| 47 | 47 | ||
| 48 | @Resource | 48 | @Resource |
| 49 | + private BargainHelpService bargainHelpService; | ||
| 50 | + @Resource | ||
| 49 | private BargainRecordService bargainRecordService; | 51 | private BargainRecordService bargainRecordService; |
| 50 | @Resource | 52 | @Resource |
| 51 | private BargainActivityService bargainActivityService; | 53 | private BargainActivityService bargainActivityService; |
| 52 | - @Resource | ||
| 53 | - private BargainHelpService bargainHelpService; | ||
| 54 | 54 | ||
| 55 | @Resource | 55 | @Resource |
| 56 | + private TradeOrderApi tradeOrderApi; | ||
| 57 | + @Resource | ||
| 56 | private MemberUserApi memberUserApi; | 58 | private MemberUserApi memberUserApi; |
| 57 | @Resource | 59 | @Resource |
| 58 | private ProductSpuApi productSpuApi; | 60 | private ProductSpuApi productSpuApi; |
| 59 | - @Resource | ||
| 60 | - private TradeOrderApi tradeOrderApi; | ||
| 61 | 61 | ||
| 62 | @GetMapping("/get-summary") | 62 | @GetMapping("/get-summary") |
| 63 | @Operation(summary = "获得砍价记录的概要信息", description = "用于小程序首页") | 63 | @Operation(summary = "获得砍价记录的概要信息", description = "用于小程序首页") |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationRecordController.java
| @@ -46,8 +46,8 @@ public class AppCombinationRecordController { | @@ -46,8 +46,8 @@ public class AppCombinationRecordController { | ||
| 46 | @Operation(summary = "获得拼团记录的概要信息", description = "用于小程序首页") | 46 | @Operation(summary = "获得拼团记录的概要信息", description = "用于小程序首页") |
| 47 | public CommonResult<AppCombinationRecordSummaryRespVO> getCombinationRecordSummary() { | 47 | public CommonResult<AppCombinationRecordSummaryRespVO> getCombinationRecordSummary() { |
| 48 | AppCombinationRecordSummaryRespVO summary = new AppCombinationRecordSummaryRespVO(); | 48 | AppCombinationRecordSummaryRespVO summary = new AppCombinationRecordSummaryRespVO(); |
| 49 | - // 1. 获得拼团记录数量 | ||
| 50 | - Long count = combinationRecordService.getCombinationRecordCount(null, null); | 49 | + // 1. 获得拼团参与用户数量 |
| 50 | + Long count = combinationRecordService.getCombinationRecordCount(null, 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
| @@ -28,7 +28,7 @@ import org.mapstruct.Mapping; | @@ -28,7 +28,7 @@ import org.mapstruct.Mapping; | ||
| 28 | import org.mapstruct.Mappings; | 28 | import org.mapstruct.Mappings; |
| 29 | import org.mapstruct.factory.Mappers; | 29 | import org.mapstruct.factory.Mappers; |
| 30 | 30 | ||
| 31 | -import java.time.LocalDateTime; | 31 | +import java.util.ArrayList; |
| 32 | import java.util.List; | 32 | import java.util.List; |
| 33 | import java.util.Map; | 33 | import java.util.Map; |
| 34 | 34 | ||
| @@ -114,9 +114,6 @@ public interface CombinationActivityConvert { | @@ -114,9 +114,6 @@ public interface CombinationActivityConvert { | ||
| 114 | ProductSpuRespDTO spu, ProductSkuRespDTO sku) { | 114 | ProductSpuRespDTO spu, ProductSkuRespDTO sku) { |
| 115 | return convert(reqDTO).setVirtualGroup(false) | 115 | return convert(reqDTO).setVirtualGroup(false) |
| 116 | .setStatus(CombinationRecordStatusEnum.IN_PROGRESS.getStatus()) // 创建后默认状态为进行中 | 116 | .setStatus(CombinationRecordStatusEnum.IN_PROGRESS.getStatus()) // 创建后默认状态为进行中 |
| 117 | - .setStartTime(LocalDateTime.now()) // TODO @puhui999:想了下,这个 startTime 应该是团长的; | ||
| 118 | - // TODO @puhui999:有团长的情况下,expireTime 应该是团长的; | ||
| 119 | - .setExpireTime(activity.getStartTime().plusHours(activity.getLimitDuration())) | ||
| 120 | .setUserSize(activity.getUserSize()).setUserCount(1) // 默认就是 1 插入后会接着更新一次所有的拼团记录 | 117 | .setUserSize(activity.getUserSize()).setUserCount(1) // 默认就是 1 插入后会接着更新一次所有的拼团记录 |
| 121 | // 用户信息 | 118 | // 用户信息 |
| 122 | .setNickname(user.getNickname()).setAvatar(user.getAvatar()) | 119 | .setNickname(user.getNickname()).setAvatar(user.getAvatar()) |
| @@ -200,4 +197,35 @@ public interface CombinationActivityConvert { | @@ -200,4 +197,35 @@ public interface CombinationActivityConvert { | ||
| 200 | return respVO; | 197 | return respVO; |
| 201 | } | 198 | } |
| 202 | 199 | ||
| 200 | + /** | ||
| 201 | + * 转换生成虚拟成团虚拟记录 | ||
| 202 | + * | ||
| 203 | + * @param virtualGroupHeadRecords 虚拟成团团长记录列表 | ||
| 204 | + * @return 虚拟记录列表 | ||
| 205 | + */ | ||
| 206 | + default List<CombinationRecordDO> convertVirtualGroupList(List<CombinationRecordDO> virtualGroupHeadRecords) { | ||
| 207 | + List<CombinationRecordDO> createRecords = new ArrayList<>(); | ||
| 208 | + virtualGroupHeadRecords.forEach(headRecord -> { | ||
| 209 | + // 计算需要创建的虚拟成团记录数量 | ||
| 210 | + int count = headRecord.getUserSize() - headRecord.getUserCount(); | ||
| 211 | + for (int i = 0; i < count; i++) { | ||
| 212 | + // 基础信息和团长保持一致 | ||
| 213 | + CombinationRecordDO newRecord = new CombinationRecordDO().setActivityId(headRecord.getActivityId()) | ||
| 214 | + .setCombinationPrice(headRecord.getCombinationPrice()).setSpuId(headRecord.getSpuId()).setSpuName(headRecord.getSpuName()) | ||
| 215 | + .setPicUrl(headRecord.getPicUrl()).setSkuId(headRecord.getSkuId()).setHeadId(headRecord.getId()) | ||
| 216 | + .setStatus(headRecord.getStatus()) // 状态保持和创建时一致,创建完成后会接着处理 | ||
| 217 | + .setVirtualGroup(headRecord.getVirtualGroup()).setExpireTime(headRecord.getExpireTime()) | ||
| 218 | + .setStartTime(headRecord.getStartTime()).setUserSize(headRecord.getUserSize()).setUserCount(headRecord.getUserCount()); | ||
| 219 | + // 虚拟信息 | ||
| 220 | + newRecord.setCount(0); | ||
| 221 | + newRecord.setUserId(0L); | ||
| 222 | + newRecord.setNickname(""); | ||
| 223 | + newRecord.setAvatar(""); | ||
| 224 | + newRecord.setOrderId(0L); | ||
| 225 | + createRecords.add(newRecord); | ||
| 226 | + } | ||
| 227 | + }); | ||
| 228 | + return createRecords; | ||
| 229 | + } | ||
| 230 | + | ||
| 203 | } | 231 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java
| @@ -6,13 +6,14 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | @@ -6,13 +6,14 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 7 | import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.activity.BargainActivityPageReqVO; | 7 | import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.activity.BargainActivityPageReqVO; |
| 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.query.QueryWrapper; | ||
| 9 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | 10 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| 10 | import org.apache.ibatis.annotations.Mapper; | 11 | import org.apache.ibatis.annotations.Mapper; |
| 11 | -import org.apache.ibatis.annotations.Select; | ||
| 12 | 12 | ||
| 13 | import java.time.LocalDateTime; | 13 | import java.time.LocalDateTime; |
| 14 | import java.util.Collection; | 14 | import java.util.Collection; |
| 15 | import java.util.List; | 15 | import java.util.List; |
| 16 | +import java.util.Map; | ||
| 16 | 17 | ||
| 17 | /** | 18 | /** |
| 18 | * 砍价活动 Mapper | 19 | * 砍价活动 Mapper |
| @@ -85,25 +86,26 @@ public interface BargainActivityMapper extends BaseMapperX<BargainActivityDO> { | @@ -85,25 +86,26 @@ public interface BargainActivityMapper extends BaseMapperX<BargainActivityDO> { | ||
| 85 | .last("LIMIT " + count)); | 86 | .last("LIMIT " + count)); |
| 86 | } | 87 | } |
| 87 | 88 | ||
| 88 | - // TODO @puhui999:一个商品,在统一时间,不会参与多个活动;so 是不是不用 inner join 哈? | ||
| 89 | - // PS:如果可以参与多个,其实可以这样写 select * from promotion_bargain_activity group by spu_id ORDER BY create_time DESC;通过 group 来过滤 | 89 | + // TODO @puhui999:是不是返回 BargainActivityDO 更干净哈? |
| 90 | /** | 90 | /** |
| 91 | - * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 | 91 | + * 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 |
| 92 | * | 92 | * |
| 93 | * @param spuIds spu 编号 | 93 | * @param spuIds spu 编号 |
| 94 | * @param status 状态 | 94 | * @param status 状态 |
| 95 | - * @return 砍价活动列表 | 95 | + * @return 包含 spuId 和 activityId 的 map 对象列表 |
| 96 | */ | 96 | */ |
| 97 | - @Select("SELECT p1.* " + | ||
| 98 | - "FROM promotion_bargain_activity p1 " + | ||
| 99 | - "INNER JOIN ( " + | ||
| 100 | - " SELECT spu_id, MAX(DISTINCT(create_time)) AS max_create_time " + | ||
| 101 | - " FROM promotion_bargain_activity " + | ||
| 102 | - " WHERE spu_id IN #{spuIds} " + | ||
| 103 | - " GROUP BY spu_id " + | ||
| 104 | - ") p2 " + | ||
| 105 | - "ON p1.spu_id = p2.spu_id AND p1.create_time = p2.max_create_time AND p1.status = #{status} " + | ||
| 106 | - "ORDER BY p1.create_time DESC;") | ||
| 107 | - List<BargainActivityDO> selectListBySpuIds(Collection<Long> spuIds, Integer status); | 97 | + default List<Map<String, Object>> selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { |
| 98 | + return selectMaps(new QueryWrapper<BargainActivityDO>() | ||
| 99 | + .select("spu_id AS spuId, MAX(DISTINCT(id)) AS activityId") // 时间越大 id 也越大 直接用 id | ||
| 100 | + .in("spu_id", spuIds) | ||
| 101 | + .eq("status", status) | ||
| 102 | + .groupBy("spu_id")); | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + default List<BargainActivityDO> selectListByIds(Collection<Long> ids) { | ||
| 106 | + return selectList(new LambdaQueryWrapperX<BargainActivityDO>() | ||
| 107 | + .in(BargainActivityDO::getId, ids) | ||
| 108 | + .orderByDesc(BargainActivityDO::getCreateTime)); | ||
| 109 | + } | ||
| 108 | 110 | ||
| 109 | } | 111 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationActivityMapper.java
| @@ -6,12 +6,13 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | @@ -6,12 +6,13 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 6 | 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 com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||
| 9 | import org.apache.ibatis.annotations.Mapper; | 10 | import org.apache.ibatis.annotations.Mapper; |
| 10 | import org.apache.ibatis.annotations.Param; | 11 | import org.apache.ibatis.annotations.Param; |
| 11 | -import org.apache.ibatis.annotations.Select; | ||
| 12 | 12 | ||
| 13 | import java.util.Collection; | 13 | import java.util.Collection; |
| 14 | import java.util.List; | 14 | import java.util.List; |
| 15 | +import java.util.Map; | ||
| 15 | 16 | ||
| 16 | /** | 17 | /** |
| 17 | * 拼团活动 Mapper | 18 | * 拼团活动 Mapper |
| @@ -43,24 +44,24 @@ public interface CombinationActivityMapper extends BaseMapperX<CombinationActivi | @@ -43,24 +44,24 @@ public interface CombinationActivityMapper extends BaseMapperX<CombinationActivi | ||
| 43 | .last("LIMIT " + count)); | 44 | .last("LIMIT " + count)); |
| 44 | } | 45 | } |
| 45 | 46 | ||
| 46 | - // TODO @puhui999:类似 BargainActivityMapper | ||
| 47 | /** | 47 | /** |
| 48 | - * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 | ||
| 49 | - * | 48 | + * 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 |
| 50 | * @param spuIds spu 编号 | 49 | * @param spuIds spu 编号 |
| 51 | * @param status 状态 | 50 | * @param status 状态 |
| 52 | - * @return 拼团活动列表 | 51 | + * @return 包含 spuId 和 activityId 的 map 对象列表 |
| 53 | */ | 52 | */ |
| 54 | - @Select("SELECT p1.* " + | ||
| 55 | - "FROM promotion_combination_activity p1 " + | ||
| 56 | - "INNER JOIN ( " + | ||
| 57 | - " SELECT spu_id, MAX(DISTINCT(create_time)) AS max_create_time " + | ||
| 58 | - " FROM promotion_combination_activity " + | ||
| 59 | - " WHERE spu_id IN #{spuIds} " + | ||
| 60 | - " GROUP BY spu_id " + | ||
| 61 | - ") p2 " + | ||
| 62 | - "ON p1.spu_id = p2.spu_id AND p1.create_time = p2.max_create_time AND p1.status = #{status} " + | ||
| 63 | - "ORDER BY p1.create_time DESC;") | ||
| 64 | - List<CombinationActivityDO> selectListBySpuIds(@Param("spuIds") Collection<Long> spuIds, @Param("status") Integer status); | 53 | + default List<Map<String, Object>> selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(@Param("spuIds") Collection<Long> spuIds, @Param("status") Integer status) { |
| 54 | + return selectMaps(new QueryWrapper<CombinationActivityDO>() | ||
| 55 | + .select("spu_id AS spuId, MAX(DISTINCT(id)) AS activityId") // 时间越大 id 也越大 直接用 id | ||
| 56 | + .in("spu_id", spuIds) | ||
| 57 | + .eq("status", status) | ||
| 58 | + .groupBy("spu_id")); | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + default List<CombinationActivityDO> selectListByIds(Collection<Long> ids) { | ||
| 62 | + return selectList(new LambdaQueryWrapperX<CombinationActivityDO>() | ||
| 63 | + .in(CombinationActivityDO::getId, ids) | ||
| 64 | + .orderByDesc(CombinationActivityDO::getCreateTime)); | ||
| 65 | + } | ||
| 65 | 66 | ||
| 66 | } | 67 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java
| @@ -6,11 +6,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | @@ -6,11 +6,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | 6 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 7 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 7 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 8 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 8 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 9 | +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPage2VO; | ||
| 9 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPageVO; | 10 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPageVO; |
| 10 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; | 11 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; |
| 11 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | 12 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| 12 | import org.apache.ibatis.annotations.Mapper; | 13 | import org.apache.ibatis.annotations.Mapper; |
| 13 | 14 | ||
| 15 | +import java.time.LocalDateTime; | ||
| 14 | import java.util.Collection; | 16 | import java.util.Collection; |
| 15 | import java.util.Collections; | 17 | import java.util.Collections; |
| 16 | import java.util.List; | 18 | import java.util.List; |
| @@ -100,13 +102,41 @@ public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO | @@ -100,13 +102,41 @@ public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO | ||
| 100 | .betweenIfPresent(CombinationRecordDO::getCreateTime, pageVO.getCreateTime())); | 102 | .betweenIfPresent(CombinationRecordDO::getCreateTime, pageVO.getCreateTime())); |
| 101 | } | 103 | } |
| 102 | 104 | ||
| 103 | - // TODO @puhui999:这个最好把 headId 也作为一个参数;因为有个要求 userCount,它要 DISTINCT 下;整体可以参考 selectCombinationRecordCountMapByActivityIdAndStatusAndHeadId | ||
| 104 | - default Long selectCountByHeadAndStatusAndVirtualGroup(Integer status, Boolean virtualGroup) { | ||
| 105 | - return selectCount(new LambdaQueryWrapperX<CombinationRecordDO>() | ||
| 106 | - .eq(status != null || virtualGroup != null, | ||
| 107 | - CombinationRecordDO::getHeadId, CombinationRecordDO.HEAD_ID_GROUP) // 统计团信息则指定团长 | ||
| 108 | - .eqIfPresent(CombinationRecordDO::getStatus, status) | ||
| 109 | - .eqIfPresent(CombinationRecordDO::getVirtualGroup, virtualGroup)); | 105 | + default PageResult<CombinationRecordDO> selectPage(CombinationRecordReqPage2VO pageVO) { |
| 106 | + return selectPage(pageVO, new LambdaQueryWrapperX<CombinationRecordDO>() | ||
| 107 | + .eq(CombinationRecordDO::getId, pageVO.getHeadId()) | ||
| 108 | + .or() | ||
| 109 | + .eq(CombinationRecordDO::getHeadId, pageVO.getHeadId())); | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + /** | ||
| 113 | + * 查询指定条件的记录数 | ||
| 114 | + * 如果参数都为 null 时则查询用户拼团记录(DISTINCT 去重),也就是说查询会员表中的用户有多少人参与过拼团活动每个人只统计一次 | ||
| 115 | + * | ||
| 116 | + * @param status 状态,可为 null | ||
| 117 | + * @param virtualGroup 是否虚拟成团,可为 null | ||
| 118 | + * @param headId 团长编号,可为 null | ||
| 119 | + * @return 记录数 | ||
| 120 | + */ | ||
| 121 | + default Long selectCountByHeadAndStatusAndVirtualGroup(Integer status, Boolean virtualGroup, Long headId) { | ||
| 122 | + return selectCount(new QueryWrapper<CombinationRecordDO>() | ||
| 123 | + // TODO @puhui999:这种偏逻辑性的,不要给 mapper 哈;可以考虑拆成 2 个 mapper,上层也是 2 个 service; | ||
| 124 | + .select(status == null && virtualGroup == null && headId == null, "DISTINCT (user_id)") | ||
| 125 | + .eq(status != null, "status", status) | ||
| 126 | + .eq(virtualGroup != null, "virtual_group", virtualGroup) | ||
| 127 | + .eq(headId != null, "head_id", headId) | ||
| 128 | + .groupBy("user_id")); | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + default List<CombinationRecordDO> selectListByHeadIdAndStatusAndExpireTimeLt(Long headId, Integer status, LocalDateTime dateTime) { | ||
| 132 | + return selectList(new LambdaQueryWrapperX<CombinationRecordDO>() | ||
| 133 | + .eq(CombinationRecordDO::getHeadId, headId) | ||
| 134 | + .eq(CombinationRecordDO::getStatus, status) | ||
| 135 | + .lt(CombinationRecordDO::getExpireTime, dateTime)); | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + default List<CombinationRecordDO> selectListByHeadIds(Collection<Long> headIds) { | ||
| 139 | + return selectList(new LambdaQueryWrapperX<CombinationRecordDO>().in(CombinationRecordDO::getHeadId, headIds)); | ||
| 110 | } | 140 | } |
| 111 | 141 | ||
| 112 | } | 142 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java
| 1 | package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity; | 1 | package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.lang.Assert; | ||
| 3 | import cn.hutool.core.util.ObjectUtil; | 4 | import cn.hutool.core.util.ObjectUtil; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| @@ -7,12 +8,14 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | @@ -7,12 +8,14 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 7 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; | 8 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; |
| 8 | import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityPageReqVO; | 9 | import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityPageReqVO; |
| 9 | import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO; | 10 | import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO; |
| 11 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||
| 10 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | 12 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| 11 | import org.apache.ibatis.annotations.Mapper; | 13 | import org.apache.ibatis.annotations.Mapper; |
| 12 | -import org.apache.ibatis.annotations.Select; | 14 | +import org.apache.ibatis.annotations.Param; |
| 13 | 15 | ||
| 14 | import java.util.Collection; | 16 | import java.util.Collection; |
| 15 | import java.util.List; | 17 | import java.util.List; |
| 18 | +import java.util.Map; | ||
| 16 | 19 | ||
| 17 | /** | 20 | /** |
| 18 | * 秒杀活动 Mapper | 21 | * 秒杀活动 Mapper |
| @@ -37,18 +40,32 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> { | @@ -37,18 +40,32 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> { | ||
| 37 | } | 40 | } |
| 38 | 41 | ||
| 39 | /** | 42 | /** |
| 40 | - * 更新活动库存 | 43 | + * 更新活动库存(减少) |
| 41 | * | 44 | * |
| 42 | * @param id 活动编号 | 45 | * @param id 活动编号 |
| 43 | - * @param count 扣减的库存数量 | 46 | + * @param count 扣减的库存数量(正数) |
| 44 | * @return 影响的行数 | 47 | * @return 影响的行数 |
| 45 | */ | 48 | */ |
| 46 | - default int updateStock(Long id, int count) { | 49 | + default int updateStockDecr(Long id, int count) { |
| 50 | + Assert.isTrue(count > 0); | ||
| 47 | return update(null, new LambdaUpdateWrapper<SeckillActivityDO>() | 51 | return update(null, new LambdaUpdateWrapper<SeckillActivityDO>() |
| 48 | .eq(SeckillActivityDO::getId, id) | 52 | .eq(SeckillActivityDO::getId, id) |
| 49 | - .gt(SeckillActivityDO::getTotalStock, 0) | ||
| 50 | - .setSql("stock = stock + " + count) | ||
| 51 | - .setSql("total_stock = total_stock - " + count)); | 53 | + .gt(SeckillActivityDO::getStock, count) |
| 54 | + .setSql("stock = stock - " + count)); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + /** | ||
| 58 | + * 更新活动库存(增加) | ||
| 59 | + * | ||
| 60 | + * @param id 活动编号 | ||
| 61 | + * @param count 增加的库存数量(正数) | ||
| 62 | + * @return 影响的行数 | ||
| 63 | + */ | ||
| 64 | + default int updateStockIncr(Long id, int count) { | ||
| 65 | + Assert.isTrue(count > 0); | ||
| 66 | + return update(null, new LambdaUpdateWrapper<SeckillActivityDO>() | ||
| 67 | + .eq(SeckillActivityDO::getId, id) | ||
| 68 | + .setSql("stock = stock + " + count)); | ||
| 52 | } | 69 | } |
| 53 | 70 | ||
| 54 | default PageResult<SeckillActivityDO> selectPage(AppSeckillActivityPageReqVO pageReqVO, Integer status) { | 71 | default PageResult<SeckillActivityDO> selectPage(AppSeckillActivityPageReqVO pageReqVO, Integer status) { |
| @@ -58,24 +75,25 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> { | @@ -58,24 +75,25 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> { | ||
| 58 | .apply(ObjectUtil.isNotNull(pageReqVO.getConfigId()), "FIND_IN_SET(" + pageReqVO.getConfigId() + ",config_ids) > 0")); | 75 | .apply(ObjectUtil.isNotNull(pageReqVO.getConfigId()), "FIND_IN_SET(" + pageReqVO.getConfigId() + ",config_ids) > 0")); |
| 59 | } | 76 | } |
| 60 | 77 | ||
| 61 | - // TODO @puhui999:类似 BargainActivityMapper | ||
| 62 | /** | 78 | /** |
| 63 | - * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 | 79 | + * 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 |
| 64 | * | 80 | * |
| 65 | * @param spuIds spu 编号 | 81 | * @param spuIds spu 编号 |
| 66 | * @param status 状态 | 82 | * @param status 状态 |
| 67 | - * @return 秒杀活动列表 | 83 | + * @return 包含 spuId 和 activityId 的 map 对象列表 |
| 68 | */ | 84 | */ |
| 69 | - @Select("SELECT p1.* " + | ||
| 70 | - "FROM promotion_seckill_activity p1 " + | ||
| 71 | - "INNER JOIN ( " + | ||
| 72 | - " SELECT spu_id, MAX(DISTINCT(create_time)) AS max_create_time " + | ||
| 73 | - " FROM promotion_seckill_activity " + | ||
| 74 | - " WHERE spu_id IN #{spuIds} " + | ||
| 75 | - " GROUP BY spu_id " + | ||
| 76 | - ") p2 " + | ||
| 77 | - "ON p1.spu_id = p2.spu_id AND p1.create_time = p2.max_create_time AND p1.status = #{status} " + | ||
| 78 | - "ORDER BY p1.create_time DESC;") | ||
| 79 | - List<SeckillActivityDO> selectListBySpuIds(Collection<Long> spuIds, Integer status); | 85 | + default List<Map<String, Object>> selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(@Param("spuIds") Collection<Long> spuIds, @Param("status") Integer status) { |
| 86 | + return selectMaps(new QueryWrapper<SeckillActivityDO>() | ||
| 87 | + .select("spu_id AS spuId, MAX(DISTINCT(id)) AS activityId") // 时间越大 id 也越大 直接用 id | ||
| 88 | + .in("spu_id", spuIds) | ||
| 89 | + .eq("status", status) | ||
| 90 | + .groupBy("spu_id")); | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + default List<SeckillActivityDO> selectListByIds(Collection<Long> ids) { | ||
| 94 | + return selectList(new LambdaQueryWrapperX<SeckillActivityDO>() | ||
| 95 | + .in(SeckillActivityDO::getId, ids) | ||
| 96 | + .orderByDesc(SeckillActivityDO::getCreateTime)); | ||
| 97 | + } | ||
| 80 | 98 | ||
| 81 | } | 99 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java
| 1 | package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity; | 1 | package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.lang.Assert; | ||
| 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 4 | import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO; | 5 | import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO; |
| 5 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | 6 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| @@ -30,17 +31,32 @@ public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> { | @@ -30,17 +31,32 @@ public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> { | ||
| 30 | } | 31 | } |
| 31 | 32 | ||
| 32 | /** | 33 | /** |
| 33 | - * 更新活动库存 | 34 | + * 更新活动库存(减少) |
| 34 | * | 35 | * |
| 35 | * @param id 活动编号 | 36 | * @param id 活动编号 |
| 36 | - * @param count 扣减的库存数量 | 37 | + * @param count 扣减的库存数量(减少库存) |
| 37 | * @return 影响的行数 | 38 | * @return 影响的行数 |
| 38 | */ | 39 | */ |
| 39 | - default int updateStock(Long id, int count) { | 40 | + default int updateStockDecr(Long id, int count) { |
| 41 | + Assert.isTrue(count > 0); | ||
| 40 | return update(null, new LambdaUpdateWrapper<SeckillProductDO>() | 42 | return update(null, new LambdaUpdateWrapper<SeckillProductDO>() |
| 41 | .eq(SeckillProductDO::getId, id) | 43 | .eq(SeckillProductDO::getId, id) |
| 42 | - .gt(SeckillProductDO::getStock, count) | 44 | + .ge(SeckillProductDO::getStock, count) |
| 43 | .setSql("stock = stock - " + count)); | 45 | .setSql("stock = stock - " + count)); |
| 44 | } | 46 | } |
| 45 | 47 | ||
| 48 | + /** | ||
| 49 | + * 更新活动库存(增加) | ||
| 50 | + * | ||
| 51 | + * @param id 活动编号 | ||
| 52 | + * @param count 需要增加的库存(增加库存) | ||
| 53 | + * @return 影响的行数 | ||
| 54 | + */ | ||
| 55 | + default int updateStockIncr(Long id, int count) { | ||
| 56 | + Assert.isTrue(count > 0); | ||
| 57 | + return update(null, new LambdaUpdateWrapper<SeckillProductDO>() | ||
| 58 | + .eq(SeckillProductDO::getId, id) | ||
| 59 | + .setSql("stock = stock + " + count)); | ||
| 60 | + } | ||
| 61 | + | ||
| 46 | } | 62 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/job/combination/CombinationRecordExpireJob.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.job.combination; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.StrUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.core.KeyValue; | ||
| 5 | +import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; | ||
| 6 | +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; | ||
| 7 | +import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService; | ||
| 8 | +import org.springframework.stereotype.Component; | ||
| 9 | + | ||
| 10 | +import javax.annotation.Resource; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 拼团过期 Job | ||
| 14 | + * | ||
| 15 | + * @author HUIHUI | ||
| 16 | + */ | ||
| 17 | +@Component | ||
| 18 | +public class CombinationRecordExpireJob implements JobHandler { | ||
| 19 | + | ||
| 20 | + @Resource | ||
| 21 | + private CombinationRecordService combinationRecordService; | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + @TenantJob | ||
| 25 | + public String execute(String param) { | ||
| 26 | + KeyValue<Integer, Integer> keyValue = combinationRecordService.expireCombinationRecord(); | ||
| 27 | + return StrUtil.format("过期拼团 {} 个, 虚拟成团 {} 个", keyValue.getKey(), keyValue.getValue()); | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | +} |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java
| 1 | package cn.iocoder.yudao.module.promotion.service.bargain; | 1 | package cn.iocoder.yudao.module.promotion.service.bargain; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.hutool.core.map.MapUtil; | ||
| 3 | import cn.hutool.core.util.ObjUtil; | 5 | import cn.hutool.core.util.ObjUtil; |
| 4 | import cn.hutool.core.util.ObjectUtil; | 6 | import cn.hutool.core.util.ObjectUtil; |
| 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 7 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| @@ -20,12 +22,11 @@ import org.springframework.validation.annotation.Validated; | @@ -20,12 +22,11 @@ import org.springframework.validation.annotation.Validated; | ||
| 20 | 22 | ||
| 21 | import javax.annotation.Resource; | 23 | import javax.annotation.Resource; |
| 22 | import java.time.LocalDateTime; | 24 | import java.time.LocalDateTime; |
| 23 | -import java.util.Collection; | ||
| 24 | -import java.util.List; | ||
| 25 | -import java.util.Set; | 25 | +import java.util.*; |
| 26 | 26 | ||
| 27 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 27 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 28 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch; | 28 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch; |
| 29 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 29 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; | 30 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; |
| 30 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; | 31 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; |
| 31 | 32 | ||
| @@ -84,10 +85,14 @@ public class BargainActivityServiceImpl implements BargainActivityService { | @@ -84,10 +85,14 @@ public class BargainActivityServiceImpl implements BargainActivityService { | ||
| 84 | 85 | ||
| 85 | @Override | 86 | @Override |
| 86 | public void updateBargainActivityStock(Long id, Integer count) { | 87 | public void updateBargainActivityStock(Long id, Integer count) { |
| 87 | - // 更新库存。如果更新失败,则抛出异常 | ||
| 88 | - int updateCount = bargainActivityMapper.updateStock(id, count); | ||
| 89 | - if (updateCount == 0) { | ||
| 90 | - throw exception(BARGAIN_ACTIVITY_STOCK_NOT_ENOUGH); | 88 | + if (count < 0) { |
| 89 | + // 更新库存。如果更新失败,则抛出异常 | ||
| 90 | + int updateCount = bargainActivityMapper.updateStock(id, count); | ||
| 91 | + if (updateCount == 0) { | ||
| 92 | + throw exception(BARGAIN_ACTIVITY_STOCK_NOT_ENOUGH); | ||
| 93 | + } | ||
| 94 | + } else if (count > 0) { | ||
| 95 | + bargainActivityMapper.updateStock(id, count); | ||
| 91 | } | 96 | } |
| 92 | } | 97 | } |
| 93 | 98 | ||
| @@ -139,7 +144,7 @@ public class BargainActivityServiceImpl implements BargainActivityService { | @@ -139,7 +144,7 @@ public class BargainActivityServiceImpl implements BargainActivityService { | ||
| 139 | 144 | ||
| 140 | @Override | 145 | @Override |
| 141 | public List<BargainActivityDO> getBargainActivityList(Set<Long> ids) { | 146 | public List<BargainActivityDO> getBargainActivityList(Set<Long> ids) { |
| 142 | - return bargainActivityMapper.selectBatchIds(ids); | 147 | + return bargainActivityMapper.selectBatchIds(ids); |
| 143 | } | 148 | } |
| 144 | 149 | ||
| 145 | @Override | 150 | @Override |
| @@ -178,7 +183,14 @@ public class BargainActivityServiceImpl implements BargainActivityService { | @@ -178,7 +183,14 @@ public class BargainActivityServiceImpl implements BargainActivityService { | ||
| 178 | 183 | ||
| 179 | @Override | 184 | @Override |
| 180 | public List<BargainActivityDO> getBargainActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { | 185 | public List<BargainActivityDO> getBargainActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { |
| 181 | - return bargainActivityMapper.selectListBySpuIds(spuIds, status); | 186 | + // 1. 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 |
| 187 | + // TODO @puhui999:我想了下,这种是不是只展示当前正在进行中的。已经结束、或者未开始的,可能没啥意义? | ||
| 188 | + List<Map<String, Object>> spuIdAndActivityIdMaps = bargainActivityMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status); | ||
| 189 | + if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) { | ||
| 190 | + return Collections.emptyList(); | ||
| 191 | + } | ||
| 192 | + // 2. 查询活动详情 | ||
| 193 | + return bargainActivityMapper.selectListByIds(convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId"))); | ||
| 182 | } | 194 | } |
| 183 | 195 | ||
| 184 | } | 196 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
| 1 | package cn.iocoder.yudao.module.promotion.service.combination; | 1 | package cn.iocoder.yudao.module.promotion.service.combination; |
| 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.util.ObjectUtil; | 5 | import cn.hutool.core.util.ObjectUtil; |
| 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 6 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageParam; | 7 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| @@ -25,12 +26,12 @@ import org.springframework.validation.annotation.Validated; | @@ -25,12 +26,12 @@ import org.springframework.validation.annotation.Validated; | ||
| 25 | 26 | ||
| 26 | import javax.annotation.Resource; | 27 | import javax.annotation.Resource; |
| 27 | import java.util.Collection; | 28 | import java.util.Collection; |
| 29 | +import java.util.Collections; | ||
| 28 | import java.util.List; | 30 | import java.util.List; |
| 29 | import java.util.Map; | 31 | import java.util.Map; |
| 30 | 32 | ||
| 31 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 33 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 32 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||
| 33 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; | 34 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; |
| 34 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; | 35 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; |
| 35 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; | 36 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; |
| 36 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; | 37 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; |
| @@ -228,7 +229,13 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic | @@ -228,7 +229,13 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic | ||
| 228 | 229 | ||
| 229 | @Override | 230 | @Override |
| 230 | public List<CombinationActivityDO> getCombinationActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { | 231 | public List<CombinationActivityDO> getCombinationActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { |
| 231 | - return combinationActivityMapper.selectListBySpuIds(spuIds, status); | 232 | + // 1.查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 |
| 233 | + List<Map<String, Object>> spuIdAndActivityIdMaps = combinationActivityMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status); | ||
| 234 | + if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) { | ||
| 235 | + return Collections.emptyList(); | ||
| 236 | + } | ||
| 237 | + // 2.查询活动详情 | ||
| 238 | + return combinationActivityMapper.selectListByIds(convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId"))); | ||
| 232 | } | 239 | } |
| 233 | 240 | ||
| 234 | } | 241 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java
| @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; | @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; | ||
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; | 5 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; |
| 6 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO; | 6 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO; |
| 7 | +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPage2VO; | ||
| 7 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPageVO; | 8 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPageVO; |
| 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; | 9 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; |
| 9 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO; | 10 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO; |
| @@ -49,9 +50,9 @@ public interface CombinationRecordService { | @@ -49,9 +50,9 @@ public interface CombinationRecordService { | ||
| 49 | * 创建拼团记录 | 50 | * 创建拼团记录 |
| 50 | * | 51 | * |
| 51 | * @param reqDTO 创建信息 | 52 | * @param reqDTO 创建信息 |
| 52 | - * @return 开团记录编号 | 53 | + * @return key 开团记录编号 value 团长编号 |
| 53 | */ | 54 | */ |
| 54 | - Long createCombinationRecord(CombinationRecordCreateReqDTO reqDTO); | 55 | + KeyValue<Long, Long> createCombinationRecord(CombinationRecordCreateReqDTO reqDTO); |
| 55 | 56 | ||
| 56 | /** | 57 | /** |
| 57 | * 获得拼团记录 | 58 | * 获得拼团记录 |
| @@ -90,9 +91,10 @@ public interface CombinationRecordService { | @@ -90,9 +91,10 @@ public interface CombinationRecordService { | ||
| 90 | * | 91 | * |
| 91 | * @param status 状态-允许为空 | 92 | * @param status 状态-允许为空 |
| 92 | * @param virtualGroup 是否虚拟成团-允许为空 | 93 | * @param virtualGroup 是否虚拟成团-允许为空 |
| 94 | + * @param headId 团长编号,允许空。目的 headId 设置为 {@link CombinationRecordDO#HEAD_ID_GROUP} 时,可以设置 | ||
| 93 | * @return 记录数 | 95 | * @return 记录数 |
| 94 | */ | 96 | */ |
| 95 | - Long getCombinationRecordCount(@Nullable Integer status, @Nullable Boolean virtualGroup); | 97 | + Long getCombinationRecordCount(@Nullable Integer status, @Nullable Boolean virtualGroup, @Nullable Long headId); |
| 96 | 98 | ||
| 97 | /** | 99 | /** |
| 98 | * 获取最近的 count 条拼团记录 | 100 | * 获取最近的 count 条拼团记录 |
| @@ -137,6 +139,14 @@ public interface CombinationRecordService { | @@ -137,6 +139,14 @@ public interface CombinationRecordService { | ||
| 137 | PageResult<CombinationRecordDO> getCombinationRecordPage(CombinationRecordReqPageVO pageVO); | 139 | PageResult<CombinationRecordDO> getCombinationRecordPage(CombinationRecordReqPageVO pageVO); |
| 138 | 140 | ||
| 139 | /** | 141 | /** |
| 142 | + * 获取拼团记录分页数据(通过团长查询) | ||
| 143 | + * | ||
| 144 | + * @param pageVO 分页请求 | ||
| 145 | + * @return 拼团记录分页数据(包括团长的) | ||
| 146 | + */ | ||
| 147 | + PageResult<CombinationRecordDO> getCombinationRecordPage2(CombinationRecordReqPage2VO pageVO); | ||
| 148 | + | ||
| 149 | + /** | ||
| 140 | * 【拼团活动】获得拼团记录数量 Map | 150 | * 【拼团活动】获得拼团记录数量 Map |
| 141 | * | 151 | * |
| 142 | * @param activityIds 活动记录编号数组 | 152 | * @param activityIds 活动记录编号数组 |
| @@ -148,7 +158,6 @@ public interface CombinationRecordService { | @@ -148,7 +158,6 @@ public interface CombinationRecordService { | ||
| 148 | @Nullable Integer status, | 158 | @Nullable Integer status, |
| 149 | @Nullable Long headId); | 159 | @Nullable Long headId); |
| 150 | 160 | ||
| 151 | - | ||
| 152 | /** | 161 | /** |
| 153 | * 获取拼团记录 | 162 | * 获取拼团记录 |
| 154 | * | 163 | * |
| @@ -167,5 +176,11 @@ public interface CombinationRecordService { | @@ -167,5 +176,11 @@ public interface CombinationRecordService { | ||
| 167 | */ | 176 | */ |
| 168 | void cancelCombinationRecord(Long userId, Long id, Long headId); | 177 | void cancelCombinationRecord(Long userId, Long id, Long headId); |
| 169 | 178 | ||
| 179 | + /** | ||
| 180 | + * 处理过期拼团 | ||
| 181 | + * | ||
| 182 | + * @return key 过期拼团数量, value 虚拟成团数量 | ||
| 183 | + */ | ||
| 184 | + KeyValue<Integer, Integer> expireCombinationRecord(); | ||
| 170 | 185 | ||
| 171 | } | 186 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.service.combination; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.service.combination; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.core.util.ObjUtil; | 4 | import cn.hutool.core.util.ObjUtil; |
| 5 | +import cn.hutool.extra.spring.SpringUtil; | ||
| 5 | import cn.iocoder.yudao.framework.common.core.KeyValue; | 6 | import cn.iocoder.yudao.framework.common.core.KeyValue; |
| 6 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 7 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| @@ -13,6 +14,7 @@ import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; | @@ -13,6 +14,7 @@ import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; | ||
| 13 | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; | 14 | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; |
| 14 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; | 15 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; |
| 15 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO; | 16 | import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO; |
| 17 | +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPage2VO; | ||
| 16 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPageVO; | 18 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.recrod.CombinationRecordReqPageVO; |
| 17 | import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; | 19 | import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; |
| 18 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; | 20 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; |
| @@ -21,18 +23,18 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationR | @@ -21,18 +23,18 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationR | ||
| 21 | import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper; | 23 | import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper; |
| 22 | import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; | 24 | import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; |
| 23 | import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi; | 25 | import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi; |
| 24 | -import org.springframework.context.annotation.Lazy; | 26 | +import org.springframework.scheduling.annotation.Async; |
| 25 | import org.springframework.stereotype.Service; | 27 | import org.springframework.stereotype.Service; |
| 26 | import org.springframework.transaction.annotation.Transactional; | 28 | import org.springframework.transaction.annotation.Transactional; |
| 27 | import org.springframework.validation.annotation.Validated; | 29 | import org.springframework.validation.annotation.Validated; |
| 28 | 30 | ||
| 29 | import javax.annotation.Nullable; | 31 | import javax.annotation.Nullable; |
| 30 | import javax.annotation.Resource; | 32 | import javax.annotation.Resource; |
| 33 | +import java.time.LocalDateTime; | ||
| 31 | import java.util.*; | 34 | import java.util.*; |
| 32 | 35 | ||
| 33 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 36 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 34 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.findFirst; | ||
| 35 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; | 37 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; |
| 36 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.afterNow; | 38 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.afterNow; |
| 37 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.beforeNow; | 39 | import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.beforeNow; |
| 38 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; | 40 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; |
| @@ -49,23 +51,20 @@ import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; | @@ -49,23 +51,20 @@ import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; | ||
| 49 | public class CombinationRecordServiceImpl implements CombinationRecordService { | 51 | public class CombinationRecordServiceImpl implements CombinationRecordService { |
| 50 | 52 | ||
| 51 | @Resource | 53 | @Resource |
| 52 | - @Lazy | ||
| 53 | private CombinationActivityService combinationActivityService; | 54 | private CombinationActivityService combinationActivityService; |
| 54 | @Resource | 55 | @Resource |
| 55 | - private CombinationRecordMapper recordMapper; | 56 | + private CombinationRecordMapper combinationRecordMapper; |
| 56 | 57 | ||
| 57 | @Resource | 58 | @Resource |
| 58 | private MemberUserApi memberUserApi; | 59 | private MemberUserApi memberUserApi; |
| 59 | @Resource | 60 | @Resource |
| 60 | - @Lazy | ||
| 61 | private ProductSpuApi productSpuApi; | 61 | private ProductSpuApi productSpuApi; |
| 62 | @Resource | 62 | @Resource |
| 63 | - @Lazy | ||
| 64 | private ProductSkuApi productSkuApi; | 63 | private ProductSkuApi productSkuApi; |
| 64 | + | ||
| 65 | @Resource | 65 | @Resource |
| 66 | private TradeOrderApi tradeOrderApi; | 66 | private TradeOrderApi tradeOrderApi; |
| 67 | 67 | ||
| 68 | - // TODO @芋艿:在详细预览下; | ||
| 69 | @Override | 68 | @Override |
| 70 | @Transactional(rollbackFor = Exception.class) | 69 | @Transactional(rollbackFor = Exception.class) |
| 71 | public void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId) { | 70 | public void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId) { |
| @@ -73,13 +72,14 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -73,13 +72,14 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 73 | CombinationRecordDO record = validateCombinationRecord(userId, orderId); | 72 | CombinationRecordDO record = validateCombinationRecord(userId, orderId); |
| 74 | 73 | ||
| 75 | // 更新状态 | 74 | // 更新状态 |
| 75 | + // TODO @puhui999:不要整个更新,new 一个出来;why?例如说,两个线程都去更新,这样存在相互覆盖的问题 | ||
| 76 | record.setStatus(status); | 76 | record.setStatus(status); |
| 77 | - recordMapper.updateById(record); | 77 | + combinationRecordMapper.updateById(record); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | private CombinationRecordDO validateCombinationRecord(Long userId, Long orderId) { | 80 | private CombinationRecordDO validateCombinationRecord(Long userId, Long orderId) { |
| 81 | // 校验拼团是否存在 | 81 | // 校验拼团是否存在 |
| 82 | - CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(userId, orderId); | 82 | + CombinationRecordDO recordDO = combinationRecordMapper.selectByUserIdAndOrderId(userId, orderId); |
| 83 | if (recordDO == null) { | 83 | if (recordDO == null) { |
| 84 | throw exception(COMBINATION_RECORD_NOT_EXISTS); | 84 | throw exception(COMBINATION_RECORD_NOT_EXISTS); |
| 85 | } | 85 | } |
| @@ -108,7 +108,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -108,7 +108,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 108 | // 2. 父拼团是否存在,是否已经满了 | 108 | // 2. 父拼团是否存在,是否已经满了 |
| 109 | if (headId != null) { | 109 | if (headId != null) { |
| 110 | // 2.1. 查询进行中的父拼团 | 110 | // 2.1. 查询进行中的父拼团 |
| 111 | - CombinationRecordDO record = recordMapper.selectByHeadId(headId, CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); | 111 | + CombinationRecordDO record = combinationRecordMapper.selectByHeadId(headId, CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); |
| 112 | if (record == null) { | 112 | if (record == null) { |
| 113 | throw exception(COMBINATION_RECORD_HEAD_NOT_EXISTS); | 113 | throw exception(COMBINATION_RECORD_HEAD_NOT_EXISTS); |
| 114 | } | 114 | } |
| @@ -143,7 +143,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -143,7 +143,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | // 6.1 校验是否有拼团记录 | 145 | // 6.1 校验是否有拼团记录 |
| 146 | - List<CombinationRecordDO> recordList = recordMapper.selectListByUserIdAndActivityId(userId, activityId); | 146 | + List<CombinationRecordDO> recordList = combinationRecordMapper.selectListByUserIdAndActivityId(userId, activityId); |
| 147 | recordList.removeIf(record -> CombinationRecordStatusEnum.isFailed(record.getStatus())); // 取消的订单,不算数 | 147 | recordList.removeIf(record -> CombinationRecordStatusEnum.isFailed(record.getStatus())); // 取消的订单,不算数 |
| 148 | if (CollUtil.isEmpty(recordList)) { // 如果为空,说明可以参与,直接返回 | 148 | if (CollUtil.isEmpty(recordList)) { // 如果为空,说明可以参与,直接返回 |
| 149 | return new KeyValue<>(activity, product); | 149 | return new KeyValue<>(activity, product); |
| @@ -164,32 +164,34 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -164,32 +164,34 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 164 | 164 | ||
| 165 | @Override | 165 | @Override |
| 166 | @Transactional(rollbackFor = Exception.class) | 166 | @Transactional(rollbackFor = Exception.class) |
| 167 | - public Long createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { | 167 | + public KeyValue<Long, Long> createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { |
| 168 | // 1. 校验拼团活动 | 168 | // 1. 校验拼团活动 |
| 169 | KeyValue<CombinationActivityDO, CombinationProductDO> keyValue = validateCombinationRecord(reqDTO.getUserId(), | 169 | KeyValue<CombinationActivityDO, CombinationProductDO> keyValue = validateCombinationRecord(reqDTO.getUserId(), |
| 170 | reqDTO.getActivityId(), reqDTO.getHeadId(), reqDTO.getSkuId(), reqDTO.getCount()); | 170 | reqDTO.getActivityId(), reqDTO.getHeadId(), reqDTO.getSkuId(), reqDTO.getCount()); |
| 171 | 171 | ||
| 172 | - // 2.1 组合数据创建拼团记录 | 172 | + // 2. 组合数据创建拼团记录 |
| 173 | MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId()); | 173 | MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId()); |
| 174 | ProductSpuRespDTO spu = productSpuApi.getSpu(reqDTO.getSpuId()); | 174 | ProductSpuRespDTO spu = productSpuApi.getSpu(reqDTO.getSpuId()); |
| 175 | ProductSkuRespDTO sku = productSkuApi.getSku(reqDTO.getSkuId()); | 175 | ProductSkuRespDTO sku = productSkuApi.getSku(reqDTO.getSkuId()); |
| 176 | CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO, keyValue.getKey(), user, spu, sku); | 176 | CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO, keyValue.getKey(), user, spu, sku); |
| 177 | - // 2.2 如果是团长需要设置 headId 为 CombinationRecordDO#HEAD_ID_GROUP | 177 | + // 2.1. 如果是团长需要设置 headId 为 CombinationRecordDO#HEAD_ID_GROUP |
| 178 | if (record.getHeadId() == null) { | 178 | if (record.getHeadId() == null) { |
| 179 | - record.setHeadId(CombinationRecordDO.HEAD_ID_GROUP); | 179 | + record.setStartTime(LocalDateTime.now()) |
| 180 | + .setExpireTime(keyValue.getKey().getStartTime().plusHours(keyValue.getKey().getLimitDuration())) | ||
| 181 | + .setHeadId(CombinationRecordDO.HEAD_ID_GROUP); | ||
| 182 | + } else { | ||
| 183 | + // 2.2.有团长的情况下需要设置开始时间和过期时间为团长的 | ||
| 184 | + CombinationRecordDO headRecord = combinationRecordMapper.selectByHeadId(record.getHeadId(), | ||
| 185 | + CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); // 查询进行中的父拼团 | ||
| 186 | + record.setStartTime(headRecord.getStartTime()).setExpireTime(headRecord.getExpireTime()); | ||
| 180 | } | 187 | } |
| 181 | - recordMapper.insert(record); | 188 | + combinationRecordMapper.insert(record); |
| 182 | 189 | ||
| 183 | - if (ObjUtil.equal(CombinationRecordDO.HEAD_ID_GROUP, record.getHeadId())) { | ||
| 184 | - return record.getId(); | 190 | + // 3. 更新拼团记录 |
| 191 | + if (ObjUtil.notEqual(CombinationRecordDO.HEAD_ID_GROUP, record.getHeadId())) { | ||
| 192 | + updateCombinationRecordWhenCreate(reqDTO.getHeadId(), keyValue.getKey()); | ||
| 185 | } | 193 | } |
| 186 | - | ||
| 187 | - // TODO @puhui:是不是这里的更新,放到 order 模块那;支付完成后; | ||
| 188 | - // 4、更新拼团相关信息到订单 | ||
| 189 | - tradeOrderApi.updateOrderCombinationInfo(record.getOrderId(), record.getActivityId(), record.getId(), record.getHeadId()); | ||
| 190 | - // 4、更新拼团记录 | ||
| 191 | - updateCombinationRecordWhenCreate(reqDTO.getHeadId(), keyValue.getKey()); | ||
| 192 | - return record.getId(); | 194 | + return new KeyValue<>(record.getId(), record.getHeadId()); |
| 193 | } | 195 | } |
| 194 | 196 | ||
| 195 | /** | 197 | /** |
| @@ -204,31 +206,33 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -204,31 +206,33 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 204 | if (CollUtil.isEmpty(records)) { | 206 | if (CollUtil.isEmpty(records)) { |
| 205 | return; | 207 | return; |
| 206 | } | 208 | } |
| 207 | - CombinationRecordDO headRecord = recordMapper.selectById(headId); | 209 | + CombinationRecordDO headRecord = combinationRecordMapper.selectById(headId); |
| 208 | 210 | ||
| 209 | // 2. 批量更新记录 | 211 | // 2. 批量更新记录 |
| 210 | List<CombinationRecordDO> updateRecords = new ArrayList<>(); | 212 | List<CombinationRecordDO> updateRecords = new ArrayList<>(); |
| 211 | records.add(headRecord); // 加入团长,团长也需要更新 | 213 | records.add(headRecord); // 加入团长,团长也需要更新 |
| 212 | boolean isFull = records.size() >= activity.getUserSize(); | 214 | boolean isFull = records.size() >= activity.getUserSize(); |
| 215 | + LocalDateTime now = LocalDateTime.now(); | ||
| 213 | records.forEach(item -> { | 216 | records.forEach(item -> { |
| 214 | CombinationRecordDO updateRecord = new CombinationRecordDO(); | 217 | CombinationRecordDO updateRecord = new CombinationRecordDO(); |
| 215 | updateRecord.setId(item.getId()).setUserCount(records.size()); | 218 | updateRecord.setId(item.getId()).setUserCount(records.size()); |
| 216 | if (isFull) { | 219 | if (isFull) { |
| 217 | updateRecord.setStatus(CombinationRecordStatusEnum.SUCCESS.getStatus()); | 220 | updateRecord.setStatus(CombinationRecordStatusEnum.SUCCESS.getStatus()); |
| 221 | + updateRecord.setEndTime(now); | ||
| 218 | } | 222 | } |
| 219 | updateRecords.add(updateRecord); | 223 | updateRecords.add(updateRecord); |
| 220 | }); | 224 | }); |
| 221 | - recordMapper.updateBatch(updateRecords); | 225 | + combinationRecordMapper.updateBatch(updateRecords); |
| 222 | } | 226 | } |
| 223 | 227 | ||
| 224 | @Override | 228 | @Override |
| 225 | public CombinationRecordDO getCombinationRecord(Long userId, Long orderId) { | 229 | public CombinationRecordDO getCombinationRecord(Long userId, Long orderId) { |
| 226 | - return recordMapper.selectByUserIdAndOrderId(userId, orderId); | 230 | + return combinationRecordMapper.selectByUserIdAndOrderId(userId, orderId); |
| 227 | } | 231 | } |
| 228 | 232 | ||
| 229 | @Override | 233 | @Override |
| 230 | public List<CombinationRecordDO> getCombinationRecordListByUserIdAndActivityId(Long userId, Long activityId) { | 234 | public List<CombinationRecordDO> getCombinationRecordListByUserIdAndActivityId(Long userId, Long activityId) { |
| 231 | - return recordMapper.selectListByUserIdAndActivityId(userId, activityId); | 235 | + return combinationRecordMapper.selectListByUserIdAndActivityId(userId, activityId); |
| 232 | } | 236 | } |
| 233 | 237 | ||
| 234 | @Override | 238 | @Override |
| @@ -241,52 +245,57 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -241,52 +245,57 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 241 | } | 245 | } |
| 242 | 246 | ||
| 243 | @Override | 247 | @Override |
| 244 | - public Long getCombinationRecordCount(@Nullable Integer status, @Nullable Boolean virtualGroup) { | ||
| 245 | - return recordMapper.selectCountByHeadAndStatusAndVirtualGroup(status, virtualGroup); | 248 | + public Long getCombinationRecordCount(@Nullable Integer status, @Nullable Boolean virtualGroup, @Nullable Long headId) { |
| 249 | + return combinationRecordMapper.selectCountByHeadAndStatusAndVirtualGroup(status, virtualGroup, headId); | ||
| 246 | } | 250 | } |
| 247 | 251 | ||
| 248 | @Override | 252 | @Override |
| 249 | public List<CombinationRecordDO> getLatestCombinationRecordList(int count) { | 253 | public List<CombinationRecordDO> getLatestCombinationRecordList(int count) { |
| 250 | - return recordMapper.selectLatestList(count); | 254 | + return combinationRecordMapper.selectLatestList(count); |
| 251 | } | 255 | } |
| 252 | 256 | ||
| 253 | @Override | 257 | @Override |
| 254 | public List<CombinationRecordDO> getHeadCombinationRecordList(Long activityId, Integer status, Integer count) { | 258 | public List<CombinationRecordDO> getHeadCombinationRecordList(Long activityId, Integer status, Integer count) { |
| 255 | - return recordMapper.selectListByActivityIdAndStatusAndHeadId(activityId, status, | 259 | + return combinationRecordMapper.selectListByActivityIdAndStatusAndHeadId(activityId, status, |
| 256 | CombinationRecordDO.HEAD_ID_GROUP, count); | 260 | CombinationRecordDO.HEAD_ID_GROUP, count); |
| 257 | } | 261 | } |
| 258 | 262 | ||
| 259 | @Override | 263 | @Override |
| 260 | public CombinationRecordDO getCombinationRecordById(Long id) { | 264 | public CombinationRecordDO getCombinationRecordById(Long id) { |
| 261 | - return recordMapper.selectById(id); | 265 | + return combinationRecordMapper.selectById(id); |
| 262 | } | 266 | } |
| 263 | 267 | ||
| 264 | @Override | 268 | @Override |
| 265 | public List<CombinationRecordDO> getCombinationRecordListByHeadId(Long headId) { | 269 | public List<CombinationRecordDO> getCombinationRecordListByHeadId(Long headId) { |
| 266 | - return recordMapper.selectList(CombinationRecordDO::getHeadId, headId); | 270 | + return combinationRecordMapper.selectList(CombinationRecordDO::getHeadId, headId); |
| 267 | } | 271 | } |
| 268 | 272 | ||
| 269 | @Override | 273 | @Override |
| 270 | public PageResult<CombinationRecordDO> getCombinationRecordPage(CombinationRecordReqPageVO pageVO) { | 274 | public PageResult<CombinationRecordDO> getCombinationRecordPage(CombinationRecordReqPageVO pageVO) { |
| 271 | - return recordMapper.selectPage(pageVO); | 275 | + return combinationRecordMapper.selectPage(pageVO); |
| 276 | + } | ||
| 277 | + | ||
| 278 | + @Override | ||
| 279 | + public PageResult<CombinationRecordDO> getCombinationRecordPage2(CombinationRecordReqPage2VO pageVO) { | ||
| 280 | + return combinationRecordMapper.selectPage(pageVO); | ||
| 272 | } | 281 | } |
| 273 | 282 | ||
| 274 | @Override | 283 | @Override |
| 275 | public Map<Long, Integer> getCombinationRecordCountMapByActivity(Collection<Long> activityIds, | 284 | public Map<Long, Integer> getCombinationRecordCountMapByActivity(Collection<Long> activityIds, |
| 276 | @Nullable Integer status, @Nullable Long headId) { | 285 | @Nullable Integer status, @Nullable Long headId) { |
| 277 | - return recordMapper.selectCombinationRecordCountMapByActivityIdAndStatusAndHeadId(activityIds, status, headId); | 286 | + return combinationRecordMapper.selectCombinationRecordCountMapByActivityIdAndStatusAndHeadId(activityIds, status, headId); |
| 278 | } | 287 | } |
| 279 | 288 | ||
| 280 | @Override | 289 | @Override |
| 281 | public CombinationRecordDO getCombinationRecordByIdAndUser(Long userId, Long id) { | 290 | public CombinationRecordDO getCombinationRecordByIdAndUser(Long userId, Long id) { |
| 282 | - return recordMapper.selectOne(CombinationRecordDO::getUserId, userId, CombinationRecordDO::getId, id); | 291 | + return combinationRecordMapper.selectOne(CombinationRecordDO::getUserId, userId, CombinationRecordDO::getId, id); |
| 283 | } | 292 | } |
| 284 | 293 | ||
| 285 | @Override | 294 | @Override |
| 286 | @Transactional(rollbackFor = Exception.class) | 295 | @Transactional(rollbackFor = Exception.class) |
| 287 | public void cancelCombinationRecord(Long userId, Long id, Long headId) { | 296 | public void cancelCombinationRecord(Long userId, Long id, Long headId) { |
| 288 | // 删除记录 | 297 | // 删除记录 |
| 289 | - recordMapper.deleteById(id); | 298 | + combinationRecordMapper.deleteById(id); |
| 290 | 299 | ||
| 291 | // 需要更新的记录 | 300 | // 需要更新的记录 |
| 292 | List<CombinationRecordDO> updateRecords = new ArrayList<>(); | 301 | List<CombinationRecordDO> updateRecords = new ArrayList<>(); |
| @@ -313,7 +322,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -313,7 +322,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 313 | }); | 322 | }); |
| 314 | } else { // 情况二:团员 | 323 | } else { // 情况二:团员 |
| 315 | // 团长 | 324 | // 团长 |
| 316 | - CombinationRecordDO recordHead = recordMapper.selectById(headId); | 325 | + CombinationRecordDO recordHead = combinationRecordMapper.selectById(headId); |
| 317 | // 团员 | 326 | // 团员 |
| 318 | List<CombinationRecordDO> records = getCombinationRecordListByHeadId(headId); | 327 | List<CombinationRecordDO> records = getCombinationRecordListByHeadId(headId); |
| 319 | if (CollUtil.isEmpty(records)) { | 328 | if (CollUtil.isEmpty(records)) { |
| @@ -329,7 +338,114 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -329,7 +338,114 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 329 | } | 338 | } |
| 330 | 339 | ||
| 331 | // 更新拼团记录 | 340 | // 更新拼团记录 |
| 332 | - recordMapper.updateBatch(updateRecords); | 341 | + combinationRecordMapper.updateBatch(updateRecords); |
| 342 | + } | ||
| 343 | + | ||
| 344 | + @Override | ||
| 345 | + public KeyValue<Integer, Integer> expireCombinationRecord() { | ||
| 346 | + // TODO @puhui999:数字一般是 1. 2. 这种格式哈 | ||
| 347 | + // 1。获取所有正在进行中的过期的父拼团 | ||
| 348 | + List<CombinationRecordDO> headExpireRecords = combinationRecordMapper.selectListByHeadIdAndStatusAndExpireTimeLt( | ||
| 349 | + CombinationRecordDO.HEAD_ID_GROUP, CombinationRecordStatusEnum.IN_PROGRESS.getStatus(), LocalDateTime.now()); | ||
| 350 | + if (CollUtil.isEmpty(headExpireRecords)) { | ||
| 351 | + return new KeyValue<>(0, 0); | ||
| 352 | + } | ||
| 353 | + | ||
| 354 | + // 2. 获取拼团活动 | ||
| 355 | + // TODO @puhui999:在自己模块里,变量可以简略点;例如说 activityList | ||
| 356 | + List<CombinationActivityDO> combinationActivities = combinationActivityService.getCombinationActivityListByIds( | ||
| 357 | + convertSet(headExpireRecords, CombinationRecordDO::getActivityId)); | ||
| 358 | + Map<Long, CombinationActivityDO> activityMap = convertMap(combinationActivities, CombinationActivityDO::getId); | ||
| 359 | + | ||
| 360 | + // TODO @puhui999:job 一般不建议异步跑;因为可能下次跑,结果上次还没跑完; | ||
| 361 | + // TODO 这里,我们可以每个 record 处理下;然后按照是否需要虚拟拼团,各搞一个方法逻辑 + 事务;这样,保证 job 里面尽量不要大事务,而是 n 个独立小事务的处理。 | ||
| 362 | + // 3. 校验是否虚拟成团 | ||
| 363 | + List<CombinationRecordDO> virtualGroupHeadRecords = new ArrayList<>(); // 虚拟成团 | ||
| 364 | + for (Iterator<CombinationRecordDO> iterator = headExpireRecords.iterator(); iterator.hasNext(); ) { | ||
| 365 | + CombinationRecordDO record = iterator.next(); | ||
| 366 | + // 3.1 不匹配,则直接跳过 | ||
| 367 | + CombinationActivityDO activity = activityMap.get(record.getActivityId()); | ||
| 368 | + if (activity == null || !activity.getVirtualGroup()) { // 取不到活动的或者不是虚拟拼团的 | ||
| 369 | + continue; | ||
| 370 | + } | ||
| 371 | + // 3.2 匹配,则移除,添加到虚拟成团中,并结束寻找 | ||
| 372 | + virtualGroupHeadRecords.add(record); | ||
| 373 | + iterator.remove(); | ||
| 374 | + break; | ||
| 375 | + } | ||
| 376 | + | ||
| 377 | + // 4.处理过期的拼团 | ||
| 378 | + getSelf().handleExpireRecord(headExpireRecords); | ||
| 379 | + // 5.虚拟成团 | ||
| 380 | + getSelf().handleVirtualGroupRecord(virtualGroupHeadRecords); | ||
| 381 | + return new KeyValue<>(headExpireRecords.size(), virtualGroupHeadRecords.size()); | ||
| 382 | + } | ||
| 383 | + | ||
| 384 | + @Async | ||
| 385 | + protected void handleExpireRecord(List<CombinationRecordDO> headExpireRecords) { | ||
| 386 | + if (CollUtil.isEmpty(headExpireRecords)) { | ||
| 387 | + return; | ||
| 388 | + } | ||
| 389 | + | ||
| 390 | + // 1.更新拼团记录 | ||
| 391 | + List<CombinationRecordDO> headsAndRecords = updateBatchCombinationRecords(headExpireRecords, | ||
| 392 | + CombinationRecordStatusEnum.FAILED); | ||
| 393 | + if (headsAndRecords == null) { | ||
| 394 | + return; | ||
| 395 | + } | ||
| 396 | + | ||
| 397 | + // 2.订单取消 TODO 以现在的取消回滚逻辑好像只能循环了 | ||
| 398 | + headsAndRecords.forEach(item -> { | ||
| 399 | + tradeOrderApi.cancelPaidOrder(item.getUserId(), item.getOrderId()); | ||
| 400 | + }); | ||
| 401 | + } | ||
| 402 | + | ||
| 403 | + @Async | ||
| 404 | + protected void handleVirtualGroupRecord(List<CombinationRecordDO> virtualGroupHeadRecords) { | ||
| 405 | + if (CollUtil.isEmpty(virtualGroupHeadRecords)) { | ||
| 406 | + return; | ||
| 407 | + } | ||
| 408 | + | ||
| 409 | + // 1. 团员补齐 | ||
| 410 | + combinationRecordMapper.insertBatch(CombinationActivityConvert.INSTANCE.convertVirtualGroupList(virtualGroupHeadRecords)); | ||
| 411 | + // 2. 更新拼团记录 | ||
| 412 | + updateBatchCombinationRecords(virtualGroupHeadRecords, CombinationRecordStatusEnum.SUCCESS); | ||
| 413 | + } | ||
| 414 | + | ||
| 415 | + private List<CombinationRecordDO> updateBatchCombinationRecords(List<CombinationRecordDO> headRecords, CombinationRecordStatusEnum status) { | ||
| 416 | + // 1. 查询团成员 | ||
| 417 | + List<CombinationRecordDO> records = combinationRecordMapper.selectListByHeadIds( | ||
| 418 | + convertSet(headRecords, CombinationRecordDO::getId)); | ||
| 419 | + if (CollUtil.isEmpty(records)) { | ||
| 420 | + return null; | ||
| 421 | + } | ||
| 422 | + Map<Long, List<CombinationRecordDO>> recordsMap = convertMultiMap(records, CombinationRecordDO::getHeadId); | ||
| 423 | + headRecords.forEach(item -> { | ||
| 424 | + recordsMap.get(item.getId()).add(item); // 把团长加进团里 | ||
| 425 | + }); | ||
| 426 | + // 2.批量更新拼团记录 status 和 失败/成团时间 | ||
| 427 | + List<CombinationRecordDO> headsAndRecords = mergeValuesFromMap(recordsMap); | ||
| 428 | + List<CombinationRecordDO> updateRecords = new ArrayList<>(headsAndRecords.size()); | ||
| 429 | + LocalDateTime now = LocalDateTime.now(); | ||
| 430 | + headsAndRecords.forEach(item -> { | ||
| 431 | + CombinationRecordDO record = new CombinationRecordDO().setId(item.getId()) | ||
| 432 | + .setStatus(status.getStatus()).setEndTime(now); | ||
| 433 | + if (CombinationRecordStatusEnum.isSuccess(status.getStatus())) { // 虚拟成团完事更改状态成功后还需要把参与人数修改为成团需要人数 | ||
| 434 | + record.setUserCount(record.getUserSize()); | ||
| 435 | + } | ||
| 436 | + updateRecords.add(record); | ||
| 437 | + }); | ||
| 438 | + combinationRecordMapper.updateBatch(updateRecords); | ||
| 439 | + return headsAndRecords; | ||
| 440 | + } | ||
| 441 | + | ||
| 442 | + /** | ||
| 443 | + * 获得自身的代理对象,解决 AOP 生效问题 | ||
| 444 | + * | ||
| 445 | + * @return 自己 | ||
| 446 | + */ | ||
| 447 | + private CombinationRecordServiceImpl getSelf() { | ||
| 448 | + return SpringUtil.getBean(getClass()); | ||
| 333 | } | 449 | } |
| 334 | 450 | ||
| 335 | } | 451 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java
| @@ -36,13 +36,22 @@ public interface SeckillActivityService { | @@ -36,13 +36,22 @@ public interface SeckillActivityService { | ||
| 36 | void updateSeckillActivity(@Valid SeckillActivityUpdateReqVO updateReqVO); | 36 | void updateSeckillActivity(@Valid SeckillActivityUpdateReqVO updateReqVO); |
| 37 | 37 | ||
| 38 | /** | 38 | /** |
| 39 | - * 更新秒杀库存 | 39 | + * 更新秒杀库存(减少) |
| 40 | * | 40 | * |
| 41 | * @param id 活动编号 | 41 | * @param id 活动编号 |
| 42 | * @param skuId sku 编号 | 42 | * @param skuId sku 编号 |
| 43 | - * @param count 数量 | 43 | + * @param count 数量(正数) |
| 44 | */ | 44 | */ |
| 45 | - void updateSeckillStock(Long id, Long skuId, Integer count); | 45 | + void updateSeckillStockDecr(Long id, Long skuId, Integer count); |
| 46 | + | ||
| 47 | + /** | ||
| 48 | + * 更新秒杀库存(增加) | ||
| 49 | + * | ||
| 50 | + * @param id 活动编号 | ||
| 51 | + * @param skuId sku 编号 | ||
| 52 | + * @param count 数量(正数) | ||
| 53 | + */ | ||
| 54 | + void updateSeckillStockIncr(Long id, Long skuId, Integer count); | ||
| 46 | 55 | ||
| 47 | /** | 56 | /** |
| 48 | * 关闭秒杀活动 | 57 | * 关闭秒杀活动 |
| @@ -113,8 +122,8 @@ public interface SeckillActivityService { | @@ -113,8 +122,8 @@ public interface SeckillActivityService { | ||
| 113 | * 如果校验失败,则抛出业务异常 | 122 | * 如果校验失败,则抛出业务异常 |
| 114 | * | 123 | * |
| 115 | * @param activityId 活动编号 | 124 | * @param activityId 活动编号 |
| 116 | - * @param skuId SKU 编号 | ||
| 117 | - * @param count 数量 | 125 | + * @param skuId SKU 编号 |
| 126 | + * @param count 数量 | ||
| 118 | * @return 秒杀信息 | 127 | * @return 秒杀信息 |
| 119 | */ | 128 | */ |
| 120 | SeckillValidateJoinRespDTO validateJoinSeckill(Long activityId, Long skuId, Integer count); | 129 | SeckillValidateJoinRespDTO validateJoinSeckill(Long activityId, Long skuId, Integer count); |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java
| 1 | package cn.iocoder.yudao.module.promotion.service.seckill; | 1 | package cn.iocoder.yudao.module.promotion.service.seckill; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 3 | import cn.hutool.core.collection.CollectionUtil; | 4 | import cn.hutool.core.collection.CollectionUtil; |
| 5 | +import cn.hutool.core.map.MapUtil; | ||
| 4 | import cn.hutool.core.util.ObjectUtil; | 6 | import cn.hutool.core.util.ObjectUtil; |
| 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 7 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| @@ -27,6 +29,7 @@ import org.springframework.validation.annotation.Validated; | @@ -27,6 +29,7 @@ import org.springframework.validation.annotation.Validated; | ||
| 27 | 29 | ||
| 28 | import javax.annotation.Resource; | 30 | import javax.annotation.Resource; |
| 29 | import java.util.Collection; | 31 | import java.util.Collection; |
| 32 | +import java.util.Collections; | ||
| 30 | import java.util.List; | 33 | import java.util.List; |
| 31 | import java.util.Map; | 34 | import java.util.Map; |
| 32 | 35 | ||
| @@ -154,7 +157,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | @@ -154,7 +157,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | ||
| 154 | 157 | ||
| 155 | @Override | 158 | @Override |
| 156 | @Transactional(rollbackFor = Exception.class) | 159 | @Transactional(rollbackFor = Exception.class) |
| 157 | - public void updateSeckillStock(Long id, Long skuId, Integer count) { | 160 | + public void updateSeckillStockDecr(Long id, Long skuId, Integer count) { |
| 158 | // 1.1 校验活动库存是否充足 | 161 | // 1.1 校验活动库存是否充足 |
| 159 | SeckillActivityDO seckillActivity = validateSeckillActivityExists(id); | 162 | SeckillActivityDO seckillActivity = validateSeckillActivityExists(id); |
| 160 | if (count > seckillActivity.getTotalStock()) { | 163 | if (count > seckillActivity.getTotalStock()) { |
| @@ -167,18 +170,28 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | @@ -167,18 +170,28 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | ||
| 167 | } | 170 | } |
| 168 | 171 | ||
| 169 | // 2.1 更新活动商品库存 | 172 | // 2.1 更新活动商品库存 |
| 170 | - int updateCount = seckillProductMapper.updateStock(product.getId(), count); | 173 | + int updateCount = seckillProductMapper.updateStockDecr(product.getId(), count); |
| 171 | if (updateCount == 0) { | 174 | if (updateCount == 0) { |
| 172 | throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); | 175 | throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); |
| 173 | } | 176 | } |
| 174 | 177 | ||
| 175 | // 2.2 更新活动库存 | 178 | // 2.2 更新活动库存 |
| 176 | - updateCount = seckillActivityMapper.updateStock(seckillActivity.getId(), count); | 179 | + updateCount = seckillActivityMapper.updateStockDecr(seckillActivity.getId(), count); |
| 177 | if (updateCount == 0) { | 180 | if (updateCount == 0) { |
| 178 | throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); | 181 | throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); |
| 179 | } | 182 | } |
| 180 | } | 183 | } |
| 181 | 184 | ||
| 185 | + @Override | ||
| 186 | + @Transactional(rollbackFor = Exception.class) | ||
| 187 | + public void updateSeckillStockIncr(Long id, Long skuId, Integer count) { | ||
| 188 | + SeckillProductDO product = seckillProductMapper.selectByActivityIdAndSkuId(id, skuId); | ||
| 189 | + // 更新活动商品库存 | ||
| 190 | + seckillProductMapper.updateStockIncr(product.getId(), count); | ||
| 191 | + // 更新活动库存 | ||
| 192 | + seckillActivityMapper.updateStockIncr(id, count); | ||
| 193 | + } | ||
| 194 | + | ||
| 182 | /** | 195 | /** |
| 183 | * 更新秒杀商品 | 196 | * 更新秒杀商品 |
| 184 | * | 197 | * |
| @@ -312,7 +325,13 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | @@ -312,7 +325,13 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | ||
| 312 | 325 | ||
| 313 | @Override | 326 | @Override |
| 314 | public List<SeckillActivityDO> getSeckillActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { | 327 | public List<SeckillActivityDO> getSeckillActivityBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { |
| 315 | - return seckillActivityMapper.selectListBySpuIds(spuIds, status); | 328 | + // 1.查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 |
| 329 | + List<Map<String, Object>> spuIdAndActivityIdMaps = seckillActivityMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status); | ||
| 330 | + if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) { | ||
| 331 | + return Collections.emptyList(); | ||
| 332 | + } | ||
| 333 | + // 2.查询活动详情 | ||
| 334 | + return seckillActivityMapper.selectListByIds(convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId"))); | ||
| 316 | } | 335 | } |
| 317 | 336 | ||
| 318 | } | 337 | } |
yudao-module-mall/yudao-module-statistics-biz/pom.xml
| @@ -59,6 +59,11 @@ | @@ -59,6 +59,11 @@ | ||
| 59 | <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId> | 59 | <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId> |
| 60 | </dependency> | 60 | </dependency> |
| 61 | 61 | ||
| 62 | + <dependency> | ||
| 63 | + <groupId>cn.iocoder.boot</groupId> | ||
| 64 | + <artifactId>yudao-spring-boot-starter-biz-ip</artifactId> | ||
| 65 | + </dependency> | ||
| 66 | + | ||
| 62 | <!-- Web 相关 --> | 67 | <!-- Web 相关 --> |
| 63 | <dependency> | 68 | <dependency> |
| 64 | <groupId>cn.iocoder.boot</groupId> | 69 | <groupId>cn.iocoder.boot</groupId> |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/MemberStatisticsController.java
| 1 | package cn.iocoder.yudao.module.statistics.controller.admin.member; | 1 | package cn.iocoder.yudao.module.statistics.controller.admin.member; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.util.ArrayUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.common.enums.TerminalEnum; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | -import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAreaStatisticsRespVO; | ||
| 5 | -import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSexStatisticsRespVO; | ||
| 6 | -import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSummaryRespVO; | ||
| 7 | -import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberTerminalStatisticsRespVO; | ||
| 8 | -import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO; | 6 | +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.*; |
| 7 | +import cn.iocoder.yudao.module.statistics.service.member.MemberStatisticsService; | ||
| 9 | import io.swagger.v3.oas.annotations.Operation; | 8 | import io.swagger.v3.oas.annotations.Operation; |
| 10 | import io.swagger.v3.oas.annotations.tags.Tag; | 9 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 11 | import lombok.extern.slf4j.Slf4j; | 10 | import lombok.extern.slf4j.Slf4j; |
| 11 | +import org.springframework.security.access.prepost.PreAuthorize; | ||
| 12 | import org.springframework.validation.annotation.Validated; | 12 | import org.springframework.validation.annotation.Validated; |
| 13 | import org.springframework.web.bind.annotation.GetMapping; | 13 | import org.springframework.web.bind.annotation.GetMapping; |
| 14 | import org.springframework.web.bind.annotation.RequestMapping; | 14 | import org.springframework.web.bind.annotation.RequestMapping; |
| 15 | import org.springframework.web.bind.annotation.RestController; | 15 | import org.springframework.web.bind.annotation.RestController; |
| 16 | 16 | ||
| 17 | +import javax.annotation.Resource; | ||
| 17 | import java.util.List; | 18 | import java.util.List; |
| 18 | 19 | ||
| 20 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 21 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 22 | + | ||
| 19 | @Tag(name = "管理后台 - 会员统计") | 23 | @Tag(name = "管理后台 - 会员统计") |
| 20 | @RestController | 24 | @RestController |
| 21 | @RequestMapping("/statistics/member") | 25 | @RequestMapping("/statistics/member") |
| @@ -23,36 +27,47 @@ import java.util.List; | @@ -23,36 +27,47 @@ import java.util.List; | ||
| 23 | @Slf4j | 27 | @Slf4j |
| 24 | public class MemberStatisticsController { | 28 | public class MemberStatisticsController { |
| 25 | 29 | ||
| 26 | - // TODO @疯狂:一个类似 getTradeTrendSummaryComparison 的接口 | ||
| 27 | - // TODO @疯狂:一个类似 getTradeStatisticsList 的接口 | 30 | + @Resource |
| 31 | + private MemberStatisticsService memberStatisticsService; | ||
| 28 | 32 | ||
| 29 | @GetMapping("/summary") | 33 | @GetMapping("/summary") |
| 30 | @Operation(summary = "获得会员统计") | 34 | @Operation(summary = "获得会员统计") |
| 31 | - public CommonResult<TradeStatisticsComparisonRespVO<MemberSummaryRespVO>> getMemberSummary() { | ||
| 32 | - // TODO 疯狂:目前先直接计算; | ||
| 33 | - return null; | 35 | + @PreAuthorize("@ss.hasPermission('statistics:member:query')") |
| 36 | + public CommonResult<MemberSummaryRespVO> getMemberSummary() { | ||
| 37 | + return success(memberStatisticsService.getMemberSummary()); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + @GetMapping("/analyse") | ||
| 41 | + @Operation(summary = "获得会员分析数据") | ||
| 42 | + @PreAuthorize("@ss.hasPermission('statistics:member:query')") | ||
| 43 | + public CommonResult<MemberAnalyseRespVO> getMemberAnalyse(MemberAnalyseReqVO reqVO) { | ||
| 44 | + return success(memberStatisticsService.getMemberAnalyse( | ||
| 45 | + ArrayUtil.get(reqVO.getTimes(), 0), ArrayUtil.get(reqVO.getTimes(), 1))); | ||
| 34 | } | 46 | } |
| 35 | 47 | ||
| 36 | @GetMapping("/get-area-statistics-list") | 48 | @GetMapping("/get-area-statistics-list") |
| 37 | @Operation(summary = "按照省份,获得会员统计列表") | 49 | @Operation(summary = "按照省份,获得会员统计列表") |
| 50 | + @PreAuthorize("@ss.hasPermission('statistics:member:query')") | ||
| 38 | public CommonResult<List<MemberAreaStatisticsRespVO>> getMemberAreaStatisticsList() { | 51 | public CommonResult<List<MemberAreaStatisticsRespVO>> getMemberAreaStatisticsList() { |
| 39 | - // TODO 疯狂:目前先直接计算,进行统计;后续再考虑优化 | ||
| 40 | - return null; | 52 | + return success(memberStatisticsService.getMemberAreaStatisticsList()); |
| 41 | } | 53 | } |
| 42 | 54 | ||
| 43 | @GetMapping("/get-sex-statistics-list") | 55 | @GetMapping("/get-sex-statistics-list") |
| 44 | @Operation(summary = "按照性别,获得会员统计列表") | 56 | @Operation(summary = "按照性别,获得会员统计列表") |
| 57 | + @PreAuthorize("@ss.hasPermission('statistics:member:query')") | ||
| 45 | public CommonResult<List<MemberSexStatisticsRespVO>> getMemberSexStatisticsList() { | 58 | public CommonResult<List<MemberSexStatisticsRespVO>> getMemberSexStatisticsList() { |
| 46 | - // TODO 疯狂:目前先直接计算,进行统计;后续再考虑优化 | ||
| 47 | - return null; | 59 | + return success(memberStatisticsService.getMemberSexStatisticsList()); |
| 48 | } | 60 | } |
| 49 | 61 | ||
| 50 | @GetMapping("/get-terminal-statistics-list") | 62 | @GetMapping("/get-terminal-statistics-list") |
| 51 | @Operation(summary = "按照终端,获得会员统计列表") | 63 | @Operation(summary = "按照终端,获得会员统计列表") |
| 64 | + @PreAuthorize("@ss.hasPermission('statistics:member:query')") | ||
| 52 | public CommonResult<List<MemberTerminalStatisticsRespVO>> getMemberTerminalStatisticsList() { | 65 | public CommonResult<List<MemberTerminalStatisticsRespVO>> getMemberTerminalStatisticsList() { |
| 53 | - // TODO 疯狂:目前先直接计算,进行统计;后续再考虑优化 | ||
| 54 | // TODO 疯狂:这个可以晚点写,因为 user = = 上还没记录 terminal | 66 | // TODO 疯狂:这个可以晚点写,因为 user = = 上还没记录 terminal |
| 55 | - return null; | 67 | + List<MemberTerminalStatisticsRespVO> list = convertList(TerminalEnum.values(), |
| 68 | + t -> new MemberTerminalStatisticsRespVO() | ||
| 69 | + .setTerminal(t.getTerminal()).setUserCount(t.getTerminal() * 100)); | ||
| 70 | + return success(list); | ||
| 56 | } | 71 | } |
| 57 | 72 | ||
| 58 | } | 73 | } |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/package-info.java deleted
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAnalyseComparisonRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.controller.admin.member.vo; | ||
| 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 MemberAnalyseComparisonRespVO { | ||
| 9 | + | ||
| 10 | + @Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 11 | + private Integer userCount; | ||
| 12 | + | ||
| 13 | + @Schema(description = "活跃用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 14 | + private Integer activeUserCount; | ||
| 15 | + | ||
| 16 | + @Schema(description = "充值会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "221") | ||
| 17 | + private Integer rechargeUserCount; | ||
| 18 | + | ||
| 19 | +} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAnalyseReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.controller.admin.member.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 6 | + | ||
| 7 | +import java.time.LocalDateTime; | ||
| 8 | + | ||
| 9 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 10 | + | ||
| 11 | +@Schema(description = "管理后台 - 会员分析 Request VO") | ||
| 12 | +@Data | ||
| 13 | +public class MemberAnalyseReqVO { | ||
| 14 | + | ||
| 15 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 16 | + @Schema(description = "时间范围") | ||
| 17 | + private LocalDateTime[] times; | ||
| 18 | + | ||
| 19 | +} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberAnalyseRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.controller.admin.member.vo; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +@Schema(description = "管理后台 - 会员分析 Response VO") | ||
| 8 | +@Data | ||
| 9 | +public class MemberAnalyseRespVO { | ||
| 10 | + | ||
| 11 | + @Schema(description = "访客数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 12 | + private Integer visitorCount; | ||
| 13 | + | ||
| 14 | + @Schema(description = "下单用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 15 | + private Integer orderUserCount; | ||
| 16 | + | ||
| 17 | + @Schema(description = "成交用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 18 | + private Integer payUserCount; | ||
| 19 | + | ||
| 20 | + @Schema(description = "客单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 21 | + private Integer atv; | ||
| 22 | + | ||
| 23 | + @Schema(description = "对照数据", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 24 | + private TradeStatisticsComparisonRespVO<MemberAnalyseComparisonRespVO> comparison; | ||
| 25 | + | ||
| 26 | +} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberSexStatisticsRespVO.java
| @@ -13,11 +13,4 @@ public class MemberSexStatisticsRespVO { | @@ -13,11 +13,4 @@ public class MemberSexStatisticsRespVO { | ||
| 13 | @Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | 13 | @Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 14 | private Integer userCount; | 14 | private Integer userCount; |
| 15 | 15 | ||
| 16 | - @Schema(description = "订单创建数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 17 | - private Integer orderCreateCount; | ||
| 18 | - @Schema(description = "订单支付数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "512") | ||
| 19 | - private Integer orderPayCount; | ||
| 20 | - @Schema(description = "订单支付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "622") | ||
| 21 | - private Integer orderPayPrice; | ||
| 22 | - | ||
| 23 | } | 16 | } |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberSummaryRespVO.java
| @@ -15,6 +15,7 @@ public class MemberSummaryRespVO { | @@ -15,6 +15,7 @@ public class MemberSummaryRespVO { | ||
| 15 | 15 | ||
| 16 | @Schema(description = "充值金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | 16 | @Schema(description = "充值金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 17 | private Integer rechargePrice; | 17 | private Integer rechargePrice; |
| 18 | + | ||
| 18 | @Schema(description = "支出金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | 19 | @Schema(description = "支出金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 19 | private Integer expensePrice; | 20 | private Integer expensePrice; |
| 20 | 21 |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/member/vo/MemberTerminalStatisticsRespVO.java
| @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.statistics.controller.admin.member.vo; | @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.statistics.controller.admin.member.vo; | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | import lombok.Data; | 4 | import lombok.Data; |
| 5 | 5 | ||
| 6 | -@Schema(description = "管理后台 - 终端性别统计 Response VO") | 6 | +@Schema(description = "管理后台 - 会员终端统计 Response VO") |
| 7 | @Data | 7 | @Data |
| 8 | public class MemberTerminalStatisticsRespVO { | 8 | public class MemberTerminalStatisticsRespVO { |
| 9 | 9 | ||
| @@ -13,11 +13,4 @@ public class MemberTerminalStatisticsRespVO { | @@ -13,11 +13,4 @@ public class MemberTerminalStatisticsRespVO { | ||
| 13 | @Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | 13 | @Schema(description = "会员数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 14 | private Integer userCount; | 14 | private Integer userCount; |
| 15 | 15 | ||
| 16 | - @Schema(description = "订单创建数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 17 | - private Integer orderCreateCount; | ||
| 18 | - @Schema(description = "订单支付数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "512") | ||
| 19 | - private Integer orderPayCount; | ||
| 20 | - @Schema(description = "订单支付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "622") | ||
| 21 | - private Integer orderPayPrice; | ||
| 22 | - | ||
| 23 | } | 16 | } |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/convert/member/MemberStatisticsConvert.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.convert.member; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.map.MapUtil; | ||
| 4 | +import cn.hutool.core.util.ObjUtil; | ||
| 5 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 6 | +import cn.iocoder.yudao.framework.ip.core.Area; | ||
| 7 | +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAreaStatisticsRespVO; | ||
| 8 | +import org.mapstruct.Mapper; | ||
| 9 | +import org.mapstruct.factory.Mappers; | ||
| 10 | + | ||
| 11 | +import java.util.List; | ||
| 12 | +import java.util.Map; | ||
| 13 | +import java.util.Optional; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * 会员统计 Convert | ||
| 17 | + * | ||
| 18 | + * @author owen | ||
| 19 | + */ | ||
| 20 | +@Mapper | ||
| 21 | +public interface MemberStatisticsConvert { | ||
| 22 | + | ||
| 23 | + MemberStatisticsConvert INSTANCE = Mappers.getMapper(MemberStatisticsConvert.class); | ||
| 24 | + | ||
| 25 | + default List<MemberAreaStatisticsRespVO> convertList(List<Area> areaList, | ||
| 26 | + Map<Integer, Integer> userCountMap, | ||
| 27 | + Map<Integer, MemberAreaStatisticsRespVO> orderMap) { | ||
| 28 | + return CollectionUtils.convertList(areaList, area -> { | ||
| 29 | + MemberAreaStatisticsRespVO orderVo = Optional.ofNullable(orderMap.get(area.getId())).orElseGet(MemberAreaStatisticsRespVO::new); | ||
| 30 | + return new MemberAreaStatisticsRespVO() | ||
| 31 | + .setAreaId(area.getId()).setAreaName(area.getName()) | ||
| 32 | + .setUserCount(MapUtil.getInt(userCountMap, area.getId(), 0)) | ||
| 33 | + .setOrderCreateCount(ObjUtil.defaultIfNull(orderVo.getOrderCreateCount(), 0)) | ||
| 34 | + .setOrderPayCount(ObjUtil.defaultIfNull(orderVo.getOrderPayCount(), 0)) | ||
| 35 | + .setOrderPayPrice(ObjUtil.defaultIfNull(orderVo.getOrderPayPrice(), 0)); | ||
| 36 | + }); | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | +} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/convert/trade/TradeStatisticsConvert.java
| 1 | package cn.iocoder.yudao.module.statistics.convert.trade; | 1 | package cn.iocoder.yudao.module.statistics.convert.trade; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.pay.api.wallet.dto.WalletSummaryRespDTO; | 3 | +import cn.iocoder.yudao.module.statistics.service.trade.bo.WalletSummaryRespBO; |
| 4 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO; | 4 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO; |
| 5 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeSummaryRespVO; | 5 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeSummaryRespVO; |
| 6 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryExcelVO; | 6 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryExcelVO; |
| 7 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO; | 7 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO; |
| 8 | import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO; | 8 | import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO; |
| 9 | +import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeOrderSummaryRespBO; | ||
| 9 | import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO; | 10 | import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO; |
| 10 | -import cn.iocoder.yudao.module.trade.api.aftersale.dto.AfterSaleSummaryRespDTO; | ||
| 11 | -import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderSummaryRespDTO; | 11 | +import cn.iocoder.yudao.module.statistics.service.trade.bo.AfterSaleSummaryRespBO; |
| 12 | import org.mapstruct.Mapper; | 12 | import org.mapstruct.Mapper; |
| 13 | import org.mapstruct.factory.Mappers; | 13 | import org.mapstruct.factory.Mappers; |
| 14 | 14 | ||
| @@ -46,8 +46,8 @@ public interface TradeStatisticsConvert { | @@ -46,8 +46,8 @@ public interface TradeStatisticsConvert { | ||
| 46 | 46 | ||
| 47 | List<TradeTrendSummaryExcelVO> convertList02(List<TradeTrendSummaryRespVO> list); | 47 | List<TradeTrendSummaryExcelVO> convertList02(List<TradeTrendSummaryRespVO> list); |
| 48 | 48 | ||
| 49 | - TradeStatisticsDO convert(LocalDateTime time, TradeOrderSummaryRespDTO orderSummary, | ||
| 50 | - AfterSaleSummaryRespDTO afterSaleSummary, Integer brokerageSettlementPrice, | ||
| 51 | - WalletSummaryRespDTO walletSummary); | 49 | + TradeStatisticsDO convert(LocalDateTime time, TradeOrderSummaryRespBO orderSummary, |
| 50 | + AfterSaleSummaryRespBO afterSaleSummary, Integer brokerageSettlementPrice, | ||
| 51 | + WalletSummaryRespBO walletSummary); | ||
| 52 | 52 | ||
| 53 | } | 53 | } |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/infra/ApiAccessLogStatisticsMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.dal.mysql.infra; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 4 | +import org.apache.ibatis.annotations.Mapper; | ||
| 5 | +import org.apache.ibatis.annotations.Param; | ||
| 6 | + | ||
| 7 | +import java.time.LocalDateTime; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * API 访问日志的统计 Mapper | ||
| 11 | + * | ||
| 12 | + * @author owen | ||
| 13 | + */ | ||
| 14 | +@Mapper | ||
| 15 | +public interface ApiAccessLogStatisticsMapper extends BaseMapperX<Object> { | ||
| 16 | + | ||
| 17 | + Integer selectCountByIp(@Param("beginTime") LocalDateTime beginTime, | ||
| 18 | + @Param("endTime") LocalDateTime endTime); | ||
| 19 | + | ||
| 20 | + Integer selectCountByUserId(@Param("beginTime") LocalDateTime beginTime, | ||
| 21 | + @Param("endTime") LocalDateTime endTime); | ||
| 22 | + | ||
| 23 | +} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/member/MemberStatisticsMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.dal.mysql.member; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 4 | +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAreaStatisticsRespVO; | ||
| 5 | +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSexStatisticsRespVO; | ||
| 6 | +import org.apache.ibatis.annotations.Mapper; | ||
| 7 | +import org.apache.ibatis.annotations.Param; | ||
| 8 | + | ||
| 9 | +import java.time.LocalDateTime; | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 会员信息的统计 Mapper | ||
| 14 | + * | ||
| 15 | + * @author owen | ||
| 16 | + */ | ||
| 17 | +@Mapper | ||
| 18 | +public interface MemberStatisticsMapper extends BaseMapperX<Object> { | ||
| 19 | + | ||
| 20 | + List<MemberAreaStatisticsRespVO> selectSummaryListByAreaId(); | ||
| 21 | + | ||
| 22 | + List<MemberSexStatisticsRespVO> selectSummaryListBySex(); | ||
| 23 | + | ||
| 24 | + Integer selectUserCount(@Param("beginTime") LocalDateTime beginTime, | ||
| 25 | + @Param("endTime") LocalDateTime endTime); | ||
| 26 | + | ||
| 27 | +} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/pay/PayWalletStatisticsMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.dal.mysql.pay; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 4 | +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSummaryRespVO; | ||
| 5 | +import cn.iocoder.yudao.module.statistics.service.trade.bo.WalletSummaryRespBO; | ||
| 6 | +import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO; | ||
| 7 | +import org.apache.ibatis.annotations.Mapper; | ||
| 8 | +import org.apache.ibatis.annotations.Param; | ||
| 9 | + | ||
| 10 | +import java.time.LocalDateTime; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 支付钱包的统计 Mapper | ||
| 14 | + * | ||
| 15 | + * @author owen | ||
| 16 | + */ | ||
| 17 | +@Mapper | ||
| 18 | +public interface PayWalletStatisticsMapper extends BaseMapperX<TradeStatisticsDO> { | ||
| 19 | + | ||
| 20 | + WalletSummaryRespBO selectRechargeSummaryByPayTimeBetween(@Param("beginTime") LocalDateTime beginTime, | ||
| 21 | + @Param("endTime") LocalDateTime endTime, | ||
| 22 | + @Param("payStatus") Boolean payStatus); | ||
| 23 | + | ||
| 24 | + WalletSummaryRespBO selectRechargeSummaryByRefundTimeBetween(@Param("beginTime") LocalDateTime beginTime, | ||
| 25 | + @Param("endTime") LocalDateTime endTime, | ||
| 26 | + @Param("refundStatus") Integer refundStatus); | ||
| 27 | + | ||
| 28 | + Integer selectPriceSummaryByBizTypeAndCreateTimeBetween(@Param("beginTime") LocalDateTime beginTime, | ||
| 29 | + @Param("endTime") LocalDateTime endTime, | ||
| 30 | + @Param("bizType") Integer bizType); | ||
| 31 | + | ||
| 32 | + // TODO @疯狂:是不是搞个单独的 BO 呀; | ||
| 33 | + MemberSummaryRespVO selectRechargeSummaryGroupByWalletId(@Param("beginTime") LocalDateTime beginTime, | ||
| 34 | + @Param("endTime") LocalDateTime endTime, | ||
| 35 | + @Param("payStatus") Boolean payStatus); | ||
| 36 | + | ||
| 37 | +} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/AfterSaleStatisticsMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.dal.mysql.trade; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 4 | +import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO; | ||
| 5 | +import cn.iocoder.yudao.module.statistics.service.trade.bo.AfterSaleSummaryRespBO; | ||
| 6 | +import org.apache.ibatis.annotations.Mapper; | ||
| 7 | +import org.apache.ibatis.annotations.Param; | ||
| 8 | + | ||
| 9 | +import java.time.LocalDateTime; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 售后订单的统计 Mapper | ||
| 13 | + * | ||
| 14 | + * @author owen | ||
| 15 | + */ | ||
| 16 | +@Mapper | ||
| 17 | +public interface AfterSaleStatisticsMapper extends BaseMapperX<TradeStatisticsDO> { | ||
| 18 | + | ||
| 19 | + AfterSaleSummaryRespBO selectSummaryByRefundTimeBetween(@Param("beginTime") LocalDateTime beginTime, | ||
| 20 | + @Param("endTime") LocalDateTime endTime); | ||
| 21 | + | ||
| 22 | +} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/BrokerageStatisticsMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.dal.mysql.trade; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 4 | +import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO; | ||
| 5 | +import org.apache.ibatis.annotations.Mapper; | ||
| 6 | +import org.apache.ibatis.annotations.Param; | ||
| 7 | + | ||
| 8 | +import java.time.LocalDateTime; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 订单分销的统计 Mapper | ||
| 12 | + * | ||
| 13 | + * @author owen | ||
| 14 | + */ | ||
| 15 | +@Mapper | ||
| 16 | +public interface BrokerageStatisticsMapper extends BaseMapperX<TradeStatisticsDO> { | ||
| 17 | + | ||
| 18 | + Integer selectSummaryPriceByStatusAndUnfreezeTimeBetween(@Param("bizType") Integer bizType, | ||
| 19 | + @Param("status") Integer status, | ||
| 20 | + @Param("beginTime") LocalDateTime beginTime, | ||
| 21 | + @Param("endTime") LocalDateTime endTime); | ||
| 22 | + | ||
| 23 | +} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/TradeOrderStatisticsMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.dal.mysql.trade; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 4 | +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAreaStatisticsRespVO; | ||
| 5 | +import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO; | ||
| 6 | +import org.apache.ibatis.annotations.Mapper; | ||
| 7 | +import org.apache.ibatis.annotations.Param; | ||
| 8 | + | ||
| 9 | +import java.time.LocalDateTime; | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 交易订单的统计 Mapper | ||
| 14 | + * | ||
| 15 | + * @author owen | ||
| 16 | + */ | ||
| 17 | +@Mapper | ||
| 18 | +public interface TradeOrderStatisticsMapper extends BaseMapperX<TradeStatisticsDO> { | ||
| 19 | + | ||
| 20 | + List<MemberAreaStatisticsRespVO> selectSummaryListByAreaId(); | ||
| 21 | + | ||
| 22 | + Integer selectCountByCreateTimeBetween(@Param("beginTime") LocalDateTime beginTime, | ||
| 23 | + @Param("endTime") LocalDateTime endTime); | ||
| 24 | + | ||
| 25 | + Integer selectCountByPayTimeBetween(@Param("beginTime") LocalDateTime beginTime, | ||
| 26 | + @Param("endTime") LocalDateTime endTime); | ||
| 27 | + | ||
| 28 | + Integer selectSummaryPriceByPayTimeBetween(@Param("beginTime") LocalDateTime beginTime, | ||
| 29 | + @Param("endTime") LocalDateTime endTime); | ||
| 30 | + | ||
| 31 | + Integer selectUserCountByCreateTimeBetween(@Param("beginTime") LocalDateTime beginTime, | ||
| 32 | + @Param("endTime") LocalDateTime endTime); | ||
| 33 | + | ||
| 34 | + Integer selectUserCountByPayTimeBetween(@Param("beginTime") LocalDateTime beginTime, | ||
| 35 | + @Param("endTime") LocalDateTime endTime); | ||
| 36 | + | ||
| 37 | +} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/trade/TradeStatisticsMapper.java
| @@ -19,6 +19,7 @@ import java.util.List; | @@ -19,6 +19,7 @@ import java.util.List; | ||
| 19 | @Mapper | 19 | @Mapper |
| 20 | public interface TradeStatisticsMapper extends BaseMapperX<TradeStatisticsDO> { | 20 | public interface TradeStatisticsMapper extends BaseMapperX<TradeStatisticsDO> { |
| 21 | 21 | ||
| 22 | + // TODO @疯狂:这个要不要也挪到 xml 里,保持统一? | ||
| 22 | @Select("SELECT IFNULL(SUM(order_create_count), 0) AS count, IFNULL(SUM(order_pay_price), 0) AS summary " + | 23 | @Select("SELECT IFNULL(SUM(order_create_count), 0) AS count, IFNULL(SUM(order_pay_price), 0) AS summary " + |
| 23 | "FROM trade_statistics " + | 24 | "FROM trade_statistics " + |
| 24 | "WHERE time BETWEEN #{beginTime} AND #{endTime} AND deleted = FALSE") | 25 | "WHERE time BETWEEN #{beginTime} AND #{endTime} AND deleted = FALSE") |
| @@ -30,4 +31,8 @@ public interface TradeStatisticsMapper extends BaseMapperX<TradeStatisticsDO> { | @@ -30,4 +31,8 @@ public interface TradeStatisticsMapper extends BaseMapperX<TradeStatisticsDO> { | ||
| 30 | 31 | ||
| 31 | List<TradeTrendSummaryRespVO> selectListByTimeBetween(@Param("beginTime") LocalDateTime beginTime, | 32 | List<TradeTrendSummaryRespVO> selectListByTimeBetween(@Param("beginTime") LocalDateTime beginTime, |
| 32 | @Param("endTime") LocalDateTime endTime); | 33 | @Param("endTime") LocalDateTime endTime); |
| 34 | + | ||
| 35 | + Integer selectExpensePriceByTimeBetween(@Param("beginTime") LocalDateTime beginTime, | ||
| 36 | + @Param("endTime") LocalDateTime endTime); | ||
| 37 | + | ||
| 33 | } | 38 | } |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/infra/ApiAccessLogStatisticsService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.service.infra; | ||
| 2 | + | ||
| 3 | +import java.time.LocalDateTime; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * API 访问日志的统计 Service 接口 | ||
| 7 | + * | ||
| 8 | + * @author owen | ||
| 9 | + */ | ||
| 10 | +public interface ApiAccessLogStatisticsService { | ||
| 11 | + | ||
| 12 | + /** | ||
| 13 | + * 获取活跃用户数量 | ||
| 14 | + * | ||
| 15 | + * @param beginTime 起始时间 | ||
| 16 | + * @param endTime 截止时间 | ||
| 17 | + * @return 活跃用户数量 | ||
| 18 | + */ | ||
| 19 | + Integer getActiveUserCount(LocalDateTime beginTime, LocalDateTime endTime); | ||
| 20 | + | ||
| 21 | + /** | ||
| 22 | + * 获取访问用户数量 | ||
| 23 | + * | ||
| 24 | + * @param beginTime 起始时间 | ||
| 25 | + * @param endTime 截止时间 | ||
| 26 | + * @return 访问用户数量 | ||
| 27 | + */ | ||
| 28 | + Integer getVisitorUserCount(LocalDateTime beginTime, LocalDateTime endTime); | ||
| 29 | + | ||
| 30 | +} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/infra/ApiAccessLogStatisticsServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.service.infra; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.statistics.dal.mysql.infra.ApiAccessLogStatisticsMapper; | ||
| 4 | +import org.springframework.stereotype.Service; | ||
| 5 | +import org.springframework.validation.annotation.Validated; | ||
| 6 | + | ||
| 7 | +import javax.annotation.Resource; | ||
| 8 | +import java.time.LocalDateTime; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * API 访问日志的统计 Service 实现类 | ||
| 12 | + * | ||
| 13 | + * @author owen | ||
| 14 | + */ | ||
| 15 | +@Service | ||
| 16 | +@Validated | ||
| 17 | +public class ApiAccessLogStatisticsServiceImpl implements ApiAccessLogStatisticsService { | ||
| 18 | + | ||
| 19 | + @Resource | ||
| 20 | + private ApiAccessLogStatisticsMapper apiAccessLogStatisticsMapper; | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + public Integer getActiveUserCount(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 24 | + return apiAccessLogStatisticsMapper.selectCountByUserId(beginTime, endTime); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + public Integer getVisitorUserCount(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 29 | + return apiAccessLogStatisticsMapper.selectCountByIp(beginTime, endTime); | ||
| 30 | + } | ||
| 31 | +} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.service.member; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAnalyseRespVO; | ||
| 4 | +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAreaStatisticsRespVO; | ||
| 5 | +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSexStatisticsRespVO; | ||
| 6 | +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSummaryRespVO; | ||
| 7 | + | ||
| 8 | +import java.time.LocalDateTime; | ||
| 9 | +import java.util.List; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 会员信息的统计 Service 接口 | ||
| 13 | + * | ||
| 14 | + * @author owen | ||
| 15 | + */ | ||
| 16 | +public interface MemberStatisticsService { | ||
| 17 | + | ||
| 18 | + /** | ||
| 19 | + * 获取会员统计 | ||
| 20 | + * | ||
| 21 | + * @return 会员统计 | ||
| 22 | + */ | ||
| 23 | + MemberSummaryRespVO getMemberSummary(); | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 按照省份,获得会员统计列表 | ||
| 27 | + * | ||
| 28 | + * @return 会员统计列表 | ||
| 29 | + */ | ||
| 30 | + List<MemberAreaStatisticsRespVO> getMemberAreaStatisticsList(); | ||
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * 按照性别,获得会员统计列表 | ||
| 34 | + * | ||
| 35 | + * @return 会员统计列表 | ||
| 36 | + */ | ||
| 37 | + List<MemberSexStatisticsRespVO> getMemberSexStatisticsList(); | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * 获取用户分析数据 | ||
| 41 | + * | ||
| 42 | + * @param beginTime 起始时间 | ||
| 43 | + * @param endTime 截止时间 | ||
| 44 | + * @return 用户分析数据 | ||
| 45 | + */ | ||
| 46 | + MemberAnalyseRespVO getMemberAnalyse(LocalDateTime beginTime, LocalDateTime endTime); | ||
| 47 | + | ||
| 48 | +} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.service.member; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.NumberUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; | ||
| 5 | +import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; | ||
| 6 | +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.*; | ||
| 7 | +import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO; | ||
| 8 | +import cn.iocoder.yudao.module.statistics.convert.member.MemberStatisticsConvert; | ||
| 9 | +import cn.iocoder.yudao.module.statistics.dal.mysql.member.MemberStatisticsMapper; | ||
| 10 | +import cn.iocoder.yudao.module.statistics.service.infra.ApiAccessLogStatisticsService; | ||
| 11 | +import cn.iocoder.yudao.module.statistics.service.pay.PayWalletStatisticsService; | ||
| 12 | +import cn.iocoder.yudao.module.statistics.service.trade.TradeOrderStatisticsService; | ||
| 13 | +import cn.iocoder.yudao.module.statistics.service.trade.TradeStatisticsService; | ||
| 14 | +import org.springframework.stereotype.Service; | ||
| 15 | +import org.springframework.validation.annotation.Validated; | ||
| 16 | + | ||
| 17 | +import javax.annotation.Resource; | ||
| 18 | +import java.time.Duration; | ||
| 19 | +import java.time.LocalDateTime; | ||
| 20 | +import java.util.List; | ||
| 21 | +import java.util.Map; | ||
| 22 | +import java.util.Optional; | ||
| 23 | + | ||
| 24 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||
| 25 | + | ||
| 26 | +/** | ||
| 27 | + * 会员信息的统计 Service 实现类 | ||
| 28 | + * | ||
| 29 | + * @author owen | ||
| 30 | + */ | ||
| 31 | +@Service | ||
| 32 | +@Validated | ||
| 33 | +public class MemberStatisticsServiceImpl implements MemberStatisticsService { | ||
| 34 | + | ||
| 35 | + @Resource | ||
| 36 | + private MemberStatisticsMapper memberStatisticsMapper; | ||
| 37 | + | ||
| 38 | + @Resource | ||
| 39 | + private PayWalletStatisticsService payWalletStatisticsService; | ||
| 40 | + @Resource | ||
| 41 | + private TradeStatisticsService tradeStatisticsService; | ||
| 42 | + @Resource | ||
| 43 | + private TradeOrderStatisticsService tradeOrderStatisticsService; | ||
| 44 | + @Resource | ||
| 45 | + private ApiAccessLogStatisticsService apiAccessLogStatisticsService; | ||
| 46 | + | ||
| 47 | + @Override | ||
| 48 | + public MemberSummaryRespVO getMemberSummary() { | ||
| 49 | + MemberSummaryRespVO vo = payWalletStatisticsService.getUserRechargeSummary(null, null); | ||
| 50 | + Integer expensePrice = tradeStatisticsService.getExpensePrice(null, null); | ||
| 51 | + Integer userCount = memberStatisticsMapper.selectUserCount(null, null); | ||
| 52 | + // 拼接数据 | ||
| 53 | + if (vo == null) { | ||
| 54 | + vo = new MemberSummaryRespVO().setRechargeUserCount(0).setRechargePrice(0); | ||
| 55 | + } | ||
| 56 | + return vo.setUserCount(userCount).setExpensePrice(expensePrice); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + @Override | ||
| 60 | + public List<MemberAreaStatisticsRespVO> getMemberAreaStatisticsList() { | ||
| 61 | + // 统计用户 | ||
| 62 | + Map<Integer, Integer> userCountMap = convertMap(memberStatisticsMapper.selectSummaryListByAreaId(), | ||
| 63 | + vo -> AreaUtils.getParentIdByType(vo.getAreaId(), AreaTypeEnum.PROVINCE), | ||
| 64 | + MemberAreaStatisticsRespVO::getUserCount, Integer::sum); | ||
| 65 | + // 统计订单 | ||
| 66 | + Map<Integer, MemberAreaStatisticsRespVO> orderMap = convertMap(tradeOrderStatisticsService.getSummaryListByAreaId(), | ||
| 67 | + vo -> AreaUtils.getParentIdByType(vo.getAreaId(), AreaTypeEnum.PROVINCE), | ||
| 68 | + vo -> vo, | ||
| 69 | + (a, b) -> new MemberAreaStatisticsRespVO() | ||
| 70 | + .setOrderCreateCount(a.getOrderCreateCount() + b.getOrderCreateCount()) | ||
| 71 | + .setOrderPayCount(a.getOrderPayCount() + b.getOrderPayCount()) | ||
| 72 | + .setOrderPayPrice(a.getOrderPayPrice() + b.getOrderPayPrice())); | ||
| 73 | + // 拼接数据 | ||
| 74 | + return MemberStatisticsConvert.INSTANCE.convertList(AreaUtils.getByType(AreaTypeEnum.PROVINCE, area -> area), userCountMap, orderMap); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + @Override | ||
| 78 | + public List<MemberSexStatisticsRespVO> getMemberSexStatisticsList() { | ||
| 79 | + return memberStatisticsMapper.selectSummaryListBySex(); | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + @Override | ||
| 83 | + public MemberAnalyseRespVO getMemberAnalyse(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 84 | + // 对照数据 | ||
| 85 | + MemberAnalyseComparisonRespVO vo = getMemberAnalyseComparisonData(beginTime, endTime); | ||
| 86 | + LocalDateTime referenceBeginTime = beginTime.minus(Duration.between(beginTime, endTime)); | ||
| 87 | + MemberAnalyseComparisonRespVO reference = getMemberAnalyseComparisonData(referenceBeginTime, beginTime); | ||
| 88 | + | ||
| 89 | + Integer payUserCount = tradeOrderStatisticsService.getPayUserCount(beginTime, endTime); | ||
| 90 | + // 计算客单价 | ||
| 91 | + int atv = 0; | ||
| 92 | + if (payUserCount != null && payUserCount > 0) { | ||
| 93 | + Integer payPrice = tradeOrderStatisticsService.getOrderPayPrice(beginTime, endTime); | ||
| 94 | + atv = NumberUtil.div(payPrice, payUserCount).intValue(); | ||
| 95 | + } | ||
| 96 | + return new MemberAnalyseRespVO() | ||
| 97 | + .setVisitorCount(apiAccessLogStatisticsService.getVisitorUserCount(beginTime, endTime)) | ||
| 98 | + .setOrderUserCount(tradeOrderStatisticsService.getOrderUserCount(beginTime, endTime)) | ||
| 99 | + .setPayUserCount(payUserCount) | ||
| 100 | + .setAtv(atv) | ||
| 101 | + .setComparison(new TradeStatisticsComparisonRespVO<>(vo, reference)); | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + private MemberAnalyseComparisonRespVO getMemberAnalyseComparisonData(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 105 | + Integer rechargeUserCount = Optional.ofNullable(payWalletStatisticsService.getUserRechargeSummary(beginTime, endTime)) | ||
| 106 | + .map(MemberSummaryRespVO::getRechargeUserCount).orElse(0); | ||
| 107 | + return new MemberAnalyseComparisonRespVO() | ||
| 108 | + .setUserCount(memberStatisticsMapper.selectUserCount(beginTime, endTime)) | ||
| 109 | + .setActiveUserCount(apiAccessLogStatisticsService.getActiveUserCount(beginTime, endTime)) | ||
| 110 | + .setRechargeUserCount(rechargeUserCount); | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | +} |
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/wallet/PayWalletApi.java renamed to yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/PayWalletStatisticsService.java
| 1 | -package cn.iocoder.yudao.module.pay.api.wallet; | 1 | +package cn.iocoder.yudao.module.statistics.service.pay; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.pay.api.wallet.dto.WalletSummaryRespDTO; | 3 | +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSummaryRespVO; |
| 4 | +import cn.iocoder.yudao.module.statistics.service.trade.bo.WalletSummaryRespBO; | ||
| 4 | 5 | ||
| 5 | import java.time.LocalDateTime; | 6 | import java.time.LocalDateTime; |
| 6 | 7 | ||
| 7 | /** | 8 | /** |
| 8 | - * 钱包 API 接口 | 9 | + * 钱包的统计 Service 接口 |
| 9 | * | 10 | * |
| 10 | * @author owen | 11 | * @author owen |
| 11 | */ | 12 | */ |
| 12 | -public interface PayWalletApi { | 13 | +public interface PayWalletStatisticsService { |
| 13 | 14 | ||
| 14 | /** | 15 | /** |
| 15 | * 获取钱包统计 | 16 | * 获取钱包统计 |
| @@ -18,6 +19,15 @@ public interface PayWalletApi { | @@ -18,6 +19,15 @@ public interface PayWalletApi { | ||
| 18 | * @param endTime 截止时间 | 19 | * @param endTime 截止时间 |
| 19 | * @return 钱包统计 | 20 | * @return 钱包统计 |
| 20 | */ | 21 | */ |
| 21 | - WalletSummaryRespDTO getWalletSummary(LocalDateTime beginTime, LocalDateTime endTime); | 22 | + WalletSummaryRespBO getWalletSummary(LocalDateTime beginTime, LocalDateTime endTime); |
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 获取钱包充值统计 | ||
| 26 | + * | ||
| 27 | + * @param beginTime 起始时间 | ||
| 28 | + * @param endTime 截止时间 | ||
| 29 | + * @return 钱包充值统计 | ||
| 30 | + */ | ||
| 31 | + MemberSummaryRespVO getUserRechargeSummary(LocalDateTime beginTime, LocalDateTime endTime); | ||
| 22 | 32 | ||
| 23 | } | 33 | } |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/pay/PayWalletStatisticsServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.service.pay; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; | ||
| 4 | +import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; | ||
| 5 | +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSummaryRespVO; | ||
| 6 | +import cn.iocoder.yudao.module.statistics.dal.mysql.pay.PayWalletStatisticsMapper; | ||
| 7 | +import cn.iocoder.yudao.module.statistics.service.trade.bo.WalletSummaryRespBO; | ||
| 8 | +import org.springframework.stereotype.Service; | ||
| 9 | +import org.springframework.validation.annotation.Validated; | ||
| 10 | + | ||
| 11 | +import javax.annotation.Resource; | ||
| 12 | +import java.time.LocalDateTime; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * 钱包的统计 Service 实现类 | ||
| 16 | + * | ||
| 17 | + * @author owen | ||
| 18 | + */ | ||
| 19 | +@Service | ||
| 20 | +@Validated | ||
| 21 | +public class PayWalletStatisticsServiceImpl implements PayWalletStatisticsService { | ||
| 22 | + | ||
| 23 | + @Resource | ||
| 24 | + private PayWalletStatisticsMapper payWalletStatisticsMapper; | ||
| 25 | + | ||
| 26 | + @Override | ||
| 27 | + public WalletSummaryRespBO getWalletSummary(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 28 | + WalletSummaryRespBO paySummary = payWalletStatisticsMapper.selectRechargeSummaryByPayTimeBetween( | ||
| 29 | + beginTime, endTime, true); | ||
| 30 | + WalletSummaryRespBO refundSummary = payWalletStatisticsMapper.selectRechargeSummaryByRefundTimeBetween( | ||
| 31 | + beginTime, endTime, PayRefundStatusEnum.SUCCESS.getStatus()); | ||
| 32 | + Integer walletPayPrice = payWalletStatisticsMapper.selectPriceSummaryByBizTypeAndCreateTimeBetween( | ||
| 33 | + beginTime, endTime, PayWalletBizTypeEnum.PAYMENT.getType()); | ||
| 34 | + // 拼接 | ||
| 35 | + paySummary.setOrderWalletPayPrice(walletPayPrice) | ||
| 36 | + .setRechargeRefundCount(refundSummary.getRechargeRefundCount()) | ||
| 37 | + .setRechargeRefundPrice(refundSummary.getRechargeRefundPrice()); | ||
| 38 | + return paySummary; | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + @Override | ||
| 42 | + public MemberSummaryRespVO getUserRechargeSummary(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 43 | + return payWalletStatisticsMapper.selectRechargeSummaryGroupByWalletId(beginTime, endTime, true); | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | +} |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/aftersale/TradeAfterSaleApi.java renamed to yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/AfterSaleStatisticsService.java
| 1 | -package cn.iocoder.yudao.module.trade.api.aftersale; | 1 | +package cn.iocoder.yudao.module.statistics.service.trade; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.trade.api.aftersale.dto.AfterSaleSummaryRespDTO; | 3 | +import cn.iocoder.yudao.module.statistics.service.trade.bo.AfterSaleSummaryRespBO; |
| 4 | 4 | ||
| 5 | import java.time.LocalDateTime; | 5 | import java.time.LocalDateTime; |
| 6 | 6 | ||
| 7 | /** | 7 | /** |
| 8 | - * 售后 API 接口 | 8 | + * 售后统计 Service 接口 |
| 9 | * | 9 | * |
| 10 | * @author owen | 10 | * @author owen |
| 11 | */ | 11 | */ |
| 12 | -public interface TradeAfterSaleApi { | 12 | +public interface AfterSaleStatisticsService { |
| 13 | 13 | ||
| 14 | /** | 14 | /** |
| 15 | * 获取售后单统计 | 15 | * 获取售后单统计 |
| @@ -18,6 +18,6 @@ public interface TradeAfterSaleApi { | @@ -18,6 +18,6 @@ public interface TradeAfterSaleApi { | ||
| 18 | * @param endTime 截止时间 | 18 | * @param endTime 截止时间 |
| 19 | * @return 售后统计结果 | 19 | * @return 售后统计结果 |
| 20 | */ | 20 | */ |
| 21 | - AfterSaleSummaryRespDTO getAfterSaleSummary(LocalDateTime beginTime, LocalDateTime endTime); | 21 | + AfterSaleSummaryRespBO getAfterSaleSummary(LocalDateTime beginTime, LocalDateTime endTime); |
| 22 | 22 | ||
| 23 | } | 23 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/aftersale/TradeAfterSaleApiImpl.java renamed to yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/AfterSaleStatisticsServiceImpl.java
| 1 | -package cn.iocoder.yudao.module.trade.api.aftersale; | 1 | +package cn.iocoder.yudao.module.statistics.service.trade; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.trade.api.aftersale.dto.AfterSaleSummaryRespDTO; | ||
| 4 | -import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleService; | 3 | +import cn.iocoder.yudao.module.statistics.dal.mysql.trade.AfterSaleStatisticsMapper; |
| 4 | +import cn.iocoder.yudao.module.statistics.service.trade.bo.AfterSaleSummaryRespBO; | ||
| 5 | import org.springframework.stereotype.Service; | 5 | import org.springframework.stereotype.Service; |
| 6 | import org.springframework.validation.annotation.Validated; | 6 | import org.springframework.validation.annotation.Validated; |
| 7 | 7 | ||
| @@ -9,20 +9,20 @@ import javax.annotation.Resource; | @@ -9,20 +9,20 @@ import javax.annotation.Resource; | ||
| 9 | import java.time.LocalDateTime; | 9 | import java.time.LocalDateTime; |
| 10 | 10 | ||
| 11 | /** | 11 | /** |
| 12 | - * 售后 API 接口实现类 | 12 | + * 售后统计 Service 实现类 |
| 13 | * | 13 | * |
| 14 | * @author owen | 14 | * @author owen |
| 15 | */ | 15 | */ |
| 16 | @Service | 16 | @Service |
| 17 | @Validated | 17 | @Validated |
| 18 | -public class TradeAfterSaleApiImpl implements TradeAfterSaleApi { | 18 | +public class AfterSaleStatisticsServiceImpl implements AfterSaleStatisticsService { |
| 19 | 19 | ||
| 20 | @Resource | 20 | @Resource |
| 21 | - private AfterSaleService afterSaleService; | 21 | + private AfterSaleStatisticsMapper afterSaleStatisticsMapper; |
| 22 | 22 | ||
| 23 | @Override | 23 | @Override |
| 24 | - public AfterSaleSummaryRespDTO getAfterSaleSummary(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 25 | - return afterSaleService.getAfterSaleSummary(beginTime, endTime); | 24 | + public AfterSaleSummaryRespBO getAfterSaleSummary(LocalDateTime beginTime, LocalDateTime endTime) { |
| 25 | + return afterSaleStatisticsMapper.selectSummaryByRefundTimeBetween(beginTime, endTime); | ||
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | } | 28 | } |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/TradeBrokerageApi.java renamed to yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/BrokerageStatisticsService.java
| 1 | -package cn.iocoder.yudao.module.trade.api.brokerage; | 1 | +package cn.iocoder.yudao.module.statistics.service.trade; |
| 2 | 2 | ||
| 3 | import java.time.LocalDateTime; | 3 | import java.time.LocalDateTime; |
| 4 | 4 | ||
| 5 | /** | 5 | /** |
| 6 | - * 分销 API 接口 | 6 | + * 分销统计 Service 接口 |
| 7 | * | 7 | * |
| 8 | * @author owen | 8 | * @author owen |
| 9 | */ | 9 | */ |
| 10 | -public interface TradeBrokerageApi { | 10 | +public interface BrokerageStatisticsService { |
| 11 | 11 | ||
| 12 | /** | 12 | /** |
| 13 | * 获取已结算的佣金金额 | 13 | * 获取已结算的佣金金额 |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/brokerage/TradeBrokerageApiImpl.java renamed to yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/BrokerageStatisticsServiceImpl.java
| 1 | -package cn.iocoder.yudao.module.trade.api.brokerage; | 1 | +package cn.iocoder.yudao.module.statistics.service.trade; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService; | 3 | +import cn.iocoder.yudao.module.statistics.dal.mysql.trade.BrokerageStatisticsMapper; |
| 4 | +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; | ||
| 5 | +import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; | ||
| 4 | import org.springframework.stereotype.Service; | 6 | import org.springframework.stereotype.Service; |
| 5 | import org.springframework.validation.annotation.Validated; | 7 | import org.springframework.validation.annotation.Validated; |
| 6 | 8 | ||
| @@ -8,20 +10,22 @@ import javax.annotation.Resource; | @@ -8,20 +10,22 @@ import javax.annotation.Resource; | ||
| 8 | import java.time.LocalDateTime; | 10 | import java.time.LocalDateTime; |
| 9 | 11 | ||
| 10 | /** | 12 | /** |
| 11 | - * 订单 API 接口实现类 | 13 | + * 分销统计 Service 实现类 |
| 12 | * | 14 | * |
| 13 | - * @author HUIHUI | 15 | + * @author owen |
| 14 | */ | 16 | */ |
| 15 | @Service | 17 | @Service |
| 16 | @Validated | 18 | @Validated |
| 17 | -public class TradeBrokerageApiImpl implements TradeBrokerageApi { | 19 | +public class BrokerageStatisticsServiceImpl implements BrokerageStatisticsService { |
| 18 | 20 | ||
| 19 | @Resource | 21 | @Resource |
| 20 | - private BrokerageRecordService brokerageRecordService; | 22 | + private BrokerageStatisticsMapper brokerageStatisticsMapper; |
| 21 | 23 | ||
| 22 | @Override | 24 | @Override |
| 23 | public Integer getBrokerageSettlementPriceSummary(LocalDateTime beginTime, LocalDateTime endTime) { | 25 | public Integer getBrokerageSettlementPriceSummary(LocalDateTime beginTime, LocalDateTime endTime) { |
| 24 | - return brokerageRecordService.getBrokerageSettlementPriceSummary(beginTime, endTime); | 26 | + return brokerageStatisticsMapper.selectSummaryPriceByStatusAndUnfreezeTimeBetween( |
| 27 | + BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus(), | ||
| 28 | + beginTime, endTime); | ||
| 25 | } | 29 | } |
| 26 | 30 | ||
| 27 | } | 31 | } |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeOrderStatisticsService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.service.trade; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAreaStatisticsRespVO; | ||
| 4 | +import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeOrderSummaryRespBO; | ||
| 5 | + | ||
| 6 | +import java.time.LocalDateTime; | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 交易订单的统计 Service 接口 | ||
| 11 | + * | ||
| 12 | + * @author owen | ||
| 13 | + */ | ||
| 14 | +public interface TradeOrderStatisticsService { | ||
| 15 | + | ||
| 16 | + /** | ||
| 17 | + * 获取订单统计 | ||
| 18 | + * | ||
| 19 | + * @param beginTime 起始时间 | ||
| 20 | + * @param endTime 截止时间 | ||
| 21 | + * @return 订单统计结果 | ||
| 22 | + */ | ||
| 23 | + TradeOrderSummaryRespBO getOrderSummary(LocalDateTime beginTime, LocalDateTime endTime); | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 获取地区订单统计 | ||
| 27 | + * | ||
| 28 | + * @return 订单统计结果 | ||
| 29 | + */ | ||
| 30 | + List<MemberAreaStatisticsRespVO> getSummaryListByAreaId(); | ||
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * 获取下单用户数量 | ||
| 34 | + * | ||
| 35 | + * @param beginTime 起始时间 | ||
| 36 | + * @param endTime 截止时间 | ||
| 37 | + * @return 支付下单数量 | ||
| 38 | + */ | ||
| 39 | + Integer getOrderUserCount(LocalDateTime beginTime, LocalDateTime endTime); | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * 获取支付用户数量 | ||
| 43 | + * | ||
| 44 | + * @param beginTime 起始时间 | ||
| 45 | + * @param endTime 截止时间 | ||
| 46 | + * @return 支付用户数量 | ||
| 47 | + */ | ||
| 48 | + Integer getPayUserCount(LocalDateTime beginTime, LocalDateTime endTime); | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * 获取支付金额 | ||
| 52 | + * | ||
| 53 | + * @param beginTime 起始时间 | ||
| 54 | + * @param endTime 截止时间 | ||
| 55 | + * @return 支付用户金额 | ||
| 56 | + */ | ||
| 57 | + Integer getOrderPayPrice(LocalDateTime beginTime, LocalDateTime endTime); | ||
| 58 | + | ||
| 59 | +} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeOrderStatisticsServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.statistics.service.trade; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAreaStatisticsRespVO; | ||
| 4 | +import cn.iocoder.yudao.module.statistics.dal.mysql.trade.TradeOrderStatisticsMapper; | ||
| 5 | +import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeOrderSummaryRespBO; | ||
| 6 | +import org.springframework.stereotype.Service; | ||
| 7 | +import org.springframework.validation.annotation.Validated; | ||
| 8 | + | ||
| 9 | +import javax.annotation.Resource; | ||
| 10 | +import java.time.LocalDateTime; | ||
| 11 | +import java.util.List; | ||
| 12 | + | ||
| 13 | +/** | ||
| 14 | + * 交易订单统计 Service 实现类 | ||
| 15 | + * | ||
| 16 | + * @author owen | ||
| 17 | + */ | ||
| 18 | +@Service | ||
| 19 | +@Validated | ||
| 20 | +public class TradeOrderStatisticsServiceImpl implements TradeOrderStatisticsService { | ||
| 21 | + | ||
| 22 | + @Resource | ||
| 23 | + private TradeOrderStatisticsMapper tradeOrderStatisticsMapper; | ||
| 24 | + | ||
| 25 | + @Override | ||
| 26 | + public TradeOrderSummaryRespBO getOrderSummary(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 27 | + return new TradeOrderSummaryRespBO() | ||
| 28 | + .setOrderCreateCount(tradeOrderStatisticsMapper.selectCountByCreateTimeBetween(beginTime, endTime)) | ||
| 29 | + .setOrderPayCount(tradeOrderStatisticsMapper.selectCountByPayTimeBetween(beginTime, endTime)) | ||
| 30 | + .setOrderPayPrice(tradeOrderStatisticsMapper.selectSummaryPriceByPayTimeBetween(beginTime, endTime)); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + @Override | ||
| 34 | + public List<MemberAreaStatisticsRespVO> getSummaryListByAreaId() { | ||
| 35 | + return tradeOrderStatisticsMapper.selectSummaryListByAreaId(); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + @Override | ||
| 39 | + public Integer getOrderUserCount(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 40 | + return tradeOrderStatisticsMapper.selectUserCountByCreateTimeBetween(beginTime, endTime); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + @Override | ||
| 44 | + public Integer getPayUserCount(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 45 | + return tradeOrderStatisticsMapper.selectUserCountByPayTimeBetween(beginTime, endTime); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + @Override | ||
| 49 | + public Integer getOrderPayPrice(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 50 | + return tradeOrderStatisticsMapper.selectSummaryPriceByPayTimeBetween(beginTime, endTime); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | +} |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsService.java
| @@ -22,7 +22,7 @@ public interface TradeStatisticsService { | @@ -22,7 +22,7 @@ public interface TradeStatisticsService { | ||
| 22 | TradeStatisticsComparisonRespVO<TradeSummaryRespVO> getTradeSummaryComparison(); | 22 | TradeStatisticsComparisonRespVO<TradeSummaryRespVO> getTradeSummaryComparison(); |
| 23 | 23 | ||
| 24 | /** | 24 | /** |
| 25 | - * 获得交易状况统计 | 25 | + * 获得交易状况统计对照 |
| 26 | * | 26 | * |
| 27 | * @return 统计数据对照 | 27 | * @return 统计数据对照 |
| 28 | */ | 28 | */ |
| @@ -30,6 +30,13 @@ public interface TradeStatisticsService { | @@ -30,6 +30,13 @@ public interface TradeStatisticsService { | ||
| 30 | LocalDateTime beginTime, LocalDateTime endTime); | 30 | LocalDateTime beginTime, LocalDateTime endTime); |
| 31 | 31 | ||
| 32 | /** | 32 | /** |
| 33 | + * 获得交易状况统计 | ||
| 34 | + * | ||
| 35 | + * @return 统计数据对照 | ||
| 36 | + */ | ||
| 37 | + Integer getExpensePrice(LocalDateTime beginTime, LocalDateTime endTime); | ||
| 38 | + | ||
| 39 | + /** | ||
| 33 | * 获得交易状况明细 | 40 | * 获得交易状况明细 |
| 34 | * | 41 | * |
| 35 | * @return 统计数据列表 | 42 | * @return 统计数据列表 |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsServiceImpl.java
| @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.statistics.service.trade; | @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.statistics.service.trade; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.date.LocalDateTimeUtil; | 3 | import cn.hutool.core.date.LocalDateTimeUtil; |
| 4 | import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; | 4 | import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; |
| 5 | -import cn.iocoder.yudao.module.pay.api.wallet.PayWalletApi; | ||
| 6 | -import cn.iocoder.yudao.module.pay.api.wallet.dto.WalletSummaryRespDTO; | 5 | +import cn.iocoder.yudao.module.statistics.service.pay.PayWalletStatisticsService; |
| 6 | +import cn.iocoder.yudao.module.statistics.service.trade.bo.WalletSummaryRespBO; | ||
| 7 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO; | 7 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO; |
| 8 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeSummaryRespVO; | 8 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeSummaryRespVO; |
| 9 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO; | 9 | import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO; |
| @@ -11,11 +11,8 @@ import cn.iocoder.yudao.module.statistics.convert.trade.TradeStatisticsConvert; | @@ -11,11 +11,8 @@ import cn.iocoder.yudao.module.statistics.convert.trade.TradeStatisticsConvert; | ||
| 11 | import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO; | 11 | import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO; |
| 12 | import cn.iocoder.yudao.module.statistics.dal.mysql.trade.TradeStatisticsMapper; | 12 | import cn.iocoder.yudao.module.statistics.dal.mysql.trade.TradeStatisticsMapper; |
| 13 | import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO; | 13 | import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO; |
| 14 | -import cn.iocoder.yudao.module.trade.api.aftersale.TradeAfterSaleApi; | ||
| 15 | -import cn.iocoder.yudao.module.trade.api.aftersale.dto.AfterSaleSummaryRespDTO; | ||
| 16 | -import cn.iocoder.yudao.module.trade.api.brokerage.TradeBrokerageApi; | ||
| 17 | -import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi; | ||
| 18 | -import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderSummaryRespDTO; | 14 | +import cn.iocoder.yudao.module.statistics.service.trade.bo.AfterSaleSummaryRespBO; |
| 15 | +import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeOrderSummaryRespBO; | ||
| 19 | import org.springframework.stereotype.Service; | 16 | import org.springframework.stereotype.Service; |
| 20 | import org.springframework.util.StopWatch; | 17 | import org.springframework.util.StopWatch; |
| 21 | import org.springframework.validation.annotation.Validated; | 18 | import org.springframework.validation.annotation.Validated; |
| @@ -37,31 +34,26 @@ public class TradeStatisticsServiceImpl implements TradeStatisticsService { | @@ -37,31 +34,26 @@ public class TradeStatisticsServiceImpl implements TradeStatisticsService { | ||
| 37 | @Resource | 34 | @Resource |
| 38 | private TradeStatisticsMapper tradeStatisticsMapper; | 35 | private TradeStatisticsMapper tradeStatisticsMapper; |
| 39 | 36 | ||
| 40 | - // TODO @疯狂:统计逻辑,自己服务 mapper 去统计,不要调用其它服务 API; | ||
| 41 | - // 主要的考虑点,其它服务是在线的业务,统计是离线业务,尽量不占用他们的 db 资源; | ||
| 42 | - // 统计服务,从建议使用从库,或者从 mysql 抽取到单独的 clickhouse 或者其它的大数据组件; | ||
| 43 | - | ||
| 44 | @Resource | 37 | @Resource |
| 45 | - private TradeOrderApi tradeOrderApi; | 38 | + private TradeOrderStatisticsService tradeOrderStatisticsService; |
| 46 | @Resource | 39 | @Resource |
| 47 | - private TradeAfterSaleApi tradeAfterSaleApi; | 40 | + private AfterSaleStatisticsService afterSaleStatisticsService; |
| 48 | @Resource | 41 | @Resource |
| 49 | - private TradeBrokerageApi tradeBrokerageApi; | 42 | + private BrokerageStatisticsService brokerageStatisticsService; |
| 50 | @Resource | 43 | @Resource |
| 51 | - private PayWalletApi payWalletApi; | 44 | + private PayWalletStatisticsService payWalletStatisticsService; |
| 52 | 45 | ||
| 53 | @Override | 46 | @Override |
| 54 | public TradeStatisticsComparisonRespVO<TradeSummaryRespVO> getTradeSummaryComparison() { | 47 | public TradeStatisticsComparisonRespVO<TradeSummaryRespVO> getTradeSummaryComparison() { |
| 55 | - // 昨天的数据 | 48 | + // 1.1 昨天的数据 |
| 56 | TradeSummaryRespBO yesterdayData = getTradeSummaryByDays(-1); | 49 | TradeSummaryRespBO yesterdayData = getTradeSummaryByDays(-1); |
| 57 | - // 前天的数据(用于对照昨天的数据) | 50 | + // 1.2 前天的数据(用于对照昨天的数据) |
| 58 | TradeSummaryRespBO beforeYesterdayData = getTradeSummaryByDays(-2); | 51 | TradeSummaryRespBO beforeYesterdayData = getTradeSummaryByDays(-2); |
| 59 | - | ||
| 60 | - // 本月数据; | 52 | + // 2.1 本月数据 |
| 61 | TradeSummaryRespBO monthData = getTradeSummaryByMonths(0); | 53 | TradeSummaryRespBO monthData = getTradeSummaryByMonths(0); |
| 62 | - // 上月数据(用于对照本月的数据) | 54 | + // 2.2 上月数据(用于对照本月的数据) |
| 63 | TradeSummaryRespBO lastMonthData = getTradeSummaryByMonths(-1); | 55 | TradeSummaryRespBO lastMonthData = getTradeSummaryByMonths(-1); |
| 64 | - | 56 | + // 转换返回 |
| 65 | return TradeStatisticsConvert.INSTANCE.convert(yesterdayData, beforeYesterdayData, monthData, lastMonthData); | 57 | return TradeStatisticsConvert.INSTANCE.convert(yesterdayData, beforeYesterdayData, monthData, lastMonthData); |
| 66 | } | 58 | } |
| 67 | 59 | ||
| @@ -77,37 +69,42 @@ public class TradeStatisticsServiceImpl implements TradeStatisticsService { | @@ -77,37 +69,42 @@ public class TradeStatisticsServiceImpl implements TradeStatisticsService { | ||
| 77 | } | 69 | } |
| 78 | 70 | ||
| 79 | @Override | 71 | @Override |
| 72 | + public Integer getExpensePrice(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 73 | + return tradeStatisticsMapper.selectExpensePriceByTimeBetween(beginTime, endTime); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + @Override | ||
| 80 | public List<TradeTrendSummaryRespVO> getTradeStatisticsList(LocalDateTime beginTime, LocalDateTime endTime) { | 77 | public List<TradeTrendSummaryRespVO> getTradeStatisticsList(LocalDateTime beginTime, LocalDateTime endTime) { |
| 81 | return tradeStatisticsMapper.selectListByTimeBetween(beginTime, endTime); | 78 | return tradeStatisticsMapper.selectListByTimeBetween(beginTime, endTime); |
| 82 | } | 79 | } |
| 83 | 80 | ||
| 84 | @Override | 81 | @Override |
| 85 | public String statisticsYesterdayTrade() { | 82 | public String statisticsYesterdayTrade() { |
| 86 | - // 处理统计参数 | ||
| 87 | LocalDateTime yesterday = LocalDateTime.now().minusDays(1); | 83 | LocalDateTime yesterday = LocalDateTime.now().minusDays(1); |
| 88 | LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(yesterday); | 84 | LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(yesterday); |
| 89 | LocalDateTime endTime = LocalDateTimeUtil.endOfDay(yesterday); | 85 | LocalDateTime endTime = LocalDateTimeUtil.endOfDay(yesterday); |
| 90 | - // 统计 | 86 | + // 1.1 统计订单 |
| 91 | StopWatch stopWatch = new StopWatch("交易统计"); | 87 | StopWatch stopWatch = new StopWatch("交易统计"); |
| 92 | stopWatch.start("统计订单"); | 88 | stopWatch.start("统计订单"); |
| 93 | - TradeOrderSummaryRespDTO orderSummary = tradeOrderApi.getOrderSummary(beginTime, endTime); | 89 | + TradeOrderSummaryRespBO orderSummary = tradeOrderStatisticsService.getOrderSummary(beginTime, endTime); |
| 94 | stopWatch.stop(); | 90 | stopWatch.stop(); |
| 95 | - | 91 | + // 1.2 统计售后 |
| 96 | stopWatch.start("统计售后"); | 92 | stopWatch.start("统计售后"); |
| 97 | - AfterSaleSummaryRespDTO afterSaleSummary = tradeAfterSaleApi.getAfterSaleSummary(beginTime, endTime); | 93 | + AfterSaleSummaryRespBO afterSaleSummary = afterSaleStatisticsService.getAfterSaleSummary(beginTime, endTime); |
| 98 | stopWatch.stop(); | 94 | stopWatch.stop(); |
| 99 | - | 95 | + // 1.3 统计佣金 |
| 100 | stopWatch.start("统计佣金"); | 96 | stopWatch.start("统计佣金"); |
| 101 | - Integer brokerageSettlementPrice = tradeBrokerageApi.getBrokerageSettlementPriceSummary(beginTime, endTime); | 97 | + Integer brokerageSettlementPrice = brokerageStatisticsService.getBrokerageSettlementPriceSummary(beginTime, endTime); |
| 102 | stopWatch.stop(); | 98 | stopWatch.stop(); |
| 103 | - | 99 | + // 1.4 统计充值 |
| 104 | stopWatch.start("统计充值"); | 100 | stopWatch.start("统计充值"); |
| 105 | - WalletSummaryRespDTO walletSummary = payWalletApi.getWalletSummary(beginTime, endTime); | 101 | + WalletSummaryRespBO walletSummary = payWalletStatisticsService.getWalletSummary(beginTime, endTime); |
| 106 | stopWatch.stop(); | 102 | stopWatch.stop(); |
| 107 | - // 插入数据 | ||
| 108 | - TradeStatisticsDO entity = TradeStatisticsConvert.INSTANCE.convert(yesterday, orderSummary, afterSaleSummary, brokerageSettlementPrice, walletSummary); | 103 | + |
| 104 | + // 2. 插入数据 | ||
| 105 | + TradeStatisticsDO entity = TradeStatisticsConvert.INSTANCE.convert(yesterday, orderSummary, afterSaleSummary, | ||
| 106 | + brokerageSettlementPrice, walletSummary); | ||
| 109 | tradeStatisticsMapper.insert(entity); | 107 | tradeStatisticsMapper.insert(entity); |
| 110 | - // 返回计时结果 | ||
| 111 | return stopWatch.prettyPrint(); | 108 | return stopWatch.prettyPrint(); |
| 112 | } | 109 | } |
| 113 | 110 |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/aftersale/dto/AfterSaleSummaryRespDTO.java renamed to yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/bo/AfterSaleSummaryRespBO.java
| 1 | -package cn.iocoder.yudao.module.trade.api.aftersale.dto; | 1 | +package cn.iocoder.yudao.module.statistics.service.trade.bo; |
| 2 | 2 | ||
| 3 | import lombok.Data; | 3 | import lombok.Data; |
| 4 | 4 | ||
| @@ -8,7 +8,7 @@ import lombok.Data; | @@ -8,7 +8,7 @@ import lombok.Data; | ||
| 8 | * @author owen | 8 | * @author owen |
| 9 | */ | 9 | */ |
| 10 | @Data | 10 | @Data |
| 11 | -public class AfterSaleSummaryRespDTO { | 11 | +public class AfterSaleSummaryRespBO { |
| 12 | 12 | ||
| 13 | /** | 13 | /** |
| 14 | * 退款订单数 | 14 | * 退款订单数 |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/dto/TradeOrderSummaryRespDTO.java renamed to yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/bo/TradeOrderSummaryRespBO.java
| 1 | -package cn.iocoder.yudao.module.trade.api.order.dto; | 1 | +package cn.iocoder.yudao.module.statistics.service.trade.bo; |
| 2 | 2 | ||
| 3 | import lombok.Data; | 3 | import lombok.Data; |
| 4 | 4 | ||
| 5 | /** | 5 | /** |
| 6 | - * 订单统计 Response DTO | 6 | + * 订单统计 Response BO |
| 7 | * | 7 | * |
| 8 | * @author owen | 8 | * @author owen |
| 9 | */ | 9 | */ |
| 10 | @Data | 10 | @Data |
| 11 | -public class TradeOrderSummaryRespDTO { | 11 | +public class TradeOrderSummaryRespBO { |
| 12 | 12 | ||
| 13 | /** | 13 | /** |
| 14 | * 创建订单数 | 14 | * 创建订单数 |
| 15 | */ | 15 | */ |
| 16 | - private Long orderCreateCount; | 16 | + private Integer orderCreateCount; |
| 17 | /** | 17 | /** |
| 18 | * 支付订单商品数 | 18 | * 支付订单商品数 |
| 19 | */ | 19 | */ |
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/wallet/dto/WalletSummaryRespDTO.java renamed to yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/bo/WalletSummaryRespBO.java
| 1 | -package cn.iocoder.yudao.module.pay.api.wallet.dto; | 1 | +package cn.iocoder.yudao.module.statistics.service.trade.bo; |
| 2 | 2 | ||
| 3 | import lombok.Data; | 3 | import lombok.Data; |
| 4 | 4 | ||
| @@ -8,7 +8,8 @@ import lombok.Data; | @@ -8,7 +8,8 @@ import lombok.Data; | ||
| 8 | * @author owen | 8 | * @author owen |
| 9 | */ | 9 | */ |
| 10 | @Data | 10 | @Data |
| 11 | -public class WalletSummaryRespDTO { | 11 | +public class WalletSummaryRespBO { |
| 12 | + | ||
| 12 | /** | 13 | /** |
| 13 | * 总支付金额(余额),单位:分 | 14 | * 总支付金额(余额),单位:分 |
| 14 | */ | 15 | */ |
yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/infra/ApiAccessLogStatisticsMapper.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||
| 3 | +<mapper namespace="cn.iocoder.yudao.module.statistics.dal.mysql.infra.ApiAccessLogStatisticsMapper"> | ||
| 4 | + | ||
| 5 | + <select id="selectCountByIp" resultType="java.lang.Integer"> | ||
| 6 | + SELECT COUNT(1) | ||
| 7 | + FROM infra_api_access_log | ||
| 8 | + WHERE create_time BETWEEN #{beginTime} AND #{endTime} | ||
| 9 | + AND deleted = FALSE | ||
| 10 | + GROUP BY user_ip | ||
| 11 | + </select> | ||
| 12 | + | ||
| 13 | + <select id="selectCountByUserId" resultType="java.lang.Integer"> | ||
| 14 | + SELECT COUNT(1) | ||
| 15 | + FROM infra_api_access_log | ||
| 16 | + WHERE user_id > 0 | ||
| 17 | + AND create_time BETWEEN #{beginTime} AND #{endTime} | ||
| 18 | + AND deleted = FALSE | ||
| 19 | + GROUP BY user_id | ||
| 20 | + </select> | ||
| 21 | + | ||
| 22 | +</mapper> |
yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/member/MemberStatisticsMapper.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||
| 3 | +<mapper namespace="cn.iocoder.yudao.module.statistics.dal.mysql.member.MemberStatisticsMapper"> | ||
| 4 | + | ||
| 5 | + <select id="selectSummaryListByAreaId" | ||
| 6 | + resultType="cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAreaStatisticsRespVO"> | ||
| 7 | + SELECT area_id, COUNT(1) AS userCount | ||
| 8 | + FROM member_user | ||
| 9 | + WHERE deleted = FALSE | ||
| 10 | + GROUP BY area_id | ||
| 11 | + <!-- TODO @疯狂:order by 是不是交给内存哈 --> | ||
| 12 | + ORDER BY userCount DESC | ||
| 13 | + </select> | ||
| 14 | + | ||
| 15 | + <select id="selectSummaryListBySex" | ||
| 16 | + resultType="cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSexStatisticsRespVO"> | ||
| 17 | + SELECT sex, COUNT(1) AS userCount | ||
| 18 | + FROM member_user | ||
| 19 | + WHERE deleted = FALSE | ||
| 20 | + GROUP BY sex | ||
| 21 | + <!-- TODO @疯狂:order by 是不是交给内存哈 --> | ||
| 22 | + ORDER BY userCount DESC | ||
| 23 | + </select> | ||
| 24 | + | ||
| 25 | + <select id="selectUserCount" resultType="java.lang.Integer"> | ||
| 26 | + SELECT COUNT(1) | ||
| 27 | + FROM member_user | ||
| 28 | + WHERE deleted = FALSE | ||
| 29 | + <if test="beginTime != null"> | ||
| 30 | + AND create_time >= #{beginTime} | ||
| 31 | + </if> | ||
| 32 | + <if test="endTime != null"> | ||
| 33 | + AND create_time <= #{endTime} | ||
| 34 | + </if> | ||
| 35 | + </select> | ||
| 36 | + | ||
| 37 | +</mapper> |
yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/pay/PayWalletStatisticsMapper.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||
| 3 | +<mapper namespace="cn.iocoder.yudao.module.statistics.dal.mysql.pay.PayWalletStatisticsMapper"> | ||
| 4 | + <select id="selectRechargeSummaryByPayTimeBetween" | ||
| 5 | + resultType="cn.iocoder.yudao.module.statistics.service.trade.bo.WalletSummaryRespBO"> | ||
| 6 | + SELECT COUNT(1) AS rechargePayCount, | ||
| 7 | + SUM(pay_price) AS rechargePayPrice | ||
| 8 | + FROM pay_wallet_recharge | ||
| 9 | + WHERE pay_status = #{payStatus} | ||
| 10 | + AND pay_time BETWEEN #{beginTime} AND #{endTime} | ||
| 11 | + AND deleted = FALSE | ||
| 12 | + </select> | ||
| 13 | + | ||
| 14 | + <select id="selectRechargeSummaryByRefundTimeBetween" | ||
| 15 | + resultType="cn.iocoder.yudao.module.statistics.service.trade.bo.WalletSummaryRespBO"> | ||
| 16 | + SELECT COUNT(1) AS rechargeRefundCount, | ||
| 17 | + SUM(pay_price) AS rechargeRefundPrice | ||
| 18 | + FROM pay_wallet_recharge | ||
| 19 | + WHERE refund_status = #{refundStatus} | ||
| 20 | + AND refund_time BETWEEN #{beginTime} AND #{endTime} | ||
| 21 | + AND deleted = FALSE | ||
| 22 | + </select> | ||
| 23 | + | ||
| 24 | + <select id="selectPriceSummaryByBizTypeAndCreateTimeBetween" resultType="java.lang.Integer"> | ||
| 25 | + SELECT SUM(price) | ||
| 26 | + FROM pay_wallet_transaction | ||
| 27 | + WHERE biz_type = #{bizType} | ||
| 28 | + AND create_time BETWEEN #{beginTime} AND #{endTime} | ||
| 29 | + AND deleted = FALSE | ||
| 30 | + </select> | ||
| 31 | + | ||
| 32 | + <select id="selectRechargeSummaryGroupByWalletId" | ||
| 33 | + resultType="cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberSummaryRespVO"> | ||
| 34 | + SELECT COUNT(1) AS rechargeUserCount, | ||
| 35 | + SUM(pay_price) AS rechargePrice | ||
| 36 | + FROM pay_wallet_recharge | ||
| 37 | + WHERE pay_status = #{payStatus} | ||
| 38 | + <if test="beginTime != null"> | ||
| 39 | + AND pay_time >= #{beginTime} | ||
| 40 | + </if> | ||
| 41 | + <if test="endTime != null"> | ||
| 42 | + AND pay_time <= #{endTime} | ||
| 43 | + </if> | ||
| 44 | + AND deleted = FALSE | ||
| 45 | + GROUP BY wallet_id | ||
| 46 | + </select> | ||
| 47 | + | ||
| 48 | +</mapper> |
yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/AfterSaleStatisticsMapper.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||
| 3 | +<mapper namespace="cn.iocoder.yudao.module.statistics.dal.mysql.trade.AfterSaleStatisticsMapper"> | ||
| 4 | + | ||
| 5 | + <select id="selectSummaryByRefundTimeBetween" | ||
| 6 | + resultType="cn.iocoder.yudao.module.statistics.service.trade.bo.AfterSaleSummaryRespBO"> | ||
| 7 | + SELECT COUNT(1) AS afterSaleCount, | ||
| 8 | + SUM(refund_price) AS afterSaleRefundPrice | ||
| 9 | + FROM trade_after_sale | ||
| 10 | + WHERE refund_time BETWEEN #{beginTime} AND #{endTime} | ||
| 11 | + AND deleted = FALSE | ||
| 12 | + </select> | ||
| 13 | + | ||
| 14 | +</mapper> |
yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/BrokerageStatisticsMapper.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||
| 3 | +<mapper namespace="cn.iocoder.yudao.module.statistics.dal.mysql.trade.BrokerageStatisticsMapper"> | ||
| 4 | + | ||
| 5 | + <select id="selectSummaryPriceByStatusAndUnfreezeTimeBetween" resultType="java.lang.Integer"> | ||
| 6 | + SELECT SUM(price) | ||
| 7 | + FROM trade_brokerage_record | ||
| 8 | + WHERE biz_type = #{bizType} | ||
| 9 | + AND status = #{status} | ||
| 10 | + AND unfreeze_time BETWEEN #{beginTime} AND #{endTime} | ||
| 11 | + AND deleted = FALSE | ||
| 12 | + </select> | ||
| 13 | + | ||
| 14 | +</mapper> |
yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/TradeOrderStatisticsMapper.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||
| 3 | +<mapper namespace="cn.iocoder.yudao.module.statistics.dal.mysql.trade.TradeOrderStatisticsMapper"> | ||
| 4 | + | ||
| 5 | + <select id="selectSummaryListByAreaId" | ||
| 6 | + resultType="cn.iocoder.yudao.module.statistics.controller.admin.member.vo.MemberAreaStatisticsRespVO"> | ||
| 7 | + SELECT receiver_area_id AS areaId, | ||
| 8 | + (SELECT COUNT(1) | ||
| 9 | + FROM trade_order AS s | ||
| 10 | + WHERE s.receiver_area_id = m.receiver_area_id) AS orderCreateCount, | ||
| 11 | + (SELECT COUNT(1) | ||
| 12 | + FROM trade_order AS s | ||
| 13 | + WHERE s.receiver_area_id = m.receiver_area_id | ||
| 14 | + AND s.pay_status = TRUE | ||
| 15 | + AND s.deleted = FALSE) AS orderPayCount, | ||
| 16 | + (SELECT SUM(s.pay_price) | ||
| 17 | + FROM trade_order AS s | ||
| 18 | + WHERE s.receiver_area_id = m.receiver_area_id | ||
| 19 | + AND s.pay_status = TRUE | ||
| 20 | + AND s.deleted = FALSE) AS orderPayPrice | ||
| 21 | + FROM trade_order m | ||
| 22 | + WHERE deleted = FALSE | ||
| 23 | + GROUP BY receiver_area_id | ||
| 24 | + </select> | ||
| 25 | + | ||
| 26 | + <select id="selectUserCountByCreateTimeBetween" resultType="java.lang.Integer"> | ||
| 27 | + SELECT COUNT(DISTINCT(user_id)) | ||
| 28 | + FROM trade_order | ||
| 29 | + WHERE deleted = FALSE | ||
| 30 | + AND create_time BETWEEN #{beginTime} AND #{endTime} | ||
| 31 | + </select> | ||
| 32 | + | ||
| 33 | + <select id="selectUserCountByPayTimeBetween" resultType="java.lang.Integer"> | ||
| 34 | + SELECT COUNT(DISTINCT(user_id)) | ||
| 35 | + FROM trade_order | ||
| 36 | + WHERE pay_time BETWEEN #{beginTime} AND #{endTime} | ||
| 37 | + AND pay_status = TRUE | ||
| 38 | + AND deleted = FALSE | ||
| 39 | + </select> | ||
| 40 | + | ||
| 41 | + <select id="selectCountByCreateTimeBetween" resultType="java.lang.Integer"> | ||
| 42 | + SELECT COUNT(1) | ||
| 43 | + FROM trade_order | ||
| 44 | + WHERE create_time BETWEEN #{beginTime} AND #{endTime} | ||
| 45 | + AND deleted = FALSE | ||
| 46 | + </select> | ||
| 47 | + | ||
| 48 | + <select id="selectCountByPayTimeBetween" resultType="java.lang.Integer"> | ||
| 49 | + SELECT COUNT(1) | ||
| 50 | + FROM trade_order | ||
| 51 | + WHERE pay_status = TRUE | ||
| 52 | + AND create_time BETWEEN #{beginTime} AND #{endTime} | ||
| 53 | + AND deleted = FALSE | ||
| 54 | + </select> | ||
| 55 | + | ||
| 56 | + <select id="selectSummaryPriceByPayTimeBetween" resultType="java.lang.Integer"> | ||
| 57 | + SELECT SUM(pay_price) | ||
| 58 | + FROM trade_order AS s | ||
| 59 | + WHERE s.pay_status = TRUE | ||
| 60 | + AND deleted = FALSE | ||
| 61 | + AND create_time BETWEEN #{beginTime} AND #{endTime} | ||
| 62 | + </select> | ||
| 63 | + | ||
| 64 | +</mapper> |
yudao-module-mall/yudao-module-statistics-biz/src/main/resources/mapper/trade/TradeStatisticsMapper.xml
| @@ -37,4 +37,17 @@ | @@ -37,4 +37,17 @@ | ||
| 37 | GROUP BY date | 37 | GROUP BY date |
| 38 | </select> | 38 | </select> |
| 39 | 39 | ||
| 40 | + <select id="selectExpensePriceByTimeBetween" resultType="java.lang.Integer"> | ||
| 41 | + SELECT -- 支出金额 = 余额支付金额 + 支付佣金金额 + 商品退款金额 | ||
| 42 | + SUM(order_wallet_pay_price + brokerage_settlement_price + after_sale_refund_price) AS expensePrice | ||
| 43 | + FROM trade_statistics | ||
| 44 | + WHERE deleted = FALSE | ||
| 45 | + <if test="beginTime != null"> | ||
| 46 | + AND time >= #{beginTime} | ||
| 47 | + </if> | ||
| 48 | + <if test="endTime != null"> | ||
| 49 | + AND time <= #{endTime} | ||
| 50 | + </if> | ||
| 51 | + </select> | ||
| 52 | + | ||
| 40 | </mapper> | 53 | </mapper> |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java
| 1 | package cn.iocoder.yudao.module.trade.api.order; | 1 | package cn.iocoder.yudao.module.trade.api.order; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; | 3 | import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; |
| 4 | -import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderSummaryRespDTO; | ||
| 5 | 4 | ||
| 6 | -import java.time.LocalDateTime; | ||
| 7 | import java.util.Collection; | 5 | import java.util.Collection; |
| 8 | import java.util.List; | 6 | import java.util.List; |
| 9 | 7 | ||
| @@ -30,25 +28,7 @@ public interface TradeOrderApi { | @@ -30,25 +28,7 @@ public interface TradeOrderApi { | ||
| 30 | */ | 28 | */ |
| 31 | TradeOrderRespDTO getOrder(Long id); | 29 | TradeOrderRespDTO getOrder(Long id); |
| 32 | 30 | ||
| 33 | - /** | ||
| 34 | - * 获取订单统计 | ||
| 35 | - * | ||
| 36 | - * @param beginTime 起始时间 | ||
| 37 | - * @param endTime 截止时间 | ||
| 38 | - * @return 订单统计结果 | ||
| 39 | - */ | ||
| 40 | - TradeOrderSummaryRespDTO getOrderSummary(LocalDateTime beginTime, LocalDateTime endTime); | ||
| 41 | - | ||
| 42 | - /** | ||
| 43 | - * 更新拼团相关信息到订单 | ||
| 44 | - * | ||
| 45 | - * @param orderId 订单编号 | ||
| 46 | - * @param activityId 拼团活动编号 | ||
| 47 | - * @param combinationRecordId 拼团记录编号 | ||
| 48 | - * @param headId 团长编号 | ||
| 49 | - */ | ||
| 50 | - void updateOrderCombinationInfo(Long orderId, Long activityId, Long combinationRecordId, Long headId); | ||
| 51 | - | 31 | + // TODO 芋艿:需要优化下; |
| 52 | /** | 32 | /** |
| 53 | * 取消支付订单 | 33 | * 取消支付订单 |
| 54 | * | 34 | * |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
| @@ -33,7 +33,8 @@ public interface ErrorCodeConstants { | @@ -33,7 +33,8 @@ 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 | + ErrorCode ORDER_UPDATE_ADDRESS_FAIL_STATUS_NOT_DELIVERED = new ErrorCode(1_011_000_031, "交易订单修改收货地址失败,原因:订单不是【待发货】状态"); |
| 37 | + ErrorCode ORDER_CREATE_FAIL_EXIST_UNPAID = new ErrorCode(1_011_000_032, "交易订单创建失败,原因:存在未付款订单"); | ||
| 37 | 38 | ||
| 38 | // ========== After Sale 模块 1-011-000-100 ========== | 39 | // ========== After Sale 模块 1-011-000-100 ========== |
| 39 | ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在"); | 40 | 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/api/order/TradeOrderApiImpl.java
| 1 | package cn.iocoder.yudao.module.trade.api.order; | 1 | package cn.iocoder.yudao.module.trade.api.order; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; | 3 | import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; |
| 4 | -import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderSummaryRespDTO; | ||
| 5 | import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; | 4 | import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; |
| 6 | import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; | 5 | import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; |
| 7 | import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; | 6 | import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; |
| @@ -9,7 +8,6 @@ import org.springframework.stereotype.Service; | @@ -9,7 +8,6 @@ import org.springframework.stereotype.Service; | ||
| 9 | import org.springframework.validation.annotation.Validated; | 8 | import org.springframework.validation.annotation.Validated; |
| 10 | 9 | ||
| 11 | import javax.annotation.Resource; | 10 | import javax.annotation.Resource; |
| 12 | -import java.time.LocalDateTime; | ||
| 13 | import java.util.Collection; | 11 | import java.util.Collection; |
| 14 | import java.util.List; | 12 | import java.util.List; |
| 15 | 13 | ||
| @@ -23,9 +21,9 @@ import java.util.List; | @@ -23,9 +21,9 @@ import java.util.List; | ||
| 23 | public class TradeOrderApiImpl implements TradeOrderApi { | 21 | public class TradeOrderApiImpl implements TradeOrderApi { |
| 24 | 22 | ||
| 25 | @Resource | 23 | @Resource |
| 26 | - private TradeOrderQueryService tradeOrderQueryService; | ||
| 27 | - @Resource | ||
| 28 | private TradeOrderUpdateService tradeOrderUpdateService; | 24 | private TradeOrderUpdateService tradeOrderUpdateService; |
| 25 | + @Resource | ||
| 26 | + private TradeOrderQueryService tradeOrderQueryService; | ||
| 29 | 27 | ||
| 30 | @Override | 28 | @Override |
| 31 | public List<TradeOrderRespDTO> getOrderList(Collection<Long> ids) { | 29 | public List<TradeOrderRespDTO> getOrderList(Collection<Long> ids) { |
| @@ -38,16 +36,6 @@ public class TradeOrderApiImpl implements TradeOrderApi { | @@ -38,16 +36,6 @@ public class TradeOrderApiImpl implements TradeOrderApi { | ||
| 38 | } | 36 | } |
| 39 | 37 | ||
| 40 | @Override | 38 | @Override |
| 41 | - public TradeOrderSummaryRespDTO getOrderSummary(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 42 | - return tradeOrderQueryService.getOrderSummary(beginTime, endTime); | ||
| 43 | - } | ||
| 44 | - | ||
| 45 | - @Override | ||
| 46 | - public void updateOrderCombinationInfo(Long orderId, Long activityId, Long combinationRecordId, Long headId) { | ||
| 47 | - tradeOrderUpdateService.updateOrderCombinationInfo(orderId, activityId, combinationRecordId, headId); | ||
| 48 | - } | ||
| 49 | - | ||
| 50 | - @Override | ||
| 51 | public void cancelPaidOrder(Long userId, Long orderId) { | 39 | public void cancelPaidOrder(Long userId, Long orderId) { |
| 52 | tradeOrderUpdateService.cancelPaidOrder(userId, orderId); | 40 | tradeOrderUpdateService.cancelPaidOrder(userId, orderId); |
| 53 | } | 41 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleMapper.java
| 1 | package cn.iocoder.yudao.module.trade.dal.mysql.aftersale; | 1 | package cn.iocoder.yudao.module.trade.dal.mysql.aftersale; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.bean.BeanUtil; | ||
| 4 | -import cn.hutool.core.collection.CollUtil; | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageParam; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 5 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 8 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 9 | -import cn.iocoder.yudao.module.trade.api.aftersale.dto.AfterSaleSummaryRespDTO; | ||
| 10 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO; | 7 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO; |
| 11 | import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; | 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; |
| 12 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | 9 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| 13 | -import com.github.yulichang.toolkit.MPJWrappers; | ||
| 14 | import org.apache.ibatis.annotations.Mapper; | 10 | import org.apache.ibatis.annotations.Mapper; |
| 15 | 11 | ||
| 16 | -import java.time.LocalDateTime; | ||
| 17 | import java.util.Collection; | 12 | import java.util.Collection; |
| 18 | 13 | ||
| 19 | @Mapper | 14 | @Mapper |
| @@ -53,12 +48,4 @@ public interface AfterSaleMapper extends BaseMapperX<AfterSaleDO> { | @@ -53,12 +48,4 @@ public interface AfterSaleMapper extends BaseMapperX<AfterSaleDO> { | ||
| 53 | .in(AfterSaleDO::getStatus, statuses)); | 48 | .in(AfterSaleDO::getStatus, statuses)); |
| 54 | } | 49 | } |
| 55 | 50 | ||
| 56 | - default AfterSaleSummaryRespDTO selectSummaryByRefundTimeBetween(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 57 | - return BeanUtil.copyProperties(CollUtil.get(selectMaps(MPJWrappers.<AfterSaleDO>lambdaJoin() | ||
| 58 | - .selectCount(AfterSaleDO::getId, AfterSaleSummaryRespDTO::getAfterSaleCount) | ||
| 59 | - .selectSum(AfterSaleDO::getRefundPrice, AfterSaleSummaryRespDTO::getAfterSaleRefundPrice) | ||
| 60 | - .between(AfterSaleDO::getRefundTime, beginTime, endTime)), 0), | ||
| 61 | - AfterSaleSummaryRespDTO.class); | ||
| 62 | - } | ||
| 63 | - | ||
| 64 | } | 51 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/BrokerageRecordMapper.java
| 1 | package cn.iocoder.yudao.module.trade.dal.mysql.brokerage; | 1 | package cn.iocoder.yudao.module.trade.dal.mysql.brokerage; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.bean.BeanUtil; | 3 | import cn.hutool.core.bean.BeanUtil; |
| 4 | -import cn.hutool.core.collection.CollUtil; | ||
| 5 | -import cn.hutool.core.convert.Convert; | ||
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 5 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 8 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| @@ -111,13 +109,4 @@ public interface BrokerageRecordMapper extends BaseMapperX<BrokerageRecordDO> { | @@ -111,13 +109,4 @@ public interface BrokerageRecordMapper extends BaseMapperX<BrokerageRecordDO> { | ||
| 111 | @Param("beginTime") LocalDateTime beginTime, | 109 | @Param("beginTime") LocalDateTime beginTime, |
| 112 | @Param("endTime") LocalDateTime endTime); | 110 | @Param("endTime") LocalDateTime endTime); |
| 113 | 111 | ||
| 114 | - default Integer selectSummaryPriceByStatusAndUnfreezeTimeBetween(Integer bizType, Integer status, | ||
| 115 | - LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 116 | - return Convert.toInt(CollUtil.getFirst(selectObjs(MPJWrappers.<BrokerageRecordDO>lambdaJoin() | ||
| 117 | - .selectSum(BrokerageRecordDO::getPrice) | ||
| 118 | - .eq(BrokerageRecordDO::getBizType, bizType) | ||
| 119 | - .eq(BrokerageRecordDO::getStatus, status) | ||
| 120 | - .between(BrokerageRecordDO::getUnfreezeTime, beginTime, endTime))), 0); | ||
| 121 | - } | ||
| 122 | - | ||
| 123 | } | 112 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java
| 1 | package cn.iocoder.yudao.module.trade.dal.mysql.order; | 1 | package cn.iocoder.yudao.module.trade.dal.mysql.order; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.bean.BeanUtil; | ||
| 4 | -import cn.hutool.core.collection.CollUtil; | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 7 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 8 | -import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderSummaryRespDTO; | ||
| 9 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; | 6 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; |
| 10 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; | 7 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; |
| 11 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; |
| 12 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | 9 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| 13 | -import com.github.yulichang.toolkit.MPJWrappers; | ||
| 14 | import org.apache.ibatis.annotations.Mapper; | 10 | import org.apache.ibatis.annotations.Mapper; |
| 15 | 11 | ||
| 16 | import java.time.LocalDateTime; | 12 | import java.time.LocalDateTime; |
| @@ -93,21 +89,21 @@ public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> { | @@ -93,21 +89,21 @@ public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> { | ||
| 93 | .eq(TradeOrderDO::getSeckillActivityId, seckillActivityId)); | 89 | .eq(TradeOrderDO::getSeckillActivityId, seckillActivityId)); |
| 94 | } | 90 | } |
| 95 | 91 | ||
| 96 | - default TradeOrderSummaryRespDTO selectSummaryByPayTimeBetween(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 97 | - return BeanUtil.copyProperties(CollUtil.get(selectMaps(MPJWrappers.<TradeOrderDO>lambdaJoin() | ||
| 98 | - .selectCount(TradeOrderDO::getId, TradeOrderSummaryRespDTO::getOrderPayCount) | ||
| 99 | - .selectSum(TradeOrderDO::getPayPrice, TradeOrderSummaryRespDTO::getOrderPayPrice) | ||
| 100 | - .between(TradeOrderDO::getPayTime, beginTime, endTime)), 0), | ||
| 101 | - TradeOrderSummaryRespDTO.class); | ||
| 102 | - } | ||
| 103 | - | ||
| 104 | - default Long selectCountByCreateTimeBetween(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 105 | - return selectCount(new LambdaQueryWrapperX<TradeOrderDO>() | ||
| 106 | - .between(TradeOrderDO::getCreateTime, beginTime, endTime)); | ||
| 107 | - } | ||
| 108 | - | ||
| 109 | default TradeOrderDO selectOneByPickUpVerifyCode(String pickUpVerifyCode) { | 92 | default TradeOrderDO selectOneByPickUpVerifyCode(String pickUpVerifyCode) { |
| 110 | return selectOne(TradeOrderDO::getPickUpVerifyCode, pickUpVerifyCode); | 93 | return selectOne(TradeOrderDO::getPickUpVerifyCode, pickUpVerifyCode); |
| 111 | } | 94 | } |
| 112 | 95 | ||
| 96 | + // TODO @hui999:是不是只针对 combinationActivityId 的查询呀? | ||
| 97 | + default TradeOrderDO selectByUserIdAndActivityIdAndStatus(Long userId, Long activityId, Integer status) { | ||
| 98 | + return selectOne(new LambdaQueryWrapperX<TradeOrderDO>() | ||
| 99 | + .and(q -> q.eq(TradeOrderDO::getUserId, userId) | ||
| 100 | + .eq(TradeOrderDO::getStatus, status)) | ||
| 101 | + .and(q -> q.eq(TradeOrderDO::getCombinationActivityId, activityId) | ||
| 102 | + .or() | ||
| 103 | + .eq(TradeOrderDO::getSeckillActivityId, activityId) | ||
| 104 | + .or() | ||
| 105 | + .eq(TradeOrderDO::getBargainActivityId, activityId)) | ||
| 106 | + ); | ||
| 107 | + } | ||
| 108 | + | ||
| 113 | } | 109 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleService.java
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.trade.service.aftersale; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.trade.service.aftersale; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | -import cn.iocoder.yudao.module.trade.api.aftersale.dto.AfterSaleSummaryRespDTO; | ||
| 6 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleDisagreeReqVO; | 5 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleDisagreeReqVO; |
| 7 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO; | 6 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO; |
| 8 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleRefuseReqVO; | 7 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleRefuseReqVO; |
| @@ -10,8 +9,6 @@ import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleCre | @@ -10,8 +9,6 @@ import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleCre | ||
| 10 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleDeliveryReqVO; | 9 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleDeliveryReqVO; |
| 11 | import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; | 10 | import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; |
| 12 | 11 | ||
| 13 | -import java.time.LocalDateTime; | ||
| 14 | - | ||
| 15 | /** | 12 | /** |
| 16 | * 售后订单 Service 接口 | 13 | * 售后订单 Service 接口 |
| 17 | * | 14 | * |
| @@ -127,13 +124,4 @@ public interface AfterSaleService { | @@ -127,13 +124,4 @@ public interface AfterSaleService { | ||
| 127 | */ | 124 | */ |
| 128 | Long getApplyingAfterSaleCount(Long userId); | 125 | Long getApplyingAfterSaleCount(Long userId); |
| 129 | 126 | ||
| 130 | - /** | ||
| 131 | - * 获取售后单统计 | ||
| 132 | - * | ||
| 133 | - * @param beginTime 起始时间 | ||
| 134 | - * @param endTime 截止时间 | ||
| 135 | - * @return 售后统计结果 | ||
| 136 | - */ | ||
| 137 | - AfterSaleSummaryRespDTO getAfterSaleSummary(LocalDateTime beginTime, LocalDateTime endTime); | ||
| 138 | - | ||
| 139 | } | 127 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java
| @@ -7,7 +7,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | @@ -7,7 +7,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 7 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | 7 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; |
| 8 | import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; | 8 | import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; |
| 9 | import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; | 9 | import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; |
| 10 | -import cn.iocoder.yudao.module.trade.api.aftersale.dto.AfterSaleSummaryRespDTO; | ||
| 11 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleDisagreeReqVO; | 10 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleDisagreeReqVO; |
| 12 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO; | 11 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO; |
| 13 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleRefuseReqVO; | 12 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleRefuseReqVO; |
| @@ -411,9 +410,4 @@ public class AfterSaleServiceImpl implements AfterSaleService { | @@ -411,9 +410,4 @@ public class AfterSaleServiceImpl implements AfterSaleService { | ||
| 411 | return tradeAfterSaleMapper.selectCountByUserIdAndStatus(userId, AfterSaleStatusEnum.APPLYING_STATUSES); | 410 | return tradeAfterSaleMapper.selectCountByUserIdAndStatus(userId, AfterSaleStatusEnum.APPLYING_STATUSES); |
| 412 | } | 411 | } |
| 413 | 412 | ||
| 414 | - @Override | ||
| 415 | - public AfterSaleSummaryRespDTO getAfterSaleSummary(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 416 | - return tradeAfterSaleMapper.selectSummaryByRefundTimeBetween(beginTime,endTime); | ||
| 417 | - } | ||
| 418 | - | ||
| 419 | } | 413 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordService.java
| @@ -156,13 +156,4 @@ public interface BrokerageRecordService { | @@ -156,13 +156,4 @@ public interface BrokerageRecordService { | ||
| 156 | */ | 156 | */ |
| 157 | AppBrokerageProductPriceRespVO calculateProductBrokeragePrice(Long userId, Long spuId); | 157 | AppBrokerageProductPriceRespVO calculateProductBrokeragePrice(Long userId, Long spuId); |
| 158 | 158 | ||
| 159 | - /** | ||
| 160 | - * 获取已结算的佣金金额 | ||
| 161 | - * | ||
| 162 | - * @param beginTime 起始时间 | ||
| 163 | - * @param endTime 截止时间 | ||
| 164 | - * @return 已结算的佣金金额 | ||
| 165 | - */ | ||
| 166 | - Integer getBrokerageSettlementPriceSummary(LocalDateTime beginTime, LocalDateTime endTime); | ||
| 167 | - | ||
| 168 | } | 159 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageRecordServiceImpl.java
| @@ -356,13 +356,6 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { | @@ -356,13 +356,6 @@ public class BrokerageRecordServiceImpl implements BrokerageRecordService { | ||
| 356 | return respVO; | 356 | return respVO; |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | - @Override | ||
| 360 | - public Integer getBrokerageSettlementPriceSummary(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 361 | - return brokerageRecordMapper.selectSummaryPriceByStatusAndUnfreezeTimeBetween( | ||
| 362 | - BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus(), | ||
| 363 | - beginTime, endTime); | ||
| 364 | - } | ||
| 365 | - | ||
| 366 | /** | 359 | /** |
| 367 | * 获得自身的代理对象,解决 AOP 生效问题 | 360 | * 获得自身的代理对象,解决 AOP 生效问题 |
| 368 | * | 361 | * |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java
| 1 | package cn.iocoder.yudao.module.trade.service.order; | 1 | package cn.iocoder.yudao.module.trade.service.order; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | -import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderSummaryRespDTO; | ||
| 5 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; | 4 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; |
| 6 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; | 5 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; |
| 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | 6 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; |
| 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; |
| 9 | import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO; | 8 | import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO; |
| 10 | 9 | ||
| 11 | -import java.time.LocalDateTime; | ||
| 12 | import java.util.Collection; | 10 | import java.util.Collection; |
| 13 | import java.util.List; | 11 | import java.util.List; |
| 14 | 12 | ||
| @@ -41,6 +39,16 @@ public interface TradeOrderQueryService { | @@ -41,6 +39,16 @@ public interface TradeOrderQueryService { | ||
| 41 | TradeOrderDO getOrder(Long userId, Long id); | 39 | TradeOrderDO getOrder(Long userId, Long id); |
| 42 | 40 | ||
| 43 | /** | 41 | /** |
| 42 | + * 获得指定用户,指定活动,指定状态的交易订单 | ||
| 43 | + * | ||
| 44 | + * @param userId 用户编号 | ||
| 45 | + * @param activityId 活动编号 | ||
| 46 | + * @param status 订单状态 | ||
| 47 | + * @return 交易订单 | ||
| 48 | + */ | ||
| 49 | + TradeOrderDO getActivityOrderByUserIdAndActivityIdAndStatus(Long userId, Long activityId, Integer status); | ||
| 50 | + | ||
| 51 | + /** | ||
| 44 | * 获得订单列表 | 52 | * 获得订单列表 |
| 45 | * | 53 | * |
| 46 | * @param ids 订单编号数组 | 54 | * @param ids 订单编号数组 |
| @@ -95,7 +103,7 @@ public interface TradeOrderQueryService { | @@ -95,7 +103,7 @@ public interface TradeOrderQueryService { | ||
| 95 | /** | 103 | /** |
| 96 | * 【会员】在指定秒杀活动下,用户购买的商品数量 | 104 | * 【会员】在指定秒杀活动下,用户购买的商品数量 |
| 97 | * | 105 | * |
| 98 | - * @param userId 用户编号 | 106 | + * @param userId 用户编号 |
| 99 | * @param activityId 活动编号 | 107 | * @param activityId 活动编号 |
| 100 | * @return 秒杀商品数量 | 108 | * @return 秒杀商品数量 |
| 101 | */ | 109 | */ |
| @@ -138,13 +146,4 @@ public interface TradeOrderQueryService { | @@ -138,13 +146,4 @@ public interface TradeOrderQueryService { | ||
| 138 | */ | 146 | */ |
| 139 | List<TradeOrderItemDO> getOrderItemListByOrderId(Collection<Long> orderIds); | 147 | List<TradeOrderItemDO> getOrderItemListByOrderId(Collection<Long> orderIds); |
| 140 | 148 | ||
| 141 | - /** | ||
| 142 | - * 获取订单统计 | ||
| 143 | - * | ||
| 144 | - * @param beginTime 起始时间 | ||
| 145 | - * @param endTime 截止时间 | ||
| 146 | - * @return 订单统计结果 | ||
| 147 | - */ | ||
| 148 | - TradeOrderSummaryRespDTO getOrderSummary(LocalDateTime beginTime, LocalDateTime endTime); | ||
| 149 | - | ||
| 150 | } | 149 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java
| @@ -7,7 +7,6 @@ import cn.hutool.extra.spring.SpringUtil; | @@ -7,7 +7,6 @@ import cn.hutool.extra.spring.SpringUtil; | ||
| 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 8 | import cn.iocoder.yudao.module.member.api.user.MemberUserApi; | 8 | import cn.iocoder.yudao.module.member.api.user.MemberUserApi; |
| 9 | import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; | 9 | import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; |
| 10 | -import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderSummaryRespDTO; | ||
| 11 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; | 10 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; |
| 12 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; | 11 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; |
| 13 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; | 12 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; |
| @@ -25,7 +24,6 @@ import org.springframework.cache.annotation.Cacheable; | @@ -25,7 +24,6 @@ import org.springframework.cache.annotation.Cacheable; | ||
| 25 | import org.springframework.stereotype.Service; | 24 | import org.springframework.stereotype.Service; |
| 26 | 25 | ||
| 27 | import javax.annotation.Resource; | 26 | import javax.annotation.Resource; |
| 28 | -import java.time.LocalDateTime; | ||
| 29 | import java.util.*; | 27 | import java.util.*; |
| 30 | 28 | ||
| 31 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 29 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| @@ -73,6 +71,11 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { | @@ -73,6 +71,11 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { | ||
| 73 | } | 71 | } |
| 74 | 72 | ||
| 75 | @Override | 73 | @Override |
| 74 | + public TradeOrderDO getActivityOrderByUserIdAndActivityIdAndStatus(Long userId, Long activityId, Integer status) { | ||
| 75 | + return tradeOrderMapper.selectByUserIdAndActivityIdAndStatus(userId, activityId, status); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + @Override | ||
| 76 | public List<TradeOrderDO> getOrderList(Collection<Long> ids) { | 79 | public List<TradeOrderDO> getOrderList(Collection<Long> ids) { |
| 77 | if (CollUtil.isEmpty(ids)) { | 80 | if (CollUtil.isEmpty(ids)) { |
| 78 | return Collections.emptyList(); | 81 | return Collections.emptyList(); |
| @@ -183,13 +186,6 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { | @@ -183,13 +186,6 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { | ||
| 183 | .setPhone(receiverMobile)); | 186 | .setPhone(receiverMobile)); |
| 184 | } | 187 | } |
| 185 | 188 | ||
| 186 | - @Override | ||
| 187 | - public TradeOrderSummaryRespDTO getOrderSummary(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 188 | - TradeOrderSummaryRespDTO dto = tradeOrderMapper.selectSummaryByPayTimeBetween(beginTime, endTime); | ||
| 189 | - dto.setOrderCreateCount(tradeOrderMapper.selectCountByCreateTimeBetween(beginTime, endTime)); | ||
| 190 | - return dto; | ||
| 191 | - } | ||
| 192 | - | ||
| 193 | 189 | ||
| 194 | // =================== Order Item =================== | 190 | // =================== Order Item =================== |
| 195 | 191 |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
| @@ -14,23 +14,12 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | @@ -14,23 +14,12 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 14 | import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; | 14 | import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; |
| 15 | import cn.iocoder.yudao.module.member.api.address.AddressApi; | 15 | import cn.iocoder.yudao.module.member.api.address.AddressApi; |
| 16 | import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; | 16 | import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; |
| 17 | -import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; | ||
| 18 | -import cn.iocoder.yudao.module.member.api.point.MemberPointApi; | ||
| 19 | -import cn.iocoder.yudao.module.member.api.user.MemberUserApi; | ||
| 20 | -import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; | ||
| 21 | -import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; | ||
| 22 | -import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; | ||
| 23 | import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; | 17 | import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; |
| 24 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; | 18 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; |
| 25 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; | 19 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; |
| 26 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; | 20 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; |
| 27 | import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi; | 21 | import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi; |
| 28 | import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; | 22 | import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; |
| 29 | -import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | ||
| 30 | -import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; | ||
| 31 | -import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; | ||
| 32 | -import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; | ||
| 33 | -import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; | ||
| 34 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; | 23 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; |
| 35 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO; | 24 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO; |
| 36 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO; | 25 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO; |
| @@ -40,7 +29,6 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettle | @@ -40,7 +29,6 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettle | ||
| 40 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; | 29 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; |
| 41 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; | 30 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; |
| 42 | import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; | 31 | import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; |
| 43 | -import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO; | ||
| 44 | import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO; | 32 | import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO; |
| 45 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; | 33 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; |
| 46 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | 34 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; |
| @@ -48,15 +36,11 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | @@ -48,15 +36,11 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | ||
| 48 | import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; | 36 | import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; |
| 49 | import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; | 37 | import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; |
| 50 | import cn.iocoder.yudao.module.trade.dal.redis.no.TradeNoRedisDAO; | 38 | import cn.iocoder.yudao.module.trade.dal.redis.no.TradeNoRedisDAO; |
| 51 | -import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; | ||
| 52 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; | 39 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; |
| 53 | import cn.iocoder.yudao.module.trade.enums.order.*; | 40 | import cn.iocoder.yudao.module.trade.enums.order.*; |
| 54 | import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; | 41 | import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; |
| 55 | import cn.iocoder.yudao.module.trade.framework.order.core.annotations.TradeOrderLog; | 42 | import cn.iocoder.yudao.module.trade.framework.order.core.annotations.TradeOrderLog; |
| 56 | import cn.iocoder.yudao.module.trade.framework.order.core.utils.TradeOrderLogUtils; | 43 | import cn.iocoder.yudao.module.trade.framework.order.core.utils.TradeOrderLogUtils; |
| 57 | -import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService; | ||
| 58 | -import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService; | ||
| 59 | -import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; | ||
| 60 | import cn.iocoder.yudao.module.trade.service.cart.CartService; | 44 | import cn.iocoder.yudao.module.trade.service.cart.CartService; |
| 61 | import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; | 45 | import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; |
| 62 | import cn.iocoder.yudao.module.trade.service.message.TradeMessageService; | 46 | import cn.iocoder.yudao.module.trade.service.message.TradeMessageService; |
| @@ -68,13 +52,15 @@ import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | @@ -68,13 +52,15 @@ import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | ||
| 68 | import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper; | 52 | import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper; |
| 69 | import lombok.extern.slf4j.Slf4j; | 53 | import lombok.extern.slf4j.Slf4j; |
| 70 | import org.jetbrains.annotations.NotNull; | 54 | import org.jetbrains.annotations.NotNull; |
| 71 | -import org.springframework.scheduling.annotation.Async; | ||
| 72 | import org.springframework.stereotype.Service; | 55 | import org.springframework.stereotype.Service; |
| 73 | import org.springframework.transaction.annotation.Transactional; | 56 | import org.springframework.transaction.annotation.Transactional; |
| 74 | 57 | ||
| 75 | import javax.annotation.Resource; | 58 | import javax.annotation.Resource; |
| 76 | import java.time.LocalDateTime; | 59 | import java.time.LocalDateTime; |
| 77 | -import java.util.*; | 60 | +import java.util.ArrayList; |
| 61 | +import java.util.List; | ||
| 62 | +import java.util.Objects; | ||
| 63 | +import java.util.Set; | ||
| 78 | 64 | ||
| 79 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 65 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 80 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | 66 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; |
| @@ -109,30 +95,12 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -109,30 +95,12 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 109 | private DeliveryExpressService deliveryExpressService; | 95 | private DeliveryExpressService deliveryExpressService; |
| 110 | @Resource | 96 | @Resource |
| 111 | private TradeMessageService tradeMessageService; | 97 | private TradeMessageService tradeMessageService; |
| 112 | - @Resource | ||
| 113 | - private BrokerageUserService brokerageUserService; | ||
| 114 | - @Resource | ||
| 115 | - private BrokerageRecordService brokerageRecordService; | ||
| 116 | 98 | ||
| 117 | @Resource | 99 | @Resource |
| 118 | - private ProductSpuApi productSpuApi; | ||
| 119 | - @Resource | ||
| 120 | - private ProductSkuApi productSkuApi; | ||
| 121 | - @Resource | ||
| 122 | private PayOrderApi payOrderApi; | 100 | private PayOrderApi payOrderApi; |
| 123 | @Resource | 101 | @Resource |
| 124 | private AddressApi addressApi; | 102 | private AddressApi addressApi; |
| 125 | @Resource | 103 | @Resource |
| 126 | - private CouponApi couponApi; | ||
| 127 | - @Resource | ||
| 128 | - private CombinationRecordApi combinationRecordApi; | ||
| 129 | - @Resource | ||
| 130 | - private MemberUserApi memberUserApi; | ||
| 131 | - @Resource | ||
| 132 | - private MemberLevelApi memberLevelApi; | ||
| 133 | - @Resource | ||
| 134 | - private MemberPointApi memberPointApi; | ||
| 135 | - @Resource | ||
| 136 | private ProductCommentApi productCommentApi; | 104 | private ProductCommentApi productCommentApi; |
| 137 | 105 | ||
| 138 | @Resource | 106 | @Resource |
| @@ -199,7 +167,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -199,7 +167,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 199 | List<TradeOrderItemDO> orderItems = buildTradeOrderItems(order, calculateRespBO); | 167 | List<TradeOrderItemDO> orderItems = buildTradeOrderItems(order, calculateRespBO); |
| 200 | 168 | ||
| 201 | // 2. 订单创建前的逻辑 | 169 | // 2. 订单创建前的逻辑 |
| 202 | - beforeCreateTradeOrder(order, orderItems); | 170 | + tradeOrderHandlers.forEach(handler -> handler.beforeOrderCreate(order, orderItems)); |
| 203 | 171 | ||
| 204 | // 3. 保存订单 | 172 | // 3. 保存订单 |
| 205 | tradeOrderMapper.insert(order); | 173 | tradeOrderMapper.insert(order); |
| @@ -234,11 +202,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -234,11 +202,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 234 | order.setReceiverName(createReqVO.getReceiverName()).setReceiverMobile(createReqVO.getReceiverMobile()); | 202 | order.setReceiverName(createReqVO.getReceiverName()).setReceiverMobile(createReqVO.getReceiverMobile()); |
| 235 | order.setPickUpVerifyCode(RandomUtil.randomNumbers(8)); // 随机一个核销码,长度为 8 位 | 203 | order.setPickUpVerifyCode(RandomUtil.randomNumbers(8)); // 随机一个核销码,长度为 8 位 |
| 236 | } | 204 | } |
| 237 | - // 设置订单推广人 | ||
| 238 | - BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(order.getUserId()); | ||
| 239 | - if (brokerageUser != null && brokerageUser.getBindUserId() != null) { | ||
| 240 | - order.setBrokerageUserId(brokerageUser.getBindUserId()); | ||
| 241 | - } | ||
| 242 | return order; | 205 | return order; |
| 243 | } | 206 | } |
| 244 | 207 | ||
| @@ -248,21 +211,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -248,21 +211,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 248 | } | 211 | } |
| 249 | 212 | ||
| 250 | /** | 213 | /** |
| 251 | - * 订单创建前,执行前置逻辑 | ||
| 252 | - * | ||
| 253 | - * @param order 订单 | ||
| 254 | - * @param orderItems 订单项 | ||
| 255 | - */ | ||
| 256 | - private void beforeCreateTradeOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | ||
| 257 | - // 1. 执行订单创建前置处理器 | ||
| 258 | - // TODO @puhui999:这里有个纠结点;handler 的定义是只处理指定类型的订单的拓展逻辑;还是通用的 handler,类似可以处理优惠劵等等 | ||
| 259 | - tradeOrderHandlers.forEach(handler -> handler.beforeOrderCreate(order, orderItems)); | ||
| 260 | - | ||
| 261 | - // 2. 下单时扣减商品库存 | ||
| 262 | - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(orderItems)); | ||
| 263 | - } | ||
| 264 | - | ||
| 265 | - /** | ||
| 266 | * 订单创建后,执行后置逻辑 | 214 | * 订单创建后,执行后置逻辑 |
| 267 | * <p> | 215 | * <p> |
| 268 | * 例如说:优惠劵的扣减、积分的扣减、支付单的创建等等 | 216 | * 例如说:优惠劵的扣减、积分的扣减、支付单的创建等等 |
| @@ -276,27 +224,16 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -276,27 +224,16 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 276 | // 1. 执行订单创建后置处理器 | 224 | // 1. 执行订单创建后置处理器 |
| 277 | tradeOrderHandlers.forEach(handler -> handler.afterOrderCreate(order, orderItems)); | 225 | tradeOrderHandlers.forEach(handler -> handler.afterOrderCreate(order, orderItems)); |
| 278 | 226 | ||
| 279 | - // 2. 有使用优惠券时更新 | ||
| 280 | - // 不在前置扣减的原因,是因为优惠劵要记录使用的订单号 | ||
| 281 | - if (order.getCouponId() != null) { | ||
| 282 | - couponApi.useCoupon(new CouponUseReqDTO().setId(order.getCouponId()).setUserId(order.getUserId()) | ||
| 283 | - .setOrderId(order.getId())); | ||
| 284 | - } | ||
| 285 | - | ||
| 286 | - // 3. 扣减积分(抵扣) | ||
| 287 | - // 不在前置扣减的原因,是因为积分扣减时,需要记录关联业务 | ||
| 288 | - reduceUserPoint(order.getUserId(), order.getUsePoint(), MemberPointBizTypeEnum.ORDER_USE, order.getId()); | ||
| 289 | - | ||
| 290 | - // 4. 删除购物车商品 | 227 | + // 2. 删除购物车商品 |
| 291 | Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId); | 228 | Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId); |
| 292 | if (CollUtil.isNotEmpty(cartIds)) { | 229 | if (CollUtil.isNotEmpty(cartIds)) { |
| 293 | cartService.deleteCart(order.getUserId(), cartIds); | 230 | cartService.deleteCart(order.getUserId(), cartIds); |
| 294 | } | 231 | } |
| 295 | 232 | ||
| 296 | - // 5. 生成预支付 | 233 | + // 3. 生成预支付 |
| 297 | createPayOrder(order, orderItems); | 234 | createPayOrder(order, orderItems); |
| 298 | 235 | ||
| 299 | - // 6. 插入订单日志 | 236 | + // 4. 插入订单日志 |
| 300 | TradeOrderLogUtils.setOrderInfo(order.getId(), null, order.getStatus()); | 237 | TradeOrderLogUtils.setOrderInfo(order.getId(), null, order.getStatus()); |
| 301 | 238 | ||
| 302 | // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来! | 239 | // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来! |
| @@ -330,18 +267,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -330,18 +267,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 330 | throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); | 267 | throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); |
| 331 | } | 268 | } |
| 332 | 269 | ||
| 333 | - // 3、订单支付成功后 | 270 | + // 3. 执行 TradeOrderHandler 的后置处理 |
| 334 | List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id); | 271 | List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id); |
| 335 | tradeOrderHandlers.forEach(handler -> handler.afterPayOrder(order, orderItems)); | 272 | tradeOrderHandlers.forEach(handler -> handler.afterPayOrder(order, orderItems)); |
| 336 | 273 | ||
| 337 | - // 4.1 增加用户积分(赠送) | ||
| 338 | - addUserPoint(order.getUserId(), order.getGivePoint(), MemberPointBizTypeEnum.ORDER_GIVE, order.getId()); | ||
| 339 | - // 4.2 增加用户经验 | ||
| 340 | - getSelf().addUserExperienceAsync(order.getUserId(), order.getPayPrice(), order.getId()); | ||
| 341 | - // 4.3 增加用户佣金 | ||
| 342 | - getSelf().addBrokerageAsync(order.getUserId(), order.getId()); | ||
| 343 | - | ||
| 344 | - // 5. 记录订单日志 | 274 | + // 4. 记录订单日志 |
| 345 | TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus()); | 275 | TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus()); |
| 346 | TradeOrderLogUtils.setUserInfo(order.getUserId(), UserTypeEnum.MEMBER.getValue()); | 276 | TradeOrderLogUtils.setUserInfo(order.getUserId(), UserTypeEnum.MEMBER.getValue()); |
| 347 | } | 277 | } |
| @@ -434,8 +364,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -434,8 +364,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 434 | .put("logisticsNo", express != null ? deliveryReqVO.getLogisticsNo() : "").build()); | 364 | .put("logisticsNo", express != null ? deliveryReqVO.getLogisticsNo() : "").build()); |
| 435 | 365 | ||
| 436 | // 4. 发送站内信 | 366 | // 4. 发送站内信 |
| 437 | - tradeMessageService.sendMessageWhenDeliveryOrder(new TradeOrderMessageWhenDeliveryOrderReqBO().setOrderId(order.getId()) | ||
| 438 | - .setUserId(order.getUserId()).setMessage(null)); | 367 | + tradeMessageService.sendMessageWhenDeliveryOrder(new TradeOrderMessageWhenDeliveryOrderReqBO() |
| 368 | + .setOrderId(order.getId()).setUserId(order.getUserId()).setMessage(null)); | ||
| 439 | } | 369 | } |
| 440 | 370 | ||
| 441 | /** | 371 | /** |
| @@ -448,18 +378,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -448,18 +378,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 448 | */ | 378 | */ |
| 449 | private TradeOrderDO validateOrderDeliverable(Long id) { | 379 | private TradeOrderDO validateOrderDeliverable(Long id) { |
| 450 | TradeOrderDO order = validateOrderExists(id); | 380 | TradeOrderDO order = validateOrderExists(id); |
| 451 | - // 校验订单是否退款 | 381 | + // 1. 校验订单是否未发货 |
| 452 | if (ObjectUtil.notEqual(TradeOrderRefundStatusEnum.NONE.getStatus(), order.getRefundStatus())) { | 382 | if (ObjectUtil.notEqual(TradeOrderRefundStatusEnum.NONE.getStatus(), order.getRefundStatus())) { |
| 453 | throw exception(ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE); | 383 | throw exception(ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE); |
| 454 | } | 384 | } |
| 455 | - // 订单类型:拼团 | ||
| 456 | - if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { | ||
| 457 | - // 校验订单拼团是否成功 | ||
| 458 | - if (!combinationRecordApi.isCombinationRecordSuccess(order.getUserId(), order.getId())) { | ||
| 459 | - throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS); | ||
| 460 | - } | ||
| 461 | - } | ||
| 462 | 385 | ||
| 386 | + // 2. 执行 TradeOrderHandler 前置处理 | ||
| 387 | + tradeOrderHandlers.forEach(handler -> handler.beforeDeliveryOrder(order)); | ||
| 463 | return order; | 388 | return order; |
| 464 | } | 389 | } |
| 465 | 390 | ||
| @@ -616,30 +541,19 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -616,30 +541,19 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 616 | * @param cancelType 取消类型 | 541 | * @param cancelType 取消类型 |
| 617 | */ | 542 | */ |
| 618 | private void cancelOrder0(TradeOrderDO order, TradeOrderCancelTypeEnum cancelType) { | 543 | private void cancelOrder0(TradeOrderDO order, TradeOrderCancelTypeEnum cancelType) { |
| 619 | - Long id = order.getId(); | ||
| 620 | // 1. 更新 TradeOrderDO 状态为已取消 | 544 | // 1. 更新 TradeOrderDO 状态为已取消 |
| 621 | - int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(), | 545 | + int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), |
| 622 | new TradeOrderDO().setStatus(TradeOrderStatusEnum.CANCELED.getStatus()) | 546 | new TradeOrderDO().setStatus(TradeOrderStatusEnum.CANCELED.getStatus()) |
| 623 | .setCancelType(cancelType.getType()).setCancelTime(LocalDateTime.now())); | 547 | .setCancelType(cancelType.getType()).setCancelTime(LocalDateTime.now())); |
| 624 | if (updateCount == 0) { | 548 | if (updateCount == 0) { |
| 625 | throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); | 549 | throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); |
| 626 | } | 550 | } |
| 627 | 551 | ||
| 628 | - List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id); | ||
| 629 | - // 3. 回滚库存 | ||
| 630 | - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); | ||
| 631 | - // 3.1、 活动相关的回滚 | ||
| 632 | - tradeOrderHandlers.forEach(handler -> handler.cancelOrder(order, orderItems)); | ||
| 633 | - | ||
| 634 | - // 4. 回滚优惠券 | ||
| 635 | - if (order.getCouponId() != null && order.getCouponId() > 0) { | ||
| 636 | - couponApi.returnUsedCoupon(order.getCouponId()); | ||
| 637 | - } | ||
| 638 | - | ||
| 639 | - // 5. 回滚积分(抵扣的) | ||
| 640 | - addUserPoint(order.getUserId(), order.getUsePoint(), MemberPointBizTypeEnum.ORDER_CANCEL, order.getId()); | 552 | + // 2. 执行 TradeOrderHandler 的后置处理 |
| 553 | + List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(order.getId()); | ||
| 554 | + tradeOrderHandlers.forEach(handler -> handler.afterCancelOrder(order, orderItems)); | ||
| 641 | 555 | ||
| 642 | - // 6. 增加订单日志 | 556 | + // 3. 增加订单日志 |
| 643 | TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus()); | 557 | TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus()); |
| 644 | } | 558 | } |
| 645 | 559 | ||
| @@ -660,8 +574,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -660,8 +574,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 660 | .setStatus(TradeOrderStatusEnum.CANCELED.getStatus()) | 574 | .setStatus(TradeOrderStatusEnum.CANCELED.getStatus()) |
| 661 | .setCancelType(TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE.getType()).setCancelTime(LocalDateTime.now())); | 575 | .setCancelType(TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE.getType()).setCancelTime(LocalDateTime.now())); |
| 662 | 576 | ||
| 663 | - // 2. 退还优惠券 | ||
| 664 | - couponApi.returnUsedCoupon(order.getCouponId()); | 577 | + // 2. 执行 TradeOrderHandler 的后置处理 |
| 578 | + List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(order.getId()); | ||
| 579 | + tradeOrderHandlers.forEach(handler -> handler.afterCancelOrder(order, orderItems)); | ||
| 665 | } | 580 | } |
| 666 | 581 | ||
| 667 | @Override | 582 | @Override |
| @@ -742,9 +657,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -742,9 +657,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 742 | public void updateOrderAddress(TradeOrderUpdateAddressReqVO reqVO) { | 657 | public void updateOrderAddress(TradeOrderUpdateAddressReqVO reqVO) { |
| 743 | // 校验交易订单 | 658 | // 校验交易订单 |
| 744 | TradeOrderDO order = validateOrderExists(reqVO.getId()); | 659 | TradeOrderDO order = validateOrderExists(reqVO.getId()); |
| 745 | - // 发货后,不允许修改; | ||
| 746 | - // TODO @puhui999:只有待发货,可以执行 update | ||
| 747 | - if (TradeOrderStatusEnum.isDelivered(order.getStatus())) { | 660 | + // 只有待发货状态,才可以修改订单收货地址; |
| 661 | + if (!TradeOrderStatusEnum.isUndelivered(order.getStatus())) { | ||
| 748 | throw exception(ORDER_UPDATE_ADDRESS_FAIL_STATUS_NOT_DELIVERED); | 662 | throw exception(ORDER_UPDATE_ADDRESS_FAIL_STATUS_NOT_DELIVERED); |
| 749 | } | 663 | } |
| 750 | 664 | ||
| @@ -790,13 +704,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -790,13 +704,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 790 | @Override | 704 | @Override |
| 791 | @Transactional(rollbackFor = Exception.class) | 705 | @Transactional(rollbackFor = Exception.class) |
| 792 | public void updateOrderItemWhenAfterSaleSuccess(Long id, Integer refundPrice) { | 706 | public void updateOrderItemWhenAfterSaleSuccess(Long id, Integer refundPrice) { |
| 793 | - // 1. 更新订单项 | 707 | + // 1.1 更新订单项 |
| 794 | updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), | 708 | updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), |
| 795 | TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus(), null); | 709 | TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus(), null); |
| 796 | - | ||
| 797 | - // 2.1 更新订单的退款金额、积分 | 710 | + // 1.2 执行 TradeOrderHandler 的后置处理 |
| 798 | TradeOrderItemDO orderItem = tradeOrderItemMapper.selectById(id); | 711 | TradeOrderItemDO orderItem = tradeOrderItemMapper.selectById(id); |
| 799 | TradeOrderDO order = tradeOrderMapper.selectById(orderItem.getOrderId()); | 712 | TradeOrderDO order = tradeOrderMapper.selectById(orderItem.getOrderId()); |
| 713 | + tradeOrderHandlers.forEach(handler -> handler.afterCancelOrderItem(order, orderItem)); | ||
| 714 | + | ||
| 715 | + // 2.1 更新订单的退款金额、积分 | ||
| 800 | Integer orderRefundPrice = order.getRefundPrice() + refundPrice; | 716 | Integer orderRefundPrice = order.getRefundPrice() + refundPrice; |
| 801 | Integer orderRefundPoint = order.getRefundPoint() + orderItem.getUsePoint(); | 717 | Integer orderRefundPoint = order.getRefundPoint() + orderItem.getUsePoint(); |
| 802 | Integer refundStatus = isAllOrderItemAfterSaleSuccess(order.getId()) ? | 718 | Integer refundStatus = isAllOrderItemAfterSaleSuccess(order.getId()) ? |
| @@ -807,23 +723,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -807,23 +723,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 807 | .setRefundPrice(orderRefundPrice).setRefundPoint(orderRefundPoint)); | 723 | .setRefundPrice(orderRefundPrice).setRefundPoint(orderRefundPoint)); |
| 808 | // 2.2 如果全部退款,则进行取消订单 | 724 | // 2.2 如果全部退款,则进行取消订单 |
| 809 | getSelf().cancelOrderByAfterSale(order, orderRefundPrice); | 725 | getSelf().cancelOrderByAfterSale(order, orderRefundPrice); |
| 810 | - | ||
| 811 | - | ||
| 812 | - // 3. 回滚库存 | ||
| 813 | - productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(Collections.singletonList(orderItem))); | ||
| 814 | - // 3.1、 活动相关的回滚 | ||
| 815 | - tradeOrderHandlers.forEach(handler -> handler.cancelOrder(order, Collections.singletonList(orderItem))); | ||
| 816 | - | ||
| 817 | - // 4.1 回滚积分:扣减用户积分(赠送的) | ||
| 818 | - reduceUserPoint(order.getUserId(), orderItem.getGivePoint(), MemberPointBizTypeEnum.AFTER_SALE_DEDUCT_GIVE, orderItem.getAfterSaleId()); | ||
| 819 | - // 4.2 回滚积分:增加用户积分(返还抵扣) | ||
| 820 | - addUserPoint(order.getUserId(), orderItem.getUsePoint(), MemberPointBizTypeEnum.AFTER_SALE_REFUND_USED, orderItem.getAfterSaleId()); | ||
| 821 | - | ||
| 822 | - // 5. 回滚经验:扣减用户经验 | ||
| 823 | - getSelf().reduceUserExperienceAsync(order.getUserId(), refundPrice, orderItem.getAfterSaleId()); | ||
| 824 | - | ||
| 825 | - // 6. 回滚佣金:更新分佣记录为已失效 | ||
| 826 | - getSelf().cancelBrokerageAsync(order.getUserId(), id); | ||
| 827 | } | 726 | } |
| 828 | 727 | ||
| 829 | @Override | 728 | @Override |
| @@ -840,6 +739,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -840,6 +739,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 840 | if (updateCount <= 0) { | 739 | if (updateCount <= 0) { |
| 841 | throw exception(ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL); | 740 | throw exception(ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL); |
| 842 | } | 741 | } |
| 742 | + | ||
| 843 | } | 743 | } |
| 844 | 744 | ||
| 845 | /** | 745 | /** |
| @@ -923,11 +823,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -923,11 +823,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 923 | @Override | 823 | @Override |
| 924 | @Transactional(rollbackFor = Exception.class) | 824 | @Transactional(rollbackFor = Exception.class) |
| 925 | public void cancelPaidOrder(Long userId, Long orderId) { | 825 | public void cancelPaidOrder(Long userId, Long orderId) { |
| 826 | + // TODO 芋艿:这里实现要优化下; | ||
| 926 | TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(orderId, userId); | 827 | TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(orderId, userId); |
| 927 | if (order == null) { | 828 | if (order == null) { |
| 928 | throw exception(ORDER_NOT_FOUND); | 829 | throw exception(ORDER_NOT_FOUND); |
| 929 | } | 830 | } |
| 930 | - | ||
| 931 | cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL); | 831 | cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL); |
| 932 | } | 832 | } |
| 933 | 833 | ||
| @@ -940,7 +840,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -940,7 +840,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 940 | @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_COMMENT) | 840 | @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_COMMENT) |
| 941 | public void createOrderItemCommentBySystemBySystem(TradeOrderDO order) { | 841 | public void createOrderItemCommentBySystemBySystem(TradeOrderDO order) { |
| 942 | // 1. 查询未评论的订单项 | 842 | // 1. 查询未评论的订单项 |
| 943 | - List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderIdAndCommentStatus(order.getId(), Boolean.FALSE); | 843 | + List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderIdAndCommentStatus( |
| 844 | + order.getId(), Boolean.FALSE); | ||
| 944 | if (CollUtil.isEmpty(orderItems)) { | 845 | if (CollUtil.isEmpty(orderItems)) { |
| 945 | return; | 846 | return; |
| 946 | } | 847 | } |
| @@ -983,73 +884,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -983,73 +884,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 983 | 884 | ||
| 984 | // =================== 营销相关的操作 =================== | 885 | // =================== 营销相关的操作 =================== |
| 985 | 886 | ||
| 986 | - @Async | ||
| 987 | - protected void addUserExperienceAsync(Long userId, Integer payPrice, Long orderId) { | ||
| 988 | - int bizType = MemberExperienceBizTypeEnum.ORDER.getType(); | ||
| 989 | - memberLevelApi.addExperience(userId, payPrice, bizType, String.valueOf(orderId)); | ||
| 990 | - } | ||
| 991 | - | ||
| 992 | - @Async | ||
| 993 | - protected void reduceUserExperienceAsync(Long userId, Integer refundPrice, Long afterSaleId) { | ||
| 994 | - int bizType = MemberExperienceBizTypeEnum.REFUND.getType(); | ||
| 995 | - memberLevelApi.addExperience(userId, -refundPrice, bizType, String.valueOf(afterSaleId)); | ||
| 996 | - } | ||
| 997 | - | ||
| 998 | - /** | ||
| 999 | - * 添加用户积分 | ||
| 1000 | - * <p> | ||
| 1001 | - * 目前是支付成功后,就会创建积分记录。 | ||
| 1002 | - * <p> | ||
| 1003 | - * 业内还有两种做法,可以根据自己的业务调整: | ||
| 1004 | - * 1. 确认收货后,才创建积分记录 | ||
| 1005 | - * 2. 支付 or 下单成功时,创建积分记录(冻结),确认收货解冻或者 n 天后解冻 | ||
| 1006 | - * | ||
| 1007 | - * @param userId 用户编号 | ||
| 1008 | - * @param point 增加积分数量 | ||
| 1009 | - * @param bizType 业务编号 | ||
| 1010 | - * @param bizId 业务编号 | ||
| 1011 | - */ | ||
| 1012 | - protected void addUserPoint(Long userId, Integer point, MemberPointBizTypeEnum bizType, Long bizId) { | ||
| 1013 | - if (point != null && point > 0) { | ||
| 1014 | - memberPointApi.addPoint(userId, point, bizType.getType(), String.valueOf(bizId)); | ||
| 1015 | - } | ||
| 1016 | - } | ||
| 1017 | - | ||
| 1018 | - protected void reduceUserPoint(Long userId, Integer point, MemberPointBizTypeEnum bizType, Long bizId) { | ||
| 1019 | - if (point != null && point > 0) { | ||
| 1020 | - memberPointApi.reducePoint(userId, point, bizType.getType(), String.valueOf(bizId)); | ||
| 1021 | - } | ||
| 1022 | - } | ||
| 1023 | - | ||
| 1024 | - /** | ||
| 1025 | - * 创建分销记录 | ||
| 1026 | - * <p> | ||
| 1027 | - * 目前是支付成功后,就会创建分销记录。 | ||
| 1028 | - * <p> | ||
| 1029 | - * 业内还有两种做法,可以根据自己的业务调整: | ||
| 1030 | - * 1. 确认收货后,才创建分销记录 | ||
| 1031 | - * 2. 支付 or 下单成功时,创建分销记录(冻结),确认收货解冻或者 n 天后解冻 | ||
| 1032 | - * | ||
| 1033 | - * @param userId 用户编号 | ||
| 1034 | - * @param orderId 订单编号 | ||
| 1035 | - */ | ||
| 1036 | - @Async | ||
| 1037 | - protected void addBrokerageAsync(Long userId, Long orderId) { | ||
| 1038 | - MemberUserRespDTO user = memberUserApi.getUser(userId); | ||
| 1039 | - Assert.notNull(user); | ||
| 1040 | - // 每一个订单项,都会去生成分销记录 | ||
| 1041 | - List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(orderId); | ||
| 1042 | - List<BrokerageAddReqBO> addList = convertList(orderItems, | ||
| 1043 | - item -> TradeOrderConvert.INSTANCE.convert(user, item, | ||
| 1044 | - productSpuApi.getSpu(item.getSpuId()), productSkuApi.getSku(item.getSkuId()))); | ||
| 1045 | - brokerageRecordService.addBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, addList); | ||
| 1046 | - } | ||
| 1047 | - | ||
| 1048 | - @Async | ||
| 1049 | - protected void cancelBrokerageAsync(Long userId, Long orderItemId) { | ||
| 1050 | - brokerageRecordService.cancelBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, String.valueOf(orderItemId)); | ||
| 1051 | - } | ||
| 1052 | - | ||
| 1053 | /** | 887 | /** |
| 1054 | * 获得自身的代理对象,解决 AOP 生效问题 | 888 | * 获得自身的代理对象,解决 AOP 生效问题 |
| 1055 | * | 889 | * |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainOrderHandler.java
| 1 | package cn.iocoder.yudao.module.trade.service.order.handler; | 1 | package cn.iocoder.yudao.module.trade.service.order.handler; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.hutool.core.lang.Assert; | ||
| 3 | import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi; | 5 | import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi; |
| 4 | import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi; | 6 | import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi; |
| 5 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; |
| @@ -11,12 +13,12 @@ import javax.annotation.Resource; | @@ -11,12 +13,12 @@ import javax.annotation.Resource; | ||
| 11 | import java.util.List; | 13 | import java.util.List; |
| 12 | 14 | ||
| 13 | /** | 15 | /** |
| 14 | - * 砍价订单 handler 实现类 | 16 | + * 砍价订单的 {@link TradeOrderHandler} 实现类 |
| 15 | * | 17 | * |
| 16 | * @author HUIHUI | 18 | * @author HUIHUI |
| 17 | */ | 19 | */ |
| 18 | @Component | 20 | @Component |
| 19 | -public class TradeBargainHandler implements TradeOrderHandler { | 21 | +public class TradeBargainOrderHandler implements TradeOrderHandler { |
| 20 | 22 | ||
| 21 | @Resource | 23 | @Resource |
| 22 | private BargainActivityApi bargainActivityApi; | 24 | private BargainActivityApi bargainActivityApi; |
| @@ -25,9 +27,11 @@ public class TradeBargainHandler implements TradeOrderHandler { | @@ -25,9 +27,11 @@ public class TradeBargainHandler implements TradeOrderHandler { | ||
| 25 | 27 | ||
| 26 | @Override | 28 | @Override |
| 27 | public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | 29 | public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { |
| 28 | - if (TradeOrderTypeEnum.isBargain(order.getType())) { | 30 | + if (!TradeOrderTypeEnum.isBargain(order.getType())) { |
| 29 | return; | 31 | return; |
| 30 | } | 32 | } |
| 33 | + // 明确校验一下 | ||
| 34 | + Assert.isTrue(orderItems.size() == 1, "砍价时,只允许选择一个商品"); | ||
| 31 | 35 | ||
| 32 | // 扣减砍价活动的库存 | 36 | // 扣减砍价活动的库存 |
| 33 | bargainActivityApi.updateBargainActivityStock(order.getBargainActivityId(), | 37 | bargainActivityApi.updateBargainActivityStock(order.getBargainActivityId(), |
| @@ -36,20 +40,39 @@ public class TradeBargainHandler implements TradeOrderHandler { | @@ -36,20 +40,39 @@ public class TradeBargainHandler implements TradeOrderHandler { | ||
| 36 | 40 | ||
| 37 | @Override | 41 | @Override |
| 38 | public void afterOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | 42 | public void afterOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { |
| 39 | - if (TradeOrderTypeEnum.isBargain(order.getType())) { | 43 | + if (!TradeOrderTypeEnum.isBargain(order.getType())) { |
| 40 | return; | 44 | return; |
| 41 | } | 45 | } |
| 46 | + // 明确校验一下 | ||
| 47 | + Assert.isTrue(orderItems.size() == 1, "砍价时,只允许选择一个商品"); | ||
| 42 | 48 | ||
| 43 | // 记录砍价记录对应的订单编号 | 49 | // 记录砍价记录对应的订单编号 |
| 44 | bargainRecordApi.updateBargainRecordOrderId(order.getBargainRecordId(), order.getId()); | 50 | bargainRecordApi.updateBargainRecordOrderId(order.getBargainRecordId(), order.getId()); |
| 45 | } | 51 | } |
| 46 | 52 | ||
| 47 | @Override | 53 | @Override |
| 48 | - public void cancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | ||
| 49 | - if (TradeOrderTypeEnum.isBargain(order.getType())) { | 54 | + public void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { |
| 55 | + if (!TradeOrderTypeEnum.isBargain(order.getType())) { | ||
| 50 | return; | 56 | return; |
| 51 | } | 57 | } |
| 52 | - // TODO 芋艿:取消订单时,需要增加库存 | 58 | + // 明确校验一下 |
| 59 | + Assert.isTrue(orderItems.size() == 1, "砍价时,只允许选择一个商品"); | ||
| 60 | + | ||
| 61 | + // 售后的订单项,已经在 afterCancelOrderItem 回滚库存,所以这里不需要重复回滚 | ||
| 62 | + orderItems = filterOrderItemListByNoneAfterSale(orderItems); | ||
| 63 | + if (CollUtil.isEmpty(orderItems)) { | ||
| 64 | + return; | ||
| 65 | + } | ||
| 66 | + afterCancelOrderItem(order, orderItems.get(0)); | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + @Override | ||
| 70 | + public void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) { | ||
| 71 | + if (!TradeOrderTypeEnum.isBargain(order.getType())) { | ||
| 72 | + return; | ||
| 73 | + } | ||
| 74 | + // 恢复(增加)砍价活动的库存 | ||
| 75 | + bargainActivityApi.updateBargainActivityStock(order.getBargainActivityId(), orderItem.getCount()); | ||
| 53 | } | 76 | } |
| 54 | 77 | ||
| 55 | } | 78 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBrokerageOrderHandler.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.order.handler; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.hutool.core.lang.Assert; | ||
| 5 | +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; | ||
| 6 | +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; | ||
| 7 | +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | ||
| 8 | +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | ||
| 9 | +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; | ||
| 10 | +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; | ||
| 11 | +import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; | ||
| 12 | +import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO; | ||
| 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.enums.brokerage.BrokerageRecordBizTypeEnum; | ||
| 16 | +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService; | ||
| 17 | +import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService; | ||
| 18 | +import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; | ||
| 19 | +import org.springframework.stereotype.Component; | ||
| 20 | + | ||
| 21 | +import javax.annotation.Resource; | ||
| 22 | +import java.util.List; | ||
| 23 | + | ||
| 24 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 25 | + | ||
| 26 | +/** | ||
| 27 | + * 订单分销的 {@link TradeOrderHandler} 实现类 | ||
| 28 | + * | ||
| 29 | + * @author 芋道源码 | ||
| 30 | + */ | ||
| 31 | +@Component | ||
| 32 | +public class TradeBrokerageOrderHandler implements TradeOrderHandler { | ||
| 33 | + | ||
| 34 | + @Resource | ||
| 35 | + private MemberUserApi memberUserApi; | ||
| 36 | + @Resource | ||
| 37 | + private ProductSpuApi productSpuApi; | ||
| 38 | + @Resource | ||
| 39 | + private ProductSkuApi productSkuApi; | ||
| 40 | + | ||
| 41 | + @Resource | ||
| 42 | + private BrokerageRecordService brokerageRecordService; | ||
| 43 | + @Resource | ||
| 44 | + private BrokerageUserService brokerageUserService; | ||
| 45 | + | ||
| 46 | + @Override | ||
| 47 | + public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | ||
| 48 | + // 设置订单推广人 | ||
| 49 | + BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(order.getUserId()); | ||
| 50 | + if (brokerageUser != null && brokerageUser.getBindUserId() != null) { | ||
| 51 | + order.setBrokerageUserId(brokerageUser.getBindUserId()); | ||
| 52 | + } | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + @Override | ||
| 56 | + public void afterPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | ||
| 57 | + if (order.getBrokerageUserId() == null) { | ||
| 58 | + return; | ||
| 59 | + } | ||
| 60 | + addBrokerage(order.getUserId(), orderItems); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + @Override | ||
| 64 | + public void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | ||
| 65 | + // 如果是未支付的订单,不会产生分销结果,所以直接 return | ||
| 66 | + if (!order.getPayStatus()) { | ||
| 67 | + return; | ||
| 68 | + } | ||
| 69 | + if (order.getBrokerageUserId() == null) { | ||
| 70 | + return; | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + // 售后的订单项,已经在 afterCancelOrderItem 回滚库存,所以这里不需要重复回滚 | ||
| 74 | + orderItems = filterOrderItemListByNoneAfterSale(orderItems); | ||
| 75 | + if (CollUtil.isEmpty(orderItems)) { | ||
| 76 | + return; | ||
| 77 | + } | ||
| 78 | + orderItems.forEach(orderItem -> afterCancelOrderItem(order, orderItem)); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + @Override | ||
| 82 | + public void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) { | ||
| 83 | + if (order.getBrokerageUserId() == null) { | ||
| 84 | + return; | ||
| 85 | + } | ||
| 86 | + cancelBrokerage(order.getId(), orderItem.getOrderId()); | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + /** | ||
| 90 | + * 创建分销记录 | ||
| 91 | + * <p> | ||
| 92 | + * 目前是支付成功后,就会创建分销记录。 | ||
| 93 | + * <p> | ||
| 94 | + * 业内还有两种做法,可以根据自己的业务调整: | ||
| 95 | + * 1. 确认收货后,才创建分销记录 | ||
| 96 | + * 2. 支付 or 下单成功时,创建分销记录(冻结),确认收货解冻或者 n 天后解冻 | ||
| 97 | + * | ||
| 98 | + * @param userId 用户编号 | ||
| 99 | + * @param orderItems 订单项 | ||
| 100 | + */ | ||
| 101 | + protected void addBrokerage(Long userId, List<TradeOrderItemDO> orderItems) { | ||
| 102 | + MemberUserRespDTO user = memberUserApi.getUser(userId); | ||
| 103 | + Assert.notNull(user); | ||
| 104 | + ProductSpuRespDTO spu = productSpuApi.getSpu(orderItems.get(0).getSpuId()); | ||
| 105 | + Assert.notNull(spu); | ||
| 106 | + ProductSkuRespDTO sku = productSkuApi.getSku(orderItems.get(0).getSkuId()); | ||
| 107 | + | ||
| 108 | + // 每一个订单项,都会去生成分销记录 | ||
| 109 | + List<BrokerageAddReqBO> addList = convertList(orderItems, | ||
| 110 | + item -> TradeOrderConvert.INSTANCE.convert(user, item, spu, sku)); | ||
| 111 | + brokerageRecordService.addBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, addList); | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + protected void cancelBrokerage(Long userId, Long orderItemId) { | ||
| 115 | + brokerageRecordService.cancelBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, String.valueOf(orderItemId)); | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | +} |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationOrderHandler.java
| 1 | package cn.iocoder.yudao.module.trade.service.order.handler; | 1 | package cn.iocoder.yudao.module.trade.service.order.handler; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.lang.Assert; | 3 | import cn.hutool.core.lang.Assert; |
| 4 | +import cn.iocoder.yudao.framework.common.core.KeyValue; | ||
| 4 | import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; | 5 | import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; |
| 5 | import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; | 6 | import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; |
| 6 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; |
| 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; |
| 9 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; | ||
| 8 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | 10 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; |
| 11 | +import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; | ||
| 12 | +import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; | ||
| 9 | import org.springframework.stereotype.Component; | 13 | import org.springframework.stereotype.Component; |
| 10 | 14 | ||
| 11 | import javax.annotation.Resource; | 15 | import javax.annotation.Resource; |
| 12 | import java.util.List; | 16 | import java.util.List; |
| 13 | 17 | ||
| 18 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 19 | +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_CREATE_FAIL_EXIST_UNPAID; | ||
| 20 | +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS; | ||
| 21 | + | ||
| 14 | /** | 22 | /** |
| 15 | - * 拼团订单 handler 接口实现类 | 23 | + * 拼团订单的 {@link TradeOrderHandler} 实现类 |
| 16 | * | 24 | * |
| 17 | * @author HUIHUI | 25 | * @author HUIHUI |
| 18 | */ | 26 | */ |
| 19 | @Component | 27 | @Component |
| 20 | -public class TradeCombinationHandler implements TradeOrderHandler { | 28 | +public class TradeCombinationOrderHandler implements TradeOrderHandler { |
| 29 | + | ||
| 30 | + @Resource | ||
| 31 | + private TradeOrderUpdateService orderUpdateService; | ||
| 32 | + @Resource | ||
| 33 | + private TradeOrderQueryService orderQueryService; | ||
| 21 | 34 | ||
| 22 | @Resource | 35 | @Resource |
| 23 | private CombinationRecordApi combinationRecordApi; | 36 | private CombinationRecordApi combinationRecordApi; |
| @@ -25,37 +38,54 @@ public class TradeCombinationHandler implements TradeOrderHandler { | @@ -25,37 +38,54 @@ public class TradeCombinationHandler implements TradeOrderHandler { | ||
| 25 | @Override | 38 | @Override |
| 26 | public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | 39 | public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { |
| 27 | // 如果不是拼团订单则结束 | 40 | // 如果不是拼团订单则结束 |
| 28 | - if (TradeOrderTypeEnum.isCombination(order.getType())) { | 41 | + if (!TradeOrderTypeEnum.isCombination(order.getType())) { |
| 29 | return; | 42 | return; |
| 30 | } | 43 | } |
| 31 | Assert.isTrue(orderItems.size() == 1, "拼团时,只允许选择一个商品"); | 44 | Assert.isTrue(orderItems.size() == 1, "拼团时,只允许选择一个商品"); |
| 32 | 45 | ||
| 33 | - // 校验是否满足拼团活动相关限制 | 46 | + // 1. 校验是否满足拼团活动相关限制 |
| 34 | TradeOrderItemDO item = orderItems.get(0); | 47 | TradeOrderItemDO item = orderItems.get(0); |
| 35 | combinationRecordApi.validateCombinationRecord(order.getUserId(), order.getCombinationActivityId(), | 48 | combinationRecordApi.validateCombinationRecord(order.getUserId(), order.getCombinationActivityId(), |
| 36 | order.getCombinationHeadId(), item.getSkuId(), item.getCount()); | 49 | order.getCombinationHeadId(), item.getSkuId(), item.getCount()); |
| 37 | - // TODO @puhui999:这里还要限制下,是不是已经 createOrder;就是还没支付的时候,重复下单了;需要校验下;不然的话,一个拼团可以下多个单子了; | 50 | + |
| 51 | + // 2. 校验该用户是否存在未支付的拼团活动订单,避免一个拼团可以下多个单子了 | ||
| 52 | + // TODO @puhui999:只校验未支付的拼团订单噢 | ||
| 53 | + TradeOrderDO activityOrder = orderQueryService.getActivityOrderByUserIdAndActivityIdAndStatus( | ||
| 54 | + order.getUserId(), order.getCombinationActivityId(), TradeOrderStatusEnum.UNPAID.getStatus()); | ||
| 55 | + if (activityOrder != null) { | ||
| 56 | + throw exception(ORDER_CREATE_FAIL_EXIST_UNPAID); | ||
| 57 | + } | ||
| 38 | } | 58 | } |
| 39 | 59 | ||
| 40 | @Override | 60 | @Override |
| 41 | public void afterPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | 61 | public void afterPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { |
| 42 | - // 如果不是拼团订单则结束 | ||
| 43 | - if (TradeOrderTypeEnum.isCombination(order.getType())) { | 62 | + // 1.如果不是拼团订单则结束 |
| 63 | + if (!TradeOrderTypeEnum.isCombination(order.getType())) { | ||
| 44 | return; | 64 | return; |
| 45 | } | 65 | } |
| 46 | Assert.isTrue(orderItems.size() == 1, "拼团时,只允许选择一个商品"); | 66 | Assert.isTrue(orderItems.size() == 1, "拼团时,只允许选择一个商品"); |
| 47 | 67 | ||
| 48 | - // 获取商品信息 | 68 | + // 2. 创建拼团记录 |
| 49 | TradeOrderItemDO item = orderItems.get(0); | 69 | TradeOrderItemDO item = orderItems.get(0); |
| 50 | - // 创建拼团记录 | ||
| 51 | - combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(order, item)); | 70 | + KeyValue<Long, Long> recordIdAndHeadId = combinationRecordApi.createCombinationRecord( |
| 71 | + TradeOrderConvert.INSTANCE.convert(order, item)); | ||
| 72 | + | ||
| 73 | + // 3. 更新拼团相关信息到订单 | ||
| 74 | + // TODO 芋艿,只需要更新 record | ||
| 75 | + orderUpdateService.updateOrderCombinationInfo(order.getId(), order.getCombinationActivityId(), | ||
| 76 | + recordIdAndHeadId.getKey(), recordIdAndHeadId.getValue()); | ||
| 52 | } | 77 | } |
| 53 | 78 | ||
| 54 | @Override | 79 | @Override |
| 55 | - public void cancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | ||
| 56 | - if (TradeOrderTypeEnum.isCombination(order.getType())) { | 80 | + public void beforeDeliveryOrder(TradeOrderDO order) { |
| 81 | + if (!TradeOrderTypeEnum.isCombination(order.getType())) { | ||
| 57 | return; | 82 | return; |
| 58 | } | 83 | } |
| 84 | + // 校验订单拼团是否成功 | ||
| 85 | + if (!combinationRecordApi.isCombinationRecordSuccess(order.getUserId(), order.getId())) { | ||
| 86 | + throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS); | ||
| 87 | + } | ||
| 59 | } | 88 | } |
| 60 | 89 | ||
| 61 | } | 90 | } |
| 91 | + |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCouponOrderHandler.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.order.handler; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; | ||
| 4 | +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; | ||
| 5 | +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | ||
| 6 | +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | ||
| 7 | +import org.springframework.stereotype.Component; | ||
| 8 | + | ||
| 9 | +import javax.annotation.Resource; | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 优惠劵的 {@link TradeOrderHandler} 实现类 | ||
| 14 | + * | ||
| 15 | + * @author 芋道源码 | ||
| 16 | + */ | ||
| 17 | +@Component | ||
| 18 | +public class TradeCouponOrderHandler implements TradeOrderHandler { | ||
| 19 | + | ||
| 20 | + @Resource | ||
| 21 | + private CouponApi couponApi; | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public void afterOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | ||
| 25 | + if (order.getCouponId() == null || order.getCouponId() <= 0) { | ||
| 26 | + return; | ||
| 27 | + } | ||
| 28 | + // 不在前置扣减的原因,是因为优惠劵要记录使用的订单号 | ||
| 29 | + couponApi.useCoupon(new CouponUseReqDTO().setId(order.getCouponId()).setUserId(order.getUserId()) | ||
| 30 | + .setOrderId(order.getId())); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + @Override | ||
| 34 | + public void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | ||
| 35 | + if (order.getCouponId() == null || order.getCouponId() <= 0) { | ||
| 36 | + return; | ||
| 37 | + } | ||
| 38 | + // 退回优惠劵 | ||
| 39 | + couponApi.returnUsedCoupon(order.getCouponId()); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | +} |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeMemberPointOrderHandler.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.order.handler; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; | ||
| 5 | +import cn.iocoder.yudao.module.member.api.point.MemberPointApi; | ||
| 6 | +import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; | ||
| 7 | +import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; | ||
| 8 | +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; | ||
| 9 | +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | ||
| 10 | +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | ||
| 11 | +import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleService; | ||
| 12 | +import org.springframework.stereotype.Component; | ||
| 13 | + | ||
| 14 | +import javax.annotation.Resource; | ||
| 15 | +import java.util.List; | ||
| 16 | + | ||
| 17 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; | ||
| 18 | + | ||
| 19 | +/** | ||
| 20 | + * 会员积分、等级的 {@link TradeOrderHandler} 实现类 | ||
| 21 | + * | ||
| 22 | + * @author owen | ||
| 23 | + */ | ||
| 24 | +@Component | ||
| 25 | +public class TradeMemberPointOrderHandler implements TradeOrderHandler { | ||
| 26 | + | ||
| 27 | + @Resource | ||
| 28 | + private MemberPointApi memberPointApi; | ||
| 29 | + @Resource | ||
| 30 | + private MemberLevelApi memberLevelApi; | ||
| 31 | + | ||
| 32 | + @Resource | ||
| 33 | + private AfterSaleService afterSaleService; | ||
| 34 | + | ||
| 35 | + @Override | ||
| 36 | + public void afterOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | ||
| 37 | + // 扣减用户积分(订单抵扣)。不在前置扣减的原因,是因为积分扣减时,需要记录关联业务 | ||
| 38 | + reducePoint(order.getUserId(), order.getUsePoint(), MemberPointBizTypeEnum.ORDER_USE, order.getId()); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + @Override | ||
| 42 | + public void afterPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | ||
| 43 | + // 增加用户积分(订单赠送) | ||
| 44 | + addPoint(order.getUserId(), order.getGivePoint(), MemberPointBizTypeEnum.ORDER_GIVE, | ||
| 45 | + order.getId()); | ||
| 46 | + | ||
| 47 | + // 增加用户经验 | ||
| 48 | + memberLevelApi.addExperience(order.getUserId(), order.getPayPrice(), | ||
| 49 | + MemberExperienceBizTypeEnum.ORDER_GIVE.getType(), String.valueOf(order.getId())); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + @Override | ||
| 53 | + public void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | ||
| 54 | + // 售后的订单项,已经在 afterCancelOrderItem 回滚库存,所以这里不需要重复回滚 | ||
| 55 | + orderItems = filterOrderItemListByNoneAfterSale(orderItems); | ||
| 56 | + if (CollUtil.isEmpty(orderItems)) { | ||
| 57 | + return; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + // 增加(回滚)用户积分(订单抵扣) | ||
| 61 | + Integer usePoint = getSumValue(orderItems, TradeOrderItemDO::getUsePoint, Integer::sum); | ||
| 62 | + addPoint(order.getUserId(), usePoint, MemberPointBizTypeEnum.ORDER_USE_CANCEL, | ||
| 63 | + order.getId()); | ||
| 64 | + | ||
| 65 | + // 如下的返还,需要经过支持,也就是经历 afterPayOrder 流程 | ||
| 66 | + if (!order.getPayStatus()) { | ||
| 67 | + return; | ||
| 68 | + } | ||
| 69 | + // 扣减(回滚)积分(订单赠送) | ||
| 70 | + Integer givePoint = getSumValue(orderItems, TradeOrderItemDO::getGivePoint, Integer::sum); | ||
| 71 | + reducePoint(order.getUserId(), givePoint, MemberPointBizTypeEnum.ORDER_GIVE_CANCEL, | ||
| 72 | + order.getId()); | ||
| 73 | + // 扣减(回滚)用户经验 | ||
| 74 | + int payPrice = order.getPayPrice() - order.getRefundPrice(); | ||
| 75 | + memberLevelApi.addExperience(order.getUserId(), payPrice, | ||
| 76 | + MemberExperienceBizTypeEnum.ORDER_GIVE_CANCEL.getType(), String.valueOf(order.getId())); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + @Override | ||
| 80 | + public void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) { | ||
| 81 | + // 扣减(回滚)积分(订单赠送) | ||
| 82 | + reducePoint(order.getUserId(), orderItem.getGivePoint(), MemberPointBizTypeEnum.ORDER_GIVE_CANCEL_ITEM, | ||
| 83 | + orderItem.getId()); | ||
| 84 | + // 增加(回滚)积分(订单抵扣) | ||
| 85 | + addPoint(order.getUserId(), orderItem.getUsePoint(), MemberPointBizTypeEnum.ORDER_USE_CANCEL_ITEM, | ||
| 86 | + orderItem.getId()); | ||
| 87 | + | ||
| 88 | + // 扣减(回滚)用户经验 | ||
| 89 | + AfterSaleDO afterSale = afterSaleService.getAfterSale(orderItem.getAfterSaleId()); | ||
| 90 | + memberLevelApi.reduceExperience(order.getUserId(), afterSale.getRefundPrice(), | ||
| 91 | + MemberExperienceBizTypeEnum.ORDER_GIVE_CANCEL_ITEM.getType(), String.valueOf(orderItem.getId())); | ||
| 92 | + } | ||
| 93 | + | ||
| 94 | + /** | ||
| 95 | + * 添加用户积分 | ||
| 96 | + * <p> | ||
| 97 | + * 目前是支付成功后,就会创建积分记录。 | ||
| 98 | + * <p> | ||
| 99 | + * 业内还有两种做法,可以根据自己的业务调整: | ||
| 100 | + * 1. 确认收货后,才创建积分记录 | ||
| 101 | + * 2. 支付 or 下单成功时,创建积分记录(冻结),确认收货解冻或者 n 天后解冻 | ||
| 102 | + * | ||
| 103 | + * @param userId 用户编号 | ||
| 104 | + * @param point 增加积分数量 | ||
| 105 | + * @param bizType 业务编号 | ||
| 106 | + * @param bizId 业务编号 | ||
| 107 | + */ | ||
| 108 | + protected void addPoint(Long userId, Integer point, MemberPointBizTypeEnum bizType, Long bizId) { | ||
| 109 | + if (point != null && point > 0) { | ||
| 110 | + memberPointApi.addPoint(userId, point, bizType.getType(), String.valueOf(bizId)); | ||
| 111 | + } | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + protected void reducePoint(Long userId, Integer point, MemberPointBizTypeEnum bizType, Long bizId) { | ||
| 115 | + if (point != null && point > 0) { | ||
| 116 | + memberPointApi.reducePoint(userId, point, bizType.getType(), String.valueOf(bizId)); | ||
| 117 | + } | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | +} |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java
| 1 | package cn.iocoder.yudao.module.trade.service.order.handler; | 1 | package cn.iocoder.yudao.module.trade.service.order.handler; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 3 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | 4 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; |
| 4 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | 5 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; |
| 6 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; | ||
| 5 | 7 | ||
| 6 | import java.util.List; | 8 | import java.util.List; |
| 7 | 9 | ||
| @@ -35,16 +37,42 @@ public interface TradeOrderHandler { | @@ -35,16 +37,42 @@ public interface TradeOrderHandler { | ||
| 35 | * @param order 订单 | 37 | * @param order 订单 |
| 36 | * @param orderItems 订单项 | 38 | * @param orderItems 订单项 |
| 37 | */ | 39 | */ |
| 38 | - default void afterPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | ||
| 39 | - } | 40 | + default void afterPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {} |
| 40 | 41 | ||
| 41 | /** | 42 | /** |
| 42 | - * 订单取消 | 43 | + * 订单取消后 |
| 43 | * | 44 | * |
| 44 | * @param order 订单 | 45 | * @param order 订单 |
| 45 | * @param orderItems 订单项 | 46 | * @param orderItems 订单项 |
| 46 | */ | 47 | */ |
| 47 | - default void cancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | 48 | + default void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {} |
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * 订单项取消后 | ||
| 52 | + * | ||
| 53 | + * @param order 订单 | ||
| 54 | + * @param orderItem 订单项 | ||
| 55 | + */ | ||
| 56 | + default void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) {} | ||
| 57 | + | ||
| 58 | + /** | ||
| 59 | + * 订单发货前 | ||
| 60 | + * | ||
| 61 | + * @param order 订单 | ||
| 62 | + */ | ||
| 63 | + default void beforeDeliveryOrder(TradeOrderDO order) {} | ||
| 64 | + | ||
| 65 | + // ========== 公用方法 ========== | ||
| 66 | + | ||
| 67 | + /** | ||
| 68 | + * 过滤“未售后”的订单项列表 | ||
| 69 | + * | ||
| 70 | + * @param orderItems 订单项列表 | ||
| 71 | + * @return 过滤后的订单项列表 | ||
| 72 | + */ | ||
| 73 | + default List<TradeOrderItemDO> filterOrderItemListByNoneAfterSale(List<TradeOrderItemDO> orderItems) { | ||
| 74 | + return CollectionUtils.filterList(orderItems, | ||
| 75 | + item -> TradeOrderItemAfterSaleStatusEnum.isNone(item.getAfterSaleStatus())); | ||
| 48 | } | 76 | } |
| 49 | 77 | ||
| 50 | } | 78 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeProductSkuOrderHandler.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.order.handler; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | ||
| 5 | +import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; | ||
| 6 | +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | ||
| 7 | +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | ||
| 8 | +import org.springframework.stereotype.Component; | ||
| 9 | + | ||
| 10 | +import javax.annotation.Resource; | ||
| 11 | +import java.util.List; | ||
| 12 | + | ||
| 13 | +import static java.util.Collections.singletonList; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * 商品 SKU 库存的 {@link TradeOrderHandler} 实现类 | ||
| 17 | + * | ||
| 18 | + * @author 芋道源码 | ||
| 19 | + */ | ||
| 20 | +@Component | ||
| 21 | +public class TradeProductSkuOrderHandler implements TradeOrderHandler { | ||
| 22 | + | ||
| 23 | + @Resource | ||
| 24 | + private ProductSkuApi productSkuApi; | ||
| 25 | + | ||
| 26 | + @Override | ||
| 27 | + public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | ||
| 28 | + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(orderItems)); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + @Override | ||
| 32 | + public void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | ||
| 33 | + // 售后的订单项,已经在 afterCancelOrderItem 回滚库存,所以这里不需要重复回滚 | ||
| 34 | + orderItems = filterOrderItemListByNoneAfterSale(orderItems); | ||
| 35 | + if (CollUtil.isEmpty(orderItems)) { | ||
| 36 | + return; | ||
| 37 | + } | ||
| 38 | + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + @Override | ||
| 42 | + public void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) { | ||
| 43 | + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(singletonList(orderItem))); | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | +} |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java renamed to yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillOrderHandler.java
| 1 | package cn.iocoder.yudao.module.trade.service.order.handler; | 1 | package cn.iocoder.yudao.module.trade.service.order.handler; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.hutool.core.lang.Assert; | ||
| 3 | import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; | 5 | import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; |
| 4 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | 6 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; |
| 5 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; |
| @@ -10,33 +12,53 @@ import javax.annotation.Resource; | @@ -10,33 +12,53 @@ import javax.annotation.Resource; | ||
| 10 | import java.util.List; | 12 | import java.util.List; |
| 11 | 13 | ||
| 12 | /** | 14 | /** |
| 13 | - * 秒杀订单 handler 实现类 | 15 | + * 秒杀订单的 {@link TradeOrderHandler} 实现类 |
| 14 | * | 16 | * |
| 15 | * @author HUIHUI | 17 | * @author HUIHUI |
| 16 | */ | 18 | */ |
| 17 | @Component | 19 | @Component |
| 18 | -public class TradeSeckillHandler implements TradeOrderHandler { | 20 | +public class TradeSeckillOrderHandler implements TradeOrderHandler { |
| 19 | 21 | ||
| 20 | @Resource | 22 | @Resource |
| 21 | private SeckillActivityApi seckillActivityApi; | 23 | private SeckillActivityApi seckillActivityApi; |
| 22 | 24 | ||
| 23 | @Override | 25 | @Override |
| 24 | public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | 26 | public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { |
| 25 | - if (TradeOrderTypeEnum.isSeckill(order.getType())) { | 27 | + if (!TradeOrderTypeEnum.isSeckill(order.getType())) { |
| 26 | return; | 28 | return; |
| 27 | } | 29 | } |
| 30 | + // 明确校验一下 | ||
| 31 | + Assert.isTrue(orderItems.size() == 1, "秒杀时,只允许选择一个商品"); | ||
| 28 | 32 | ||
| 29 | // 扣减秒杀活动的库存 | 33 | // 扣减秒杀活动的库存 |
| 30 | - seckillActivityApi.updateSeckillStock(order.getSeckillActivityId(), | 34 | + seckillActivityApi.updateSeckillStockDecr(order.getSeckillActivityId(), |
| 31 | orderItems.get(0).getSkuId(), orderItems.get(0).getCount()); | 35 | orderItems.get(0).getSkuId(), orderItems.get(0).getCount()); |
| 32 | } | 36 | } |
| 33 | 37 | ||
| 34 | @Override | 38 | @Override |
| 35 | - public void cancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { | ||
| 36 | - if (TradeOrderTypeEnum.isSeckill(order.getType())) { | 39 | + public void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { |
| 40 | + if (!TradeOrderTypeEnum.isSeckill(order.getType())) { | ||
| 37 | return; | 41 | return; |
| 38 | } | 42 | } |
| 43 | + // 明确校验一下 | ||
| 44 | + Assert.isTrue(orderItems.size() == 1, "秒杀时,只允许选择一个商品"); | ||
| 39 | 45 | ||
| 46 | + // 售后的订单项,已经在 afterCancelOrderItem 回滚库存,所以这里不需要重复回滚 | ||
| 47 | + orderItems = filterOrderItemListByNoneAfterSale(orderItems); | ||
| 48 | + if (CollUtil.isEmpty(orderItems)) { | ||
| 49 | + return; | ||
| 50 | + } | ||
| 51 | + afterCancelOrderItem(order, orderItems.get(0)); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + @Override | ||
| 55 | + public void afterCancelOrderItem(TradeOrderDO order, TradeOrderItemDO orderItem) { | ||
| 56 | + if (!TradeOrderTypeEnum.isSeckill(order.getType())) { | ||
| 57 | + return; | ||
| 58 | + } | ||
| 59 | + // 恢复秒杀活动的库存 | ||
| 60 | + seckillActivityApi.updateSeckillStockIncr(order.getSeckillActivityId(), | ||
| 61 | + orderItem.getSkuId(), orderItem.getCount()); | ||
| 40 | } | 62 | } |
| 41 | 63 | ||
| 42 | } | 64 | } |
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApi.java
| @@ -28,4 +28,14 @@ public interface MemberLevelApi { | @@ -28,4 +28,14 @@ public interface MemberLevelApi { | ||
| 28 | */ | 28 | */ |
| 29 | void addExperience(Long userId, Integer experience, Integer bizType, String bizId); | 29 | void addExperience(Long userId, Integer experience, Integer bizType, String bizId); |
| 30 | 30 | ||
| 31 | + /** | ||
| 32 | + * 扣减会员经验 | ||
| 33 | + * | ||
| 34 | + * @param userId 会员ID | ||
| 35 | + * @param experience 经验 | ||
| 36 | + * @param bizType 业务类型 {@link MemberExperienceBizTypeEnum} | ||
| 37 | + * @param bizId 业务编号 | ||
| 38 | + */ | ||
| 39 | + void reduceExperience(Long userId, Integer experience, Integer bizType, String bizId); | ||
| 40 | + | ||
| 31 | } | 41 | } |
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/MemberExperienceBizTypeEnum.java
| @@ -20,10 +20,11 @@ public enum MemberExperienceBizTypeEnum { | @@ -20,10 +20,11 @@ public enum MemberExperienceBizTypeEnum { | ||
| 20 | */ | 20 | */ |
| 21 | ADMIN(0, "管理员调整", "管理员调整获得 {} 经验", true), | 21 | ADMIN(0, "管理员调整", "管理员调整获得 {} 经验", true), |
| 22 | INVITE_REGISTER(1, "邀新奖励", "邀请好友获得 {} 经验", true), | 22 | INVITE_REGISTER(1, "邀新奖励", "邀请好友获得 {} 经验", true), |
| 23 | - ORDER(2, "下单奖励", "下单获得 {} 经验", true), | ||
| 24 | - REFUND(3, "退单扣除", "退单获得 {} 经验", false), | ||
| 25 | SIGN_IN(4, "签到奖励", "签到获得 {} 经验", true), | 23 | SIGN_IN(4, "签到奖励", "签到获得 {} 经验", true), |
| 26 | LOTTERY(5, "抽奖奖励", "抽奖获得 {} 经验", true), | 24 | LOTTERY(5, "抽奖奖励", "抽奖获得 {} 经验", true), |
| 25 | + ORDER_GIVE(11, "下单奖励", "下单获得 {} 经验", true), | ||
| 26 | + ORDER_GIVE_CANCEL(12, "下单奖励(整单取消)", "取消订单获得 {} 经验", false), // ORDER_GIVE 的取消 | ||
| 27 | + ORDER_GIVE_CANCEL_ITEM(13, "下单奖励(单个退款)", "退款订单获得 {} 经验", false), // ORDER_GIVE 的取消 | ||
| 27 | ; | 28 | ; |
| 28 | 29 | ||
| 29 | /** | 30 | /** |
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/point/MemberPointBizTypeEnum.java
| @@ -18,11 +18,14 @@ public enum MemberPointBizTypeEnum implements IntArrayValuable { | @@ -18,11 +18,14 @@ public enum MemberPointBizTypeEnum implements IntArrayValuable { | ||
| 18 | 18 | ||
| 19 | SIGN(1, "签到", "签到获得 {} 积分", true), | 19 | SIGN(1, "签到", "签到获得 {} 积分", true), |
| 20 | ADMIN(2, "管理员修改", "管理员修改 {} 积分", true), | 20 | ADMIN(2, "管理员修改", "管理员修改 {} 积分", true), |
| 21 | - ORDER_GIVE(10, "订单奖励", "下单获得 {} 积分", true), // 支付订单时,赠送积分 | ||
| 22 | - ORDER_CANCEL(11, "订单取消", "订单取消,退还 {} 积分", true), // 取消订单时,退回积分 | ||
| 23 | - ORDER_USE(12, "订单使用", "下单使用 {} 积分", false), // 下单时,扣减积分 | ||
| 24 | - AFTER_SALE_REFUND_USED(13, "订单退款", "订单退款,退还 {} 积分", true), // 售后订单成功时,退回积分(对应 ORDER_USE 操作) | ||
| 25 | - AFTER_SALE_DEDUCT_GIVE(14, "订单退款", "订单退款,扣除赠送的 {} 积分", false), // 售后订单成功时,扣减积分(对应 ORDER_GIVE 操作) | 21 | + |
| 22 | + ORDER_USE(11, "订单积分抵扣", "下单使用 {} 积分", false), // 下单时,扣减积分 | ||
| 23 | + ORDER_USE_CANCEL(12, "订单积分抵扣(整单取消)", "订单取消,退还 {} 积分", true), // ORDER_USE 的取消 | ||
| 24 | + ORDER_USE_CANCEL_ITEM(13, "订单积分抵扣(单个退款)", "订单退款,退还 {} 积分", true), // ORDER_USE 的取消 | ||
| 25 | + | ||
| 26 | + ORDER_GIVE(21, "订单积分奖励", "下单获得 {} 积分", true), // 支付订单时,赠送积分 | ||
| 27 | + ORDER_GIVE_CANCEL(22, "订单积分奖励(整单取消)", "订单取消,退还 {} 积分", false), // ORDER_GIVE 的取消 | ||
| 28 | + ORDER_GIVE_CANCEL_ITEM(23, "订单积分奖励(单个退款)", "订单退款,扣除赠送的 {} 积分", false) // ORDER_GIVE 的取消 | ||
| 26 | ; | 29 | ; |
| 27 | 30 | ||
| 28 | /** | 31 | /** |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApiImpl.java
| @@ -38,4 +38,9 @@ public class MemberLevelApiImpl implements MemberLevelApi { | @@ -38,4 +38,9 @@ public class MemberLevelApiImpl implements MemberLevelApi { | ||
| 38 | memberLevelService.addExperience(userId, experience, bizTypeEnum, bizId); | 38 | memberLevelService.addExperience(userId, experience, bizTypeEnum, bizId); |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | + @Override | ||
| 42 | + public void reduceExperience(Long userId, Integer experience, Integer bizType, String bizId) { | ||
| 43 | + addExperience(userId, -experience, bizType, bizId); | ||
| 44 | + } | ||
| 45 | + | ||
| 41 | } | 46 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/wallet/PayWalletApiImpl.java deleted
| 1 | -package cn.iocoder.yudao.module.pay.api.wallet; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.module.pay.api.wallet.dto.WalletSummaryRespDTO; | ||
| 4 | -import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; | ||
| 5 | -import cn.iocoder.yudao.module.pay.service.wallet.PayWalletRechargeService; | ||
| 6 | -import cn.iocoder.yudao.module.pay.service.wallet.PayWalletTransactionService; | ||
| 7 | -import org.springframework.stereotype.Service; | ||
| 8 | -import org.springframework.validation.annotation.Validated; | ||
| 9 | - | ||
| 10 | -import javax.annotation.Resource; | ||
| 11 | -import java.time.LocalDateTime; | ||
| 12 | - | ||
| 13 | -/** | ||
| 14 | - * 钱包 API 接口实现类 | ||
| 15 | - * | ||
| 16 | - * @author owen | ||
| 17 | - */ | ||
| 18 | -@Service | ||
| 19 | -@Validated | ||
| 20 | -public class PayWalletApiImpl implements PayWalletApi { | ||
| 21 | - | ||
| 22 | - @Resource | ||
| 23 | - private PayWalletRechargeService payWalletRechargeService; | ||
| 24 | - @Resource | ||
| 25 | - private PayWalletTransactionService payWalletTransactionService; | ||
| 26 | - | ||
| 27 | - @Override | ||
| 28 | - public WalletSummaryRespDTO getWalletSummary(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 29 | - WalletSummaryRespDTO walletSummary = payWalletRechargeService.getWalletSummary(beginTime, endTime); | ||
| 30 | - walletSummary.setOrderWalletPayPrice(payWalletTransactionService.getPriceSummary(PayWalletBizTypeEnum.PAYMENT, beginTime, endTime)); | ||
| 31 | - return walletSummary; | ||
| 32 | - } | ||
| 33 | - | ||
| 34 | -} |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletRechargeMapper.java
| 1 | package cn.iocoder.yudao.module.pay.dal.mysql.wallet; | 1 | package cn.iocoder.yudao.module.pay.dal.mysql.wallet; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.bean.BeanUtil; | ||
| 4 | -import cn.hutool.core.collection.CollUtil; | ||
| 5 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 7 | -import cn.iocoder.yudao.module.pay.api.wallet.dto.WalletSummaryRespDTO; | ||
| 8 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargeDO; | 5 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargeDO; |
| 9 | -import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; | ||
| 10 | -import com.github.yulichang.toolkit.MPJWrappers; | ||
| 11 | import org.apache.ibatis.annotations.Mapper; | 6 | import org.apache.ibatis.annotations.Mapper; |
| 12 | 7 | ||
| 13 | -import java.time.LocalDateTime; | ||
| 14 | - | ||
| 15 | @Mapper | 8 | @Mapper |
| 16 | public interface PayWalletRechargeMapper extends BaseMapperX<PayWalletRechargeDO> { | 9 | public interface PayWalletRechargeMapper extends BaseMapperX<PayWalletRechargeDO> { |
| 17 | 10 | ||
| @@ -25,24 +18,6 @@ public interface PayWalletRechargeMapper extends BaseMapperX<PayWalletRechargeDO | @@ -25,24 +18,6 @@ public interface PayWalletRechargeMapper extends BaseMapperX<PayWalletRechargeDO | ||
| 25 | .eq(PayWalletRechargeDO::getId, id).eq(PayWalletRechargeDO::getRefundStatus, whereRefundStatus)); | 18 | .eq(PayWalletRechargeDO::getId, id).eq(PayWalletRechargeDO::getRefundStatus, whereRefundStatus)); |
| 26 | } | 19 | } |
| 27 | 20 | ||
| 28 | - default WalletSummaryRespDTO selectRechargeSummaryByPayTimeBetween(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 29 | - return BeanUtil.copyProperties(CollUtil.get(selectMaps(MPJWrappers.<PayWalletRechargeDO>lambdaJoin() | ||
| 30 | - .selectCount(PayWalletRechargeDO::getId, WalletSummaryRespDTO::getRechargePayCount) | ||
| 31 | - .selectSum(PayWalletRechargeDO::getPayPrice, WalletSummaryRespDTO::getRechargePayPrice) | ||
| 32 | - .eq(PayWalletRechargeDO::getPayStatus, true) | ||
| 33 | - .between(PayWalletRechargeDO::getPayTime, beginTime, endTime)), 0), | ||
| 34 | - WalletSummaryRespDTO.class); | ||
| 35 | - } | ||
| 36 | - | ||
| 37 | - default WalletSummaryRespDTO selectRechargeSummaryByRefundTimeBetween(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 38 | - return BeanUtil.copyProperties(CollUtil.get(selectMaps(MPJWrappers.<PayWalletRechargeDO>lambdaJoin() | ||
| 39 | - .selectCount(PayWalletRechargeDO::getId, WalletSummaryRespDTO::getRechargeRefundCount) | ||
| 40 | - .selectSum(PayWalletRechargeDO::getRefundPayPrice, WalletSummaryRespDTO::getRechargeRefundPrice) | ||
| 41 | - .eq(PayWalletRechargeDO::getRefundStatus, PayRefundStatusEnum.SUCCESS.getStatus()) | ||
| 42 | - .between(PayWalletRechargeDO::getRefundTime, beginTime, endTime)), 0), | ||
| 43 | - WalletSummaryRespDTO.class); | ||
| 44 | - } | ||
| 45 | - | ||
| 46 | } | 21 | } |
| 47 | 22 | ||
| 48 | 23 |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletTransactionMapper.java
| @@ -6,12 +6,9 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | @@ -6,12 +6,9 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 7 | import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO; | 7 | import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO; |
| 8 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; | 8 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; |
| 9 | -import com.github.yulichang.toolkit.MPJWrappers; | ||
| 10 | import org.apache.ibatis.annotations.Mapper; | 9 | import org.apache.ibatis.annotations.Mapper; |
| 11 | 10 | ||
| 12 | -import java.time.LocalDateTime; | ||
| 13 | import java.util.Objects; | 11 | import java.util.Objects; |
| 14 | -import java.util.Optional; | ||
| 15 | 12 | ||
| 16 | @Mapper | 13 | @Mapper |
| 17 | public interface PayWalletTransactionMapper extends BaseMapperX<PayWalletTransactionDO> { | 14 | public interface PayWalletTransactionMapper extends BaseMapperX<PayWalletTransactionDO> { |
| @@ -38,15 +35,6 @@ public interface PayWalletTransactionMapper extends BaseMapperX<PayWalletTransac | @@ -38,15 +35,6 @@ public interface PayWalletTransactionMapper extends BaseMapperX<PayWalletTransac | ||
| 38 | PayWalletTransactionDO::getBizType, bizType); | 35 | PayWalletTransactionDO::getBizType, bizType); |
| 39 | } | 36 | } |
| 40 | 37 | ||
| 41 | - default Integer selectSummaryByBizTypeAndCreateTimeBetween(Integer type, LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 42 | - return Optional.ofNullable(selectOne(MPJWrappers.<PayWalletTransactionDO>lambdaJoin() | ||
| 43 | - .selectSum(PayWalletTransactionDO::getPrice) | ||
| 44 | - .eq(PayWalletTransactionDO::getBizType, type) | ||
| 45 | - .between(PayWalletTransactionDO::getCreateTime, beginTime, endTime))) | ||
| 46 | - .map(PayWalletTransactionDO::getPrice) | ||
| 47 | - .orElse(0); | ||
| 48 | - } | ||
| 49 | - | ||
| 50 | } | 38 | } |
| 51 | 39 | ||
| 52 | 40 |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeService.java
| 1 | package cn.iocoder.yudao.module.pay.service.wallet; | 1 | package cn.iocoder.yudao.module.pay.service.wallet; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.pay.api.wallet.dto.WalletSummaryRespDTO; | ||
| 4 | import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge.AppPayWalletRechargeCreateReqVO; | 3 | import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge.AppPayWalletRechargeCreateReqVO; |
| 5 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargeDO; | 4 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletRechargeDO; |
| 6 | 5 | ||
| 7 | -import java.time.LocalDateTime; | ||
| 8 | - | ||
| 9 | /** | 6 | /** |
| 10 | * 钱包充值 Service 接口 | 7 | * 钱包充值 Service 接口 |
| 11 | * | 8 | * |
| @@ -16,8 +13,8 @@ public interface PayWalletRechargeService { | @@ -16,8 +13,8 @@ public interface PayWalletRechargeService { | ||
| 16 | /** | 13 | /** |
| 17 | * 创建钱包充值记录(发起充值) | 14 | * 创建钱包充值记录(发起充值) |
| 18 | * | 15 | * |
| 19 | - * @param userId 用户 id | ||
| 20 | - * @param userType 用户类型 | 16 | + * @param userId 用户 id |
| 17 | + * @param userType 用户类型 | ||
| 21 | * @param createReqVO 钱包充值请求 VO | 18 | * @param createReqVO 钱包充值请求 VO |
| 22 | * @return 钱包充值记录 | 19 | * @return 钱包充值记录 |
| 23 | */ | 20 | */ |
| @@ -27,32 +24,25 @@ public interface PayWalletRechargeService { | @@ -27,32 +24,25 @@ public interface PayWalletRechargeService { | ||
| 27 | /** | 24 | /** |
| 28 | * 更新钱包充值成功 | 25 | * 更新钱包充值成功 |
| 29 | * | 26 | * |
| 30 | - * @param id 钱包充值记录 id | 27 | + * @param id 钱包充值记录 id |
| 31 | * @param payOrderId 支付订单 id | 28 | * @param payOrderId 支付订单 id |
| 32 | */ | 29 | */ |
| 33 | void updateWalletRechargerPaid(Long id, Long payOrderId); | 30 | void updateWalletRechargerPaid(Long id, Long payOrderId); |
| 34 | 31 | ||
| 35 | /** | 32 | /** |
| 36 | * 发起钱包充值退款 | 33 | * 发起钱包充值退款 |
| 37 | - * @param id 钱包充值编号 | 34 | + * |
| 35 | + * @param id 钱包充值编号 | ||
| 38 | * @param userIp 用户 ip 地址 | 36 | * @param userIp 用户 ip 地址 |
| 39 | */ | 37 | */ |
| 40 | void refundWalletRecharge(Long id, String userIp); | 38 | void refundWalletRecharge(Long id, String userIp); |
| 41 | 39 | ||
| 42 | /** | 40 | /** |
| 43 | * 更新钱包充值记录为已退款 | 41 | * 更新钱包充值记录为已退款 |
| 44 | - * @param id 钱包充值 id | 42 | + * |
| 43 | + * @param id 钱包充值 id | ||
| 45 | * @param payRefundId 退款单id | 44 | * @param payRefundId 退款单id |
| 46 | */ | 45 | */ |
| 47 | void updateWalletRechargeRefunded(Long id, Long payRefundId); | 46 | void updateWalletRechargeRefunded(Long id, Long payRefundId); |
| 48 | 47 | ||
| 49 | - /** | ||
| 50 | - * 获取钱包统计 | ||
| 51 | - * | ||
| 52 | - * @param beginTime 起始时间 | ||
| 53 | - * @param endTime 截止时间 | ||
| 54 | - * @return 钱包统计 | ||
| 55 | - */ | ||
| 56 | - WalletSummaryRespDTO getWalletSummary(LocalDateTime beginTime, LocalDateTime endTime); | ||
| 57 | - | ||
| 58 | } | 48 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java
| @@ -4,7 +4,6 @@ import cn.hutool.core.lang.Assert; | @@ -4,7 +4,6 @@ import cn.hutool.core.lang.Assert; | ||
| 4 | import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; | 4 | import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; |
| 5 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; | 5 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; |
| 6 | import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; | 6 | import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; |
| 7 | -import cn.iocoder.yudao.module.pay.api.wallet.dto.WalletSummaryRespDTO; | ||
| 8 | import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge.AppPayWalletRechargeCreateReqVO; | 7 | import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge.AppPayWalletRechargeCreateReqVO; |
| 9 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; | 8 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; |
| 10 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; | 9 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; |
| @@ -279,15 +278,4 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService { | @@ -279,15 +278,4 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService { | ||
| 279 | return payOrder; | 278 | return payOrder; |
| 280 | } | 279 | } |
| 281 | 280 | ||
| 282 | - @Override | ||
| 283 | - public WalletSummaryRespDTO getWalletSummary(LocalDateTime beginTime, LocalDateTime endTime) { | ||
| 284 | - WalletSummaryRespDTO paySummary = walletRechargeMapper.selectRechargeSummaryByPayTimeBetween(beginTime, endTime); | ||
| 285 | - WalletSummaryRespDTO refundSummary = walletRechargeMapper.selectRechargeSummaryByRefundTimeBetween(beginTime, endTime); | ||
| 286 | - | ||
| 287 | - paySummary.setRechargeRefundCount(refundSummary.getRechargeRefundCount()); | ||
| 288 | - paySummary.setRechargeRefundPrice(refundSummary.getRechargeRefundPrice()); | ||
| 289 | - | ||
| 290 | - return paySummary; | ||
| 291 | - } | ||
| 292 | - | ||
| 293 | } | 281 | } |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java
| 1 | package cn.iocoder.yudao.module.pay.service.wallet; | 1 | package cn.iocoder.yudao.module.pay.service.wallet; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.pay.api.wallet.dto.WalletSummaryRespDTO; | ||
| 4 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; | 3 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; |
| 5 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; | 4 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO; |
| 6 | import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; | 5 | import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; |
| 7 | 6 | ||
| 8 | -import java.time.LocalDateTime; | ||
| 9 | - | ||
| 10 | /** | 7 | /** |
| 11 | * 钱包 Service 接口 | 8 | * 钱包 Service 接口 |
| 12 | * | 9 | * |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java
| 1 | package cn.iocoder.yudao.module.pay.service.wallet; | 1 | package cn.iocoder.yudao.module.pay.service.wallet; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.lang.Assert; | 3 | import cn.hutool.core.lang.Assert; |
| 4 | -import cn.iocoder.yudao.module.pay.api.wallet.dto.WalletSummaryRespDTO; | ||
| 5 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; | 4 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; |
| 6 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; | 5 | import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; |
| 7 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; | 6 | import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletTransactionService.java
| @@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; | @@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum; | ||
| 7 | import cn.iocoder.yudao.module.pay.service.wallet.bo.WalletTransactionCreateReqBO; | 7 | import cn.iocoder.yudao.module.pay.service.wallet.bo.WalletTransactionCreateReqBO; |
| 8 | 8 | ||
| 9 | import javax.validation.Valid; | 9 | import javax.validation.Valid; |
| 10 | -import java.time.LocalDateTime; | ||
| 11 | 10 | ||
| 12 | /** | 11 | /** |
| 13 | * 钱包余额流水 Service 接口 | 12 | * 钱包余额流水 Service 接口 |
| @@ -50,14 +49,4 @@ public interface PayWalletTransactionService { | @@ -50,14 +49,4 @@ public interface PayWalletTransactionService { | ||
| 50 | */ | 49 | */ |
| 51 | PayWalletTransactionDO getWalletTransaction(String bizId, PayWalletBizTypeEnum type); | 50 | PayWalletTransactionDO getWalletTransaction(String bizId, PayWalletBizTypeEnum type); |
| 52 | 51 | ||
| 53 | - /** | ||
| 54 | - * 获取支付金额合计 | ||
| 55 | - * | ||
| 56 | - * @param bizType 业务类型 | ||
| 57 | - * @param beginTime 开始时间 | ||
| 58 | - * @param endTime 结束时间 | ||
| 59 | - * @return 支付金额合计 | ||
| 60 | - */ | ||
| 61 | - Integer getPriceSummary(PayWalletBizTypeEnum bizType, LocalDateTime beginTime, LocalDateTime endTime); | ||
| 62 | - | ||
| 63 | } | 52 | } |