mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-09-16 01:51:52 +08:00
Merge remote-tracking branch 'yudao/feature/mall_product' into feature/mall_product
# Conflicts: # yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
<name>${project.artifactId}</name>
|
||||
|
||||
<description>
|
||||
商城大模块,由 product 商品、promotion 营销、trade 交易等组成
|
||||
商城大模块,由 product 商品、promotion 营销、trade 交易、statistics 统计等组成
|
||||
</description>
|
||||
<modules>
|
||||
<module>yudao-module-promotion-api</module>
|
||||
@@ -24,6 +24,8 @@
|
||||
<module>yudao-module-product-biz</module>
|
||||
<module>yudao-module-trade-api</module>
|
||||
<module>yudao-module-trade-biz</module>
|
||||
<module>yudao-module-statistics-api</module>
|
||||
<module>yudao-module-statistics-biz</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
@@ -110,11 +110,6 @@ public class ProductSpuRespDTO {
|
||||
|
||||
// ========== 物流相关字段 =========
|
||||
|
||||
/**
|
||||
* 赠送积分
|
||||
*/
|
||||
private Integer giveIntegral;
|
||||
|
||||
/**
|
||||
* 物流配置模板编号
|
||||
*
|
||||
@@ -122,6 +117,13 @@ public class ProductSpuRespDTO {
|
||||
*/
|
||||
private Long deliveryTemplateId;
|
||||
|
||||
// ========== 营销相关字段 =========
|
||||
|
||||
/**
|
||||
* 赠送积分
|
||||
*/
|
||||
private Integer giveIntegral;
|
||||
|
||||
// ========== 统计相关字段 =========
|
||||
|
||||
/**
|
||||
|
@@ -9,47 +9,47 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||
*/
|
||||
public interface ErrorCodeConstants {
|
||||
|
||||
// ========== 商品分类相关 1008001000 ============
|
||||
ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1008001000, "商品分类不存在");
|
||||
ErrorCode CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1008001001, "父分类不存在");
|
||||
ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类");
|
||||
ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除");
|
||||
ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用");
|
||||
ErrorCode CATEGORY_HAVE_BIND_SPU = new ErrorCode(1008001005, "类别下存在商品,无法删除");
|
||||
// ========== 商品分类相关 1-008-001-000 ============
|
||||
ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1_008_001_000, "商品分类不存在");
|
||||
ErrorCode CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1_008_001_001, "父分类不存在");
|
||||
ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1_008_001_002, "父分类不能是二级分类");
|
||||
ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1_008_001_003, "存在子分类,无法删除");
|
||||
ErrorCode CATEGORY_DISABLED = new ErrorCode(1_008_001_004, "商品分类({})已禁用,无法使用");
|
||||
ErrorCode CATEGORY_HAVE_BIND_SPU = new ErrorCode(1_008_001_005, "类别下存在商品,无法删除");
|
||||
|
||||
// ========== 商品品牌相关编号 1008002000 ==========
|
||||
ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
|
||||
ErrorCode BRAND_DISABLED = new ErrorCode(1008002001, "品牌已禁用");
|
||||
ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1008002002, "品牌名称已存在");
|
||||
// ========== 商品品牌相关编号 1-008-002-000 ==========
|
||||
ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1_008_002_000, "品牌不存在");
|
||||
ErrorCode BRAND_DISABLED = new ErrorCode(1_008_002_001, "品牌已禁用");
|
||||
ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1_008_002_002, "品牌名称已存在");
|
||||
|
||||
// ========== 商品属性项 1008003000 ==========
|
||||
ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "属性项不存在");
|
||||
ErrorCode PROPERTY_EXISTS = new ErrorCode(1008003001, "属性项的名称已存在");
|
||||
ErrorCode PROPERTY_DELETE_FAIL_VALUE_EXISTS = new ErrorCode(1008003002, "属性项下存在属性值,无法删除");
|
||||
// ========== 商品属性项 1-008-003-000 ==========
|
||||
ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1_008_003_000, "属性项不存在");
|
||||
ErrorCode PROPERTY_EXISTS = new ErrorCode(1_008_003_001, "属性项的名称已存在");
|
||||
ErrorCode PROPERTY_DELETE_FAIL_VALUE_EXISTS = new ErrorCode(1_008_003_002, "属性项下存在属性值,无法删除");
|
||||
|
||||
// ========== 商品属性值 1008004000 ==========
|
||||
ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "属性值不存在");
|
||||
ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1008004001, "属性值的名称已存在");
|
||||
// ========== 商品属性值 1-008-004-000 ==========
|
||||
ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1_008_004_000, "属性值不存在");
|
||||
ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1_008_004_001, "属性值的名称已存在");
|
||||
|
||||
// ========== 商品 SPU 1008005000 ==========
|
||||
ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在");
|
||||
ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1008005001, "商品分类不正确,原因:必须使用第二级的商品分类及以下");
|
||||
ErrorCode SPU_NOT_ENABLE = new ErrorCode(1008005002, "商品 SPU 不处于上架状态");
|
||||
ErrorCode SPU_NOT_RECYCLE = new ErrorCode(1008005003, "商品 SPU 不处于回收站状态");
|
||||
// ========== 商品 SPU 1-008-005-000 ==========
|
||||
ErrorCode SPU_NOT_EXISTS = new ErrorCode(1_008_005_000, "商品 SPU 不存在");
|
||||
ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1_008_005_001, "商品分类不正确,原因:必须使用第二级的商品分类及以下");
|
||||
ErrorCode SPU_NOT_ENABLE = new ErrorCode(1_008_005_002, "商品 SPU 不处于上架状态");
|
||||
ErrorCode SPU_NOT_RECYCLE = new ErrorCode(1_008_005_003, "商品 SPU 不处于回收站状态");
|
||||
|
||||
// ========== 商品 SKU 1008006000 ==========
|
||||
ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在");
|
||||
ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品 SKU 的属性组合存在重复");
|
||||
ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU,其属性项必须一致");
|
||||
ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU,必须不重复");
|
||||
ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1008006004, "商品 SKU 库存不足");
|
||||
// ========== 商品 SKU 1-008-006-000 ==========
|
||||
ErrorCode SKU_NOT_EXISTS = new ErrorCode(1_008_006_000, "商品 SKU 不存在");
|
||||
ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1_008_006_001, "商品 SKU 的属性组合存在重复");
|
||||
ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1_008_006_002, "一个 SPU 下的每个 SKU,其属性项必须一致");
|
||||
ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1_008_006_003, "一个 SPU 下的每个 SKU,必须不重复");
|
||||
ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1_008_006_004, "商品 SKU 库存不足");
|
||||
|
||||
// ========== 商品 评价 1008007000 ==========
|
||||
ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1008007000, "商品评价不存在");
|
||||
ErrorCode COMMENT_ORDER_EXISTS = new ErrorCode(1008007001, "订单的商品评价已存在");
|
||||
// ========== 商品 评价 1-008-007-000 ==========
|
||||
ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1_008_007_000, "商品评价不存在");
|
||||
ErrorCode COMMENT_ORDER_EXISTS = new ErrorCode(1_008_007_001, "订单的商品评价已存在");
|
||||
|
||||
// ========== 商品 收藏 1008008000 ==========
|
||||
ErrorCode FAVORITE_EXISTS = new ErrorCode(1008008000, "该商品已经被收藏");
|
||||
ErrorCode FAVORITE_NOT_EXISTS = new ErrorCode(1008008001, "商品收藏不存在");
|
||||
// ========== 商品 收藏 1-008-008-000 ==========
|
||||
ErrorCode FAVORITE_EXISTS = new ErrorCode(1_008_008_000, "该商品已经被收藏");
|
||||
ErrorCode FAVORITE_NOT_EXISTS = new ErrorCode(1_008_008_001, "商品收藏不存在");
|
||||
|
||||
}
|
||||
|
@@ -140,4 +140,5 @@ public class AppProductSpuController {
|
||||
return price - newPrice;
|
||||
}
|
||||
|
||||
// TODO 芋艿:商品的浏览记录;
|
||||
}
|
||||
|
@@ -68,7 +68,7 @@ public class RewardActivityMatchRespDTO {
|
||||
*/
|
||||
private List<Long> couponIds;
|
||||
/**
|
||||
* 赠送的优惠卷数量的数组
|
||||
* 赠送的优惠券数量的数组
|
||||
*/
|
||||
private List<Integer> couponCounts;
|
||||
|
||||
|
@@ -9,66 +9,75 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||
*/
|
||||
public interface ErrorCodeConstants {
|
||||
|
||||
// ========== 促销活动相关 1013001000 ============
|
||||
ErrorCode DISCOUNT_ACTIVITY_NOT_EXISTS = new ErrorCode(1013001000, "限时折扣活动不存在");
|
||||
ErrorCode DISCOUNT_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013001001, "存在商品参加了其它限时折扣活动");
|
||||
ErrorCode DISCOUNT_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013001002, "限时折扣活动已关闭,不能修改");
|
||||
ErrorCode DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1013001003, "限时折扣活动未关闭,不能删除");
|
||||
ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013001004, "限时折扣活动已关闭,不能重复关闭");
|
||||
ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1013001005, "限时折扣活动已结束,不能关闭");
|
||||
// ========== 促销活动相关 1-013-001-000 ============
|
||||
ErrorCode DISCOUNT_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_001_000, "限时折扣活动不存在");
|
||||
ErrorCode DISCOUNT_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_001_001, "存在商品参加了其它限时折扣活动");
|
||||
ErrorCode DISCOUNT_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_002, "限时折扣活动已关闭,不能修改");
|
||||
ErrorCode DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_001_003, "限时折扣活动未关闭,不能删除");
|
||||
ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_004, "限时折扣活动已关闭,不能重复关闭");
|
||||
ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1_013_001_005, "限时折扣活动已结束,不能关闭");
|
||||
|
||||
// ========== Banner 相关 1013002000 ============
|
||||
ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1013002000, "Banner 不存在");
|
||||
// ========== Banner 相关 1-013-002-000 ============
|
||||
ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1_013_002_000, "Banner 不存在");
|
||||
|
||||
// ========== Coupon 相关 1013003000 ============
|
||||
ErrorCode COUPON_NO_MATCH_SPU = new ErrorCode(1013003000, "优惠劵没有可使用的商品!");
|
||||
ErrorCode COUPON_NO_MATCH_MIN_PRICE = new ErrorCode(1013003001, "所结算的商品中未满足使用的金额");
|
||||
// ========== Coupon 相关 1-013-003-000 ============
|
||||
ErrorCode COUPON_NO_MATCH_SPU = new ErrorCode(1_013_003_000, "优惠劵没有可使用的商品!");
|
||||
ErrorCode COUPON_NO_MATCH_MIN_PRICE = new ErrorCode(1_013_003_001, "所结算的商品中未满足使用的金额");
|
||||
|
||||
// ========== 优惠劵模板 1013004000 ==========
|
||||
ErrorCode COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1013004000, "优惠劵模板不存在");
|
||||
ErrorCode COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL = new ErrorCode(1013004001, "发放数量不能小于已领取数量({})");
|
||||
ErrorCode COUPON_TEMPLATE_NOT_ENOUGH = new ErrorCode(1013004002, "当前剩余数量不够领取");
|
||||
ErrorCode COUPON_TEMPLATE_USER_ALREADY_TAKE = new ErrorCode(1013004003, "用户已领取过此优惠券");
|
||||
ErrorCode COUPON_TEMPLATE_EXPIRED = new ErrorCode(1013004004, "优惠券已过期");
|
||||
ErrorCode COUPON_TEMPLATE_CANNOT_TAKE = new ErrorCode(1013004005, "领取方式不正确");
|
||||
// ========== 优惠劵模板 1-013-004-000 ==========
|
||||
ErrorCode COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1_013_004_000, "优惠劵模板不存在");
|
||||
ErrorCode COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL = new ErrorCode(1_013_004_001, "发放数量不能小于已领取数量({})");
|
||||
ErrorCode COUPON_TEMPLATE_NOT_ENOUGH = new ErrorCode(1_013_004_002, "当前剩余数量不够领取");
|
||||
ErrorCode COUPON_TEMPLATE_USER_ALREADY_TAKE = new ErrorCode(1_013_004_003, "用户已领取过此优惠券");
|
||||
ErrorCode COUPON_TEMPLATE_EXPIRED = new ErrorCode(1_013_004_004, "优惠券已过期");
|
||||
ErrorCode COUPON_TEMPLATE_CANNOT_TAKE = new ErrorCode(1_013_004_005, "领取方式不正确");
|
||||
|
||||
// ========== 优惠劵 1013005000 ==========
|
||||
ErrorCode COUPON_NOT_EXISTS = new ErrorCode(1013005000, "优惠券不存在");
|
||||
ErrorCode COUPON_DELETE_FAIL_USED = new ErrorCode(1013005001, "回收优惠劵失败,优惠劵已被使用");
|
||||
ErrorCode COUPON_STATUS_NOT_UNUSED = new ErrorCode(1013005002, "优惠劵不处于待使用状态");
|
||||
ErrorCode COUPON_VALID_TIME_NOT_NOW = new ErrorCode(1013005003, "优惠券不在使用时间范围内");
|
||||
ErrorCode COUPON_STATUS_NOT_USED = new ErrorCode(1013005004, "优惠劵不是已使用状态");
|
||||
// ========== 优惠劵 1-013-005-000 ==========
|
||||
ErrorCode COUPON_NOT_EXISTS = new ErrorCode(1_013_005_000, "优惠券不存在");
|
||||
ErrorCode COUPON_DELETE_FAIL_USED = new ErrorCode(1_013_005_001, "回收优惠劵失败,优惠劵已被使用");
|
||||
ErrorCode COUPON_STATUS_NOT_UNUSED = new ErrorCode(1_013_005_002, "优惠劵不处于待使用状态");
|
||||
ErrorCode COUPON_VALID_TIME_NOT_NOW = new ErrorCode(1_013_005_003, "优惠券不在使用时间范围内");
|
||||
ErrorCode COUPON_STATUS_NOT_USED = new ErrorCode(1_013_005_004, "优惠劵不是已使用状态");
|
||||
|
||||
// ========== 满减送活动 1013006000 ==========
|
||||
ErrorCode REWARD_ACTIVITY_NOT_EXISTS = new ErrorCode(1013006000, "满减送活动不存在");
|
||||
ErrorCode REWARD_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013006001, "存在商品参加了其它满减送活动");
|
||||
ErrorCode REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013006002, "满减送活动已关闭,不能修改");
|
||||
ErrorCode REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1013006003, "满减送活动未关闭,不能删除");
|
||||
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013006004, "满减送活动已关闭,不能重复关闭");
|
||||
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1013006005, "满减送活动已结束,不能关闭");
|
||||
// ========== 满减送活动 1-013-006-000 ==========
|
||||
ErrorCode REWARD_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_006_000, "满减送活动不存在");
|
||||
ErrorCode REWARD_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_006_001, "存在商品参加了其它满减送活动");
|
||||
ErrorCode REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_002, "满减送活动已关闭,不能修改");
|
||||
ErrorCode REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_006_003, "满减送活动未关闭,不能删除");
|
||||
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_004, "满减送活动已关闭,不能重复关闭");
|
||||
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1_013_006_005, "满减送活动已结束,不能关闭");
|
||||
|
||||
// ========== TODO 空着 1013007000 ============
|
||||
// ========== TODO 空着 1-013-007-000 ============
|
||||
|
||||
// ========== 秒杀活动 1013008000 ==========
|
||||
ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1013008000, "秒杀活动不存在");
|
||||
ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013008002, "存在商品参加了其它秒杀活动,秒杀时段冲突");
|
||||
ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改");
|
||||
ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除");
|
||||
ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭");
|
||||
ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "秒杀失败,原因秒杀库存不足");
|
||||
// ========== 秒杀活动 1-013-008-000 ==========
|
||||
ErrorCode SECKILL_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_008_000, "秒杀活动不存在");
|
||||
ErrorCode SECKILL_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_008_002, "存在商品参加了其它秒杀活动,秒杀时段冲突");
|
||||
ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_008_003, "秒杀活动已关闭,不能修改");
|
||||
ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1_013_008_004, "秒杀活动未关闭或未结束,不能删除");
|
||||
ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_008_005, "秒杀活动已关闭,不能重复关闭");
|
||||
ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1_013_008_006, "秒杀失败,原因秒杀库存不足");
|
||||
|
||||
// ========== 秒杀时段 1013009000 ==========
|
||||
ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在");
|
||||
ErrorCode SECKILL_CONFIG_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突");
|
||||
ErrorCode SECKILL_CONFIG_DISABLE = new ErrorCode(1013009004, "秒杀时段已关闭");
|
||||
// ========== 秒杀时段 1-013-009-000 ==========
|
||||
ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1_013_009_000, "秒杀时段不存在");
|
||||
ErrorCode SECKILL_CONFIG_TIME_CONFLICTS = new ErrorCode(1_013_009_001, "秒杀时段冲突");
|
||||
ErrorCode SECKILL_CONFIG_DISABLE = new ErrorCode(1_013_009_004, "秒杀时段已关闭");
|
||||
|
||||
// ========== 拼团活动 1013010000 ==========
|
||||
ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在");
|
||||
ErrorCode COMBINATION_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013010001, "存在商品参加了其它拼团活动");
|
||||
ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE = new ErrorCode(1013010002, "拼团活动已关闭不能修改");
|
||||
ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013010003, "拼团活动未关闭或未结束,不能删除");
|
||||
ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010004, "拼团失败,原因:拼团活动已关闭");
|
||||
// ========== 拼团活动 1-013-010-000 ==========
|
||||
ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_010_000, "拼团活动不存在");
|
||||
ErrorCode COMBINATION_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_010_001, "存在商品参加了其它拼团活动");
|
||||
ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE = new ErrorCode(1_013_010_002, "拼团活动已关闭不能修改");
|
||||
ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1_013_010_003, "拼团活动未关闭或未结束,不能删除");
|
||||
ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1_013_010_004, "拼团失败,原因:拼团活动已关闭");
|
||||
|
||||
// ========== 拼团记录 1-013-011-000 ==========
|
||||
ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1_013_011_000, "拼团不存在");
|
||||
ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1_013_011_001, "拼团失败,已参与过该拼团");
|
||||
ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1_013_011_002, "拼团失败,父拼团不存在");
|
||||
ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1_013_011_003, "拼团失败,拼团人数已满");
|
||||
ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1_013_011_004, "拼团失败,已参与其它拼团");
|
||||
ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1_013_011_005, "拼团失败,活动已经结束");
|
||||
ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_011_006, "拼团失败,原因:单次限购超出");
|
||||
ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_011_007, "拼团失败,原因:超出总购买次数");
|
||||
// ========== 拼团记录 1013011000 ==========
|
||||
ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013011000, "拼团不存在");
|
||||
ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011001, "拼团失败,已参与过该拼团");
|
||||
@@ -80,17 +89,17 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:单次限购超出");
|
||||
ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011008, "拼团失败,原因:超出总购买次数");
|
||||
|
||||
// ========== 砍价活动 1013012000 ==========
|
||||
ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1013012000, "砍价活动不存在");
|
||||
ErrorCode BARGAIN_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013012001, "存在商品参加了其它砍价活动");
|
||||
ErrorCode BARGAIN_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013012002, "砍价活动已关闭不能修改");
|
||||
ErrorCode BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013012003, "砍价活动未关闭或未结束,不能删除");
|
||||
ErrorCode BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013012004, "砍价失败,原因:该砍价活动库存不足");
|
||||
// ========== 砍价活动 1-013-012-000 ==========
|
||||
ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_012_000, "砍价活动不存在");
|
||||
ErrorCode BARGAIN_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_012_001, "存在商品参加了其它砍价活动");
|
||||
ErrorCode BARGAIN_ACTIVITY_STATUS_DISABLE = new ErrorCode(1_013_012_002, "砍价活动已关闭不能修改");
|
||||
ErrorCode BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1_013_012_003, "砍价活动未关闭或未结束,不能删除");
|
||||
ErrorCode BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1_013_012_004, "砍价失败,原因:该砍价活动库存不足");
|
||||
|
||||
// ========== 砍价记录 1013013000 ==========
|
||||
ErrorCode BARGAIN_RECORD_NOT_EXISTS = new ErrorCode(1013013000, "砍价记录不存在");
|
||||
ErrorCode BARGAIN_RECORD_EXISTS = new ErrorCode(1013013001, "砍价失败,已参与过该砍价");
|
||||
ErrorCode BARGAIN_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013013002, "砍价失败,父砍价不存在");
|
||||
ErrorCode BARGAIN_RECORD_USER_FULL = new ErrorCode(1013013003, "砍价失败,砍价人数已满");
|
||||
// ========== 砍价记录 1-013-013-000 ==========
|
||||
ErrorCode BARGAIN_RECORD_NOT_EXISTS = new ErrorCode(1_013_013_000, "砍价记录不存在");
|
||||
ErrorCode BARGAIN_RECORD_EXISTS = new ErrorCode(1_013_013_001, "砍价失败,已参与过该砍价");
|
||||
ErrorCode BARGAIN_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1_013_013_002, "砍价失败,父砍价不存在");
|
||||
ErrorCode BARGAIN_RECORD_USER_FULL = new ErrorCode(1_013_013_003, "砍价失败,砍价人数已满");
|
||||
|
||||
}
|
||||
|
@@ -15,9 +15,9 @@ import java.util.Arrays;
|
||||
@AllArgsConstructor
|
||||
public enum PromotionProductScopeEnum implements IntArrayValuable {
|
||||
|
||||
ALL(1, "通用卷"), // 全部商品
|
||||
SPU(2, "商品卷"), // 指定商品
|
||||
CATEGORY(3, "品类卷"), // 指定商品
|
||||
ALL(1, "通用券"), // 全部商品
|
||||
SPU(2, "商品券"), // 指定商品
|
||||
CATEGORY(3, "品类券"), // 指定品类
|
||||
;
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionProductScopeEnum::getScope).toArray();
|
||||
|
@@ -45,6 +45,10 @@
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-weixin</artifactId>
|
||||
|
@@ -37,15 +37,6 @@ public class CouponController {
|
||||
@Resource
|
||||
private MemberUserApi memberUserApi;
|
||||
|
||||
// @GetMapping("/get")
|
||||
// @Operation(summary = "获得优惠劵")
|
||||
// @Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
// @PreAuthorize("@ss.hasPermission('promotion:coupon:query')")
|
||||
// public CommonResult<CouponRespVO> getCoupon(@RequestParam("id") Long id) {
|
||||
// CouponDO coupon = couponService.getCoupon(id);
|
||||
// return success(CouponConvert.INSTANCE.convert(coupon));
|
||||
// }
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "回收优惠劵")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
|
@@ -1,6 +1,8 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -8,6 +10,7 @@ import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@@ -21,6 +24,7 @@ public class CouponPageReqVO extends PageParam {
|
||||
private Long templateId;
|
||||
|
||||
@Schema(description = "优惠码状态", example = "1")
|
||||
@InEnum(value = CouponStatusEnum.class, message = "优惠劵状态,必须是 {value}")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@@ -30,4 +34,7 @@ public class CouponPageReqVO extends PageParam {
|
||||
@Schema(description = "用户昵称", example = "芋艿")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "用户编号", example = "1")
|
||||
private Collection<Long> userIds;
|
||||
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
@@ -33,8 +34,15 @@ public class CouponTemplatePageReqVO extends PageParam {
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
@Schema(description = "可以领取的类型", example = "[1,2, 3]")
|
||||
@Schema(description = "可以领取的类型", example = "[1, 2, 3]")
|
||||
@InEnum(value = CouponTakeTypeEnum.class, message = "可以领取的类型,必须是 {value}")
|
||||
private List<Integer> canTakeTypes;
|
||||
|
||||
@Schema(description = "商品范围", example = "1")
|
||||
@InEnum(value = PromotionProductScopeEnum.class, message = "商品范围,必须是 {value}")
|
||||
private Integer productScope;
|
||||
|
||||
@Schema(description = "商品范围编号", example = "1")
|
||||
private Long productScopeValue;
|
||||
|
||||
}
|
||||
|
@@ -84,7 +84,7 @@ public class RewardActivityBaseVO {
|
||||
@Schema(description = "赠送的优惠劵编号的数组", example = "1,2,3")
|
||||
private List<Long> couponIds;
|
||||
|
||||
@Schema(description = "赠送的优惠卷数量的数组", example = "1,2,3")
|
||||
@Schema(description = "赠送的优惠券数量的数组", example = "1,2,3")
|
||||
private List<Integer> couponCounts;
|
||||
|
||||
@AssertTrue(message = "优惠劵和数量必须一一对应")
|
||||
|
@@ -9,41 +9,41 @@ import java.time.LocalDateTime;
|
||||
@Data
|
||||
public class AppArticleRespVO {
|
||||
|
||||
@Schema(description = "文章编号", required = true, example = "1")
|
||||
@Schema(description = "文章编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "文章标题", required = true, example = "芋道源码 - 促销模块")
|
||||
@Schema(description = "文章标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码 - 促销模块")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "文章作者", required = true, example = "芋道源码")
|
||||
@Schema(description = "文章作者", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
|
||||
private String author;
|
||||
|
||||
@Schema(description = "分类编号", required = true, example = "2048")
|
||||
@Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
|
||||
private Long categoryId;
|
||||
|
||||
@Schema(description = "图文封面", required = true, example = "https://www.iocoder.cn/1.png")
|
||||
@Schema(description = "图文封面", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
|
||||
private String picUrl;
|
||||
|
||||
@Schema(description = "文章简介", required = true, example = "我是简介")
|
||||
@Schema(description = "文章简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是简介")
|
||||
private String introduction;
|
||||
|
||||
@Schema(description = "文章内容", required = true, example = "我是详细")
|
||||
@Schema(description = "文章内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是详细")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "发布时间", required = true)
|
||||
@Schema(description = "发布时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "浏览量", required = true, example = "1024")
|
||||
@Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer browseCount;
|
||||
|
||||
@Schema(description = "关联的商品 SPU 编号", example = "1024")
|
||||
private Long spuId;
|
||||
|
||||
// TODO 芋艿:下面 2 个字段,后端要存储,前端不用返回;
|
||||
// @Schema(description = "是否热卖推荐", required = true, example = "true")
|
||||
// @Schema(description = "是否热卖推荐", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
// private Boolean recommendHot;
|
||||
//
|
||||
// @Schema(description = "是否 Banner 推荐", required = true, example = "true")
|
||||
// @Schema(description = "是否 Banner 推荐", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
// private Boolean recommendBanner;
|
||||
|
||||
}
|
||||
|
@@ -7,20 +7,20 @@ import lombok.Data;
|
||||
@Data
|
||||
public class AppArticleCategoryRespVO {
|
||||
|
||||
@Schema(description = "分类编号", required = true, example = "1")
|
||||
@Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "分类名称", required = true, example = "技术")
|
||||
@Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "技术")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "分类图标", required = true, example = "https://www.iocoder.cn/1.png")
|
||||
@Schema(description = "分类图标", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png")
|
||||
private String picUrl;
|
||||
|
||||
// TODO 芋艿:下面 2 个字段,后端要存储,前端不用返回;
|
||||
// @Schema(description = "状态", required = true, example = "1")
|
||||
// @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
// private Integer status;
|
||||
//
|
||||
// @Schema(description = "排序", required = true, example = "1024")
|
||||
// @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
// private Integer sort;
|
||||
|
||||
}
|
||||
|
@@ -9,46 +9,46 @@ import java.time.LocalDateTime;
|
||||
@Data
|
||||
public class AppBargainActivityDetailRespVO {
|
||||
|
||||
@Schema(description = "砍价活动编号", required = true, example = "1024")
|
||||
@Schema(description = "砍价活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "砍价活动名称", required = true, example = "618 大砍价")
|
||||
@Schema(description = "砍价活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618 大砍价")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "活动开始时间", required = true)
|
||||
@Schema(description = "活动开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@Schema(description = "活动结束时间", required = true)
|
||||
@Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "商品 SPU 编号", required = true, example = "2048")
|
||||
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
|
||||
private Long spuId;
|
||||
|
||||
@Schema(description = "商品 SKU 编号", required = true, example = "1024")
|
||||
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long skuId;
|
||||
|
||||
@Schema(description = "商品价格,单位:分", required = true, example = "100")
|
||||
@Schema(description = "商品价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||
private Integer price;
|
||||
|
||||
@Schema(description = "商品描述", required = true, example = "我要吃西红柿")
|
||||
@Schema(description = "商品描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "我要吃西红柿")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "砍价库存", required = true, example = "512")
|
||||
@Schema(description = "砍价库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "512")
|
||||
private Integer stock;
|
||||
|
||||
@Schema(description = "商品图片", required = true, example = "4096") // 从 SPU 的 picUrl 读取
|
||||
@Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096") // 从 SPU 的 picUrl 读取
|
||||
private String picUrl;
|
||||
|
||||
@Schema(description = "商品市场价,单位:分", required = true, example = "50") // 从 SPU 的 marketPrice 读取
|
||||
@Schema(description = "商品市场价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") // 从 SPU 的 marketPrice 读取
|
||||
private Integer marketPrice;
|
||||
|
||||
@Schema(description = "商品单位", required = true, example = "个") // 从 SPU 的 unit 读取,然后转换
|
||||
@Schema(description = "商品单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "个") // 从 SPU 的 unit 读取,然后转换
|
||||
private String unitName;
|
||||
|
||||
@Schema(description = "砍价最低金额,单位:分", required = true, example = "100")
|
||||
@Schema(description = "砍价最低金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||
private Integer bargainPrice;
|
||||
|
||||
@Schema(description = "砍价成功数量", required = true, example = "100")
|
||||
@Schema(description = "砍价成功数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||
private Integer successCount;
|
||||
|
||||
}
|
||||
|
@@ -9,34 +9,34 @@ import java.time.LocalDateTime;
|
||||
@Data
|
||||
public class AppBargainActivityRespVO {
|
||||
|
||||
@Schema(description = "砍价活动编号", required = true, example = "1024")
|
||||
@Schema(description = "砍价活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "砍价活动名称", required = true, example = "618 大砍价")
|
||||
@Schema(description = "砍价活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618 大砍价")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "活动开始时间", required = true)
|
||||
@Schema(description = "活动开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@Schema(description = "活动结束时间", required = true)
|
||||
@Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "商品 SPU 编号", required = true, example = "2048")
|
||||
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
|
||||
private Long spuId;
|
||||
|
||||
@Schema(description = "商品 SKU 编号", required = true, example = "1024")
|
||||
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Long skuId;
|
||||
|
||||
@Schema(description = "砍价库存", required = true, example = "512")
|
||||
@Schema(description = "砍价库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "512")
|
||||
private Integer stock;
|
||||
|
||||
@Schema(description = "商品图片", required = true, example = "4096") // 从 SPU 的 picUrl 读取
|
||||
@Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096") // 从 SPU 的 picUrl 读取
|
||||
private String picUrl;
|
||||
|
||||
@Schema(description = "商品市场价,单位:分", required = true, example = "50") // 从 SPU 的 marketPrice 读取
|
||||
@Schema(description = "商品市场价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") // 从 SPU 的 marketPrice 读取
|
||||
private Integer marketPrice;
|
||||
|
||||
@Schema(description = "砍价最低金额,单位:分", required = true, example = "100")
|
||||
@Schema(description = "砍价最低金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||
private Integer bargainPrice;
|
||||
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@ import javax.validation.constraints.NotNull;
|
||||
@Data
|
||||
public class AppBargainHelpCreateReqVO {
|
||||
|
||||
@Schema(description = "砍价记录编号", required = true, example = "1024")
|
||||
@Schema(description = "砍价记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "砍价记录编号不能为空")
|
||||
private Long recordId;
|
||||
|
||||
|
@@ -9,16 +9,16 @@ import java.time.LocalDateTime;
|
||||
@Data
|
||||
public class AppBargainHelpRespVO {
|
||||
|
||||
@Schema(description = "助力用户的昵称", required = true, example = "1024")
|
||||
@Schema(description = "助力用户的昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "助力用户的头像", required = true, example = "1024")
|
||||
@Schema(description = "助力用户的头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "助力用户的砍价金额", required = true, example = "1024")
|
||||
@Schema(description = "助力用户的砍价金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer reducePrice;
|
||||
|
||||
@Schema(description = "创建时间", required = true, example = "1024")
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@ import javax.validation.constraints.NotNull;
|
||||
@Data
|
||||
public class AppBargainRecordCreateReqVO {
|
||||
|
||||
@Schema(description = "砍价活动编号", required = true, example = "1024")
|
||||
@Schema(description = "砍价活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@NotNull(message = "砍价活动编号不能为空")
|
||||
private Long activityId;
|
||||
|
||||
|
@@ -9,23 +9,23 @@ import java.util.List;
|
||||
@Data
|
||||
public class AppBargainRecordSummaryRespVO {
|
||||
|
||||
@Schema(description = "砍价用户数量", required = true, example = "1024")
|
||||
@Schema(description = "砍价用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer userCount;
|
||||
|
||||
@Schema(description = "成功砍价的记录", required = true) // 只返回最近的 7 个
|
||||
@Schema(description = "成功砍价的记录", requiredMode = Schema.RequiredMode.REQUIRED) // 只返回最近的 7 个
|
||||
private List<Record> successRecords;
|
||||
|
||||
@Schema(description = "成功砍价记录")
|
||||
@Data
|
||||
public static class Record {
|
||||
|
||||
@Schema(description = "用户昵称", required = true, example = "王**")
|
||||
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王**")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "用户头像", required = true, example = "https://www.iocoder.cn/xxx.jpg")
|
||||
@Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.jpg")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "活动名称", required = true, example = "天蚕土豆")
|
||||
@Schema(description = "活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "天蚕土豆")
|
||||
private String activityName;
|
||||
|
||||
}
|
||||
|
@@ -1,24 +1,26 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.app.coupon;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.*;
|
||||
import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
|
||||
import cn.iocoder.yudao.module.promotion.service.coupon.CouponTemplateService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
@@ -31,73 +33,42 @@ public class AppCouponController {
|
||||
|
||||
@Resource
|
||||
private CouponService couponService;
|
||||
@Resource
|
||||
private CouponTemplateService couponTemplateService;
|
||||
|
||||
// TODO 芋艿:待实现
|
||||
@PostMapping("/take")
|
||||
@Operation(summary = "领取优惠劵")
|
||||
public CommonResult<Long> takeCoupon(@RequestBody AppCouponTemplatePageReqVO pageReqVO) {
|
||||
return success(1L);
|
||||
@Parameter(name = "templateId", description = "优惠券模板编号", required = true, example = "1024")
|
||||
@PreAuthenticated
|
||||
public CommonResult<Boolean> takeCoupon(@Valid @RequestBody AppCouponTakeReqVO reqVO) {
|
||||
// 1. 领取优惠劵
|
||||
Long userId = getLoginUserId();
|
||||
couponService.takeCoupon(reqVO.getTemplateId(), CollUtil.newHashSet(userId), CouponTakeTypeEnum.USER);
|
||||
|
||||
// 2. 检查是否可以继续领取
|
||||
CouponTemplateDO couponTemplate = couponTemplateService.getCouponTemplate(reqVO.getTemplateId());
|
||||
boolean canTakeAgain = true;
|
||||
if (couponTemplate.getTakeLimitCount() != null && couponTemplate.getTakeLimitCount() > 0) {
|
||||
Integer takeCount = couponService.getTakeCount(reqVO.getTemplateId(), userId);
|
||||
canTakeAgain = takeCount < couponTemplate.getTakeLimitCount();
|
||||
}
|
||||
return success(canTakeAgain);
|
||||
}
|
||||
|
||||
// TODO 芋艿:待实现
|
||||
@GetMapping("/match-list")
|
||||
@Operation(summary = "获得匹配指定商品的优惠劵列表")
|
||||
@Operation(summary = "获得匹配指定商品的优惠劵列表", description = "用于下单页,展示优惠劵列表")
|
||||
public CommonResult<List<AppCouponMatchRespVO>> getMatchCouponList(AppCouponMatchReqVO matchReqVO) {
|
||||
List<AppCouponMatchRespVO> list = new ArrayList<>();
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
AppCouponMatchRespVO vo = new AppCouponMatchRespVO();
|
||||
vo.setId(i + 1L);
|
||||
vo.setName("优惠劵" + (i + 1));
|
||||
vo.setUsePrice(random.nextInt(100) * 100);
|
||||
vo.setValidStartTime(LocalDateTime.now().plusDays(random.nextInt(10)));
|
||||
vo.setValidEndTime(LocalDateTime.now().plusDays(random.nextInt(20) + 10));
|
||||
vo.setDiscountType(random.nextInt(2) + 1);
|
||||
if (vo.getDiscountType() == 1) {
|
||||
vo.setDiscountPercent(null);
|
||||
vo.setDiscountPrice(random.nextInt(50) * 100);
|
||||
vo.setDiscountLimitPrice(null);
|
||||
} else {
|
||||
vo.setDiscountPercent(random.nextInt(90) + 10);
|
||||
vo.setDiscountPrice(null);
|
||||
vo.setDiscountLimitPrice(random.nextInt(200) * 100);
|
||||
}
|
||||
vo.setMatch(random.nextBoolean());
|
||||
if (!vo.getMatch()) {
|
||||
vo.setDescription("不符合条件噢");
|
||||
}
|
||||
list.add(vo);
|
||||
}
|
||||
return success(list);
|
||||
// todo: 优化:优惠金额倒序
|
||||
return success(CouponConvert.INSTANCE.convertList(couponService.getMatchCouponList(getLoginUserId(), matchReqVO)));
|
||||
}
|
||||
|
||||
// TODO 芋艿:待实现
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "优惠劵列表", description = "我的优惠劵")
|
||||
public CommonResult<PageResult<AppCouponRespVO>> takeCoupon(AppCouponPageReqVO pageReqVO) {
|
||||
List<AppCouponRespVO> list = new ArrayList<>();
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
AppCouponRespVO vo = new AppCouponRespVO();
|
||||
vo.setId(i + 1L);
|
||||
vo.setName("优惠劵" + (i + 1));
|
||||
vo.setStatus(pageReqVO.getStatus());
|
||||
vo.setUsePrice(random.nextInt(100) * 100);
|
||||
vo.setValidStartTime(LocalDateTime.now().plusDays(random.nextInt(10)));
|
||||
vo.setValidEndTime(LocalDateTime.now().plusDays(random.nextInt(20) + 10));
|
||||
vo.setDiscountType(random.nextInt(2) + 1);
|
||||
if (vo.getDiscountType() == 1) {
|
||||
vo.setDiscountPercent(null);
|
||||
vo.setDiscountPrice(random.nextInt(50) * 100);
|
||||
vo.setDiscountLimitPrice(null);
|
||||
} else {
|
||||
vo.setDiscountPercent(random.nextInt(90) + 10);
|
||||
vo.setDiscountPrice(null);
|
||||
vo.setDiscountLimitPrice(random.nextInt(200) * 100);
|
||||
}
|
||||
list.add(vo);
|
||||
}
|
||||
return success(new PageResult<>(list, 20L));
|
||||
@Operation(summary = "我的优惠劵列表")
|
||||
@PreAuthenticated
|
||||
public CommonResult<PageResult<AppCouponRespVO>> getCouponPage(AppCouponPageReqVO pageReqVO) {
|
||||
PageResult<CouponDO> pageResult = couponService.getCouponPage(
|
||||
CouponConvert.INSTANCE.convert(pageReqVO, Collections.singleton(getLoginUserId())));
|
||||
return success(CouponConvert.INSTANCE.convertAppPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping(value = "/get-unused-count")
|
||||
|
@@ -1,9 +1,18 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.app.coupon;
|
||||
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
||||
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplateRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.coupon.CouponTemplateConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
|
||||
import cn.iocoder.yudao.module.promotion.service.coupon.CouponTemplateService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@@ -17,11 +26,11 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Tag(name = "用户 App - 优惠劵模板")
|
||||
@RestController
|
||||
@@ -31,8 +40,13 @@ public class AppCouponTemplateController {
|
||||
|
||||
@Resource
|
||||
private CouponTemplateService couponTemplateService;
|
||||
@Resource
|
||||
private CouponService couponService;
|
||||
|
||||
// TODO 芋艿:待实现
|
||||
@Resource
|
||||
private ProductSpuApi productSpuApi;
|
||||
|
||||
// TODO 疯狂:这里应该还有个 list 接口哈;获得优惠劵模版列表,用于首页、商品页的优惠劵
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "获得优惠劵模版列表")
|
||||
@Parameters({
|
||||
@@ -40,9 +54,10 @@ public class AppCouponTemplateController {
|
||||
@Parameter(name = "useType", description = "使用类型"),
|
||||
@Parameter(name = "count", description = "数量", required = true)
|
||||
})
|
||||
public CommonResult<List<AppCouponTemplateRespVO>> getCouponTemplateList(@RequestParam(value = "spuId", required = false) Long spuId,
|
||||
@RequestParam(value = "useType", required = false) Integer useType,
|
||||
@RequestParam(value = "count", required = false, defaultValue = "10") Integer count) {
|
||||
public CommonResult<List<AppCouponTemplateRespVO>> getCouponTemplateList(
|
||||
@RequestParam(value = "spuId", required = false) Long spuId,
|
||||
@RequestParam(value = "useType", required = false) Integer useType,
|
||||
@RequestParam(value = "count", required = false, defaultValue = "10") Integer count) {
|
||||
List<AppCouponTemplateRespVO> list = new ArrayList<>();
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
@@ -69,46 +84,55 @@ public class AppCouponTemplateController {
|
||||
vo.setDiscountPrice(null);
|
||||
vo.setDiscountLimitPrice(random.nextInt(200) * 100);
|
||||
}
|
||||
// TODO @疯狂:是否已领取,要不在 TemplateService 搞个 static 方法,让它基于 countMap 这种去计算,这样好点?
|
||||
vo.setTakeStatus(random.nextBoolean());
|
||||
list.add(vo);
|
||||
}
|
||||
return success(list);
|
||||
}
|
||||
|
||||
// TODO 芋艿:待实现;和 getCouponTemplateList 类似
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得优惠劵模版分页")
|
||||
public CommonResult<PageResult<AppCouponTemplateRespVO>> getCouponTemplatePage(AppCouponTemplatePageReqVO pageReqVO) {
|
||||
List<AppCouponTemplateRespVO> list = new ArrayList<>();
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
AppCouponTemplateRespVO vo = new AppCouponTemplateRespVO();
|
||||
vo.setId(i + 1L);
|
||||
vo.setName("优惠劵" + (i + 1));
|
||||
vo.setTakeLimitCount(random.nextInt(10) + 1);
|
||||
vo.setUsePrice(random.nextInt(100) * 100);
|
||||
vo.setValidityType(random.nextInt(2) + 1);
|
||||
if (vo.getValidityType() == 1) {
|
||||
vo.setValidStartTime(LocalDateTime.now().plusDays(random.nextInt(10)));
|
||||
vo.setValidEndTime(LocalDateTime.now().plusDays(random.nextInt(20) + 10));
|
||||
} else {
|
||||
vo.setFixedStartTerm(random.nextInt(10));
|
||||
vo.setFixedEndTerm(random.nextInt(10) + vo.getFixedStartTerm() + 1);
|
||||
}
|
||||
vo.setDiscountType(random.nextInt(2) + 1);
|
||||
if (vo.getDiscountType() == 1) {
|
||||
vo.setDiscountPercent(null);
|
||||
vo.setDiscountPrice(random.nextInt(50) * 100);
|
||||
vo.setDiscountLimitPrice(null);
|
||||
} else {
|
||||
vo.setDiscountPercent(random.nextInt(90) + 10);
|
||||
vo.setDiscountPrice(null);
|
||||
vo.setDiscountLimitPrice(random.nextInt(200) * 100);
|
||||
}
|
||||
vo.setTakeStatus(random.nextBoolean());
|
||||
list.add(vo);
|
||||
// 1.1 处理查询条件:商品范围编号
|
||||
Long productScopeValue = getProductScopeValue(pageReqVO);
|
||||
// 1.2 处理查询条件:领取方式 = 直接领取
|
||||
List<Integer> canTakeTypes = Collections.singletonList(CouponTakeTypeEnum.USER.getValue());
|
||||
|
||||
// 2. 分页查询
|
||||
PageResult<CouponTemplateDO> pageResult = couponTemplateService.getCouponTemplatePage(
|
||||
CouponTemplateConvert.INSTANCE.convert(pageReqVO, canTakeTypes, pageReqVO.getProductScope(), productScopeValue));
|
||||
|
||||
// 3.1 领取数量
|
||||
Map<Long, Integer> couponTakeCountMap = new HashMap<>(0);
|
||||
Long userId = getLoginUserId();
|
||||
if (userId != null) {
|
||||
List<Long> templateIds = convertList(pageResult.getList(), CouponTemplateDO::getId,
|
||||
t -> ObjUtil.notEqual(t.getTakeLimitCount(), -1)); // 只查有设置“每人限领个数”的
|
||||
couponTakeCountMap = couponService.getTakeCountMapByTemplateIds(templateIds, userId);
|
||||
}
|
||||
return success(new PageResult<>(list, 20L));
|
||||
// 3.2 拼接返回
|
||||
return success(CouponTemplateConvert.INSTANCE.convertAppPage(pageResult, couponTakeCountMap));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得分页查询的商品范围
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 商品范围
|
||||
*/
|
||||
private Long getProductScopeValue(AppCouponTemplatePageReqVO pageReqVO) {
|
||||
// 通用券:清除商品范围
|
||||
if (pageReqVO.getProductScope() == null || ObjectUtils.equalsAny(pageReqVO.getProductScope(), PromotionProductScopeEnum.ALL.getScope(), null)) {
|
||||
return null;
|
||||
}
|
||||
// 品类券:查询商品的品类
|
||||
if (Objects.equals(pageReqVO.getProductScope(), PromotionProductScopeEnum.CATEGORY.getScope()) && pageReqVO.getSpuId() != null) {
|
||||
return Optional.ofNullable(productSpuApi.getSpu(pageReqVO.getSpuId()))
|
||||
.map(ProductSpuRespDTO::getCategoryId).orElse(null);
|
||||
}
|
||||
// 商品卷:直接返回
|
||||
return pageReqVO.getSpuId();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -15,15 +15,15 @@ public class AppCouponMatchReqVO {
|
||||
@NotNull(message = "商品金额不能为空")
|
||||
private Integer price;
|
||||
|
||||
@Schema(description = "商品 SPU 编号的数组", required = true, example = "[1, 2]")
|
||||
@Schema(description = "商品 SPU 编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]")
|
||||
@NotEmpty(message = "商品 SPU 编号不能为空")
|
||||
private List<Long> spuIds;
|
||||
|
||||
@Schema(description = "商品 SKU 编号的数组", required = true, example = "[1, 2]")
|
||||
@Schema(description = "商品 SKU 编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]")
|
||||
@NotEmpty(message = "商品 SKU 编号不能为空")
|
||||
private List<Long> skuIds;
|
||||
|
||||
@Schema(description = "分类编号的数组", required = true, example = "[10, 20]")
|
||||
@Schema(description = "分类编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[10, 20]")
|
||||
@NotEmpty(message = "分类编号不能为空")
|
||||
private List<Long> categoryIds;
|
||||
|
||||
|
@@ -1,6 +1,8 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -13,6 +15,7 @@ import lombok.ToString;
|
||||
public class AppCouponPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "优惠劵状态", example = "1")
|
||||
@InEnum(value = CouponStatusEnum.class, message = "优惠劵状态,必须是 {value}")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
|
@@ -1,6 +1,8 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -12,8 +14,11 @@ import lombok.ToString;
|
||||
@ToString(callSuper = true)
|
||||
public class AppCouponTemplatePageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "使用类型", example = "1")
|
||||
// TODO 芋艿:这里要限制下枚举的使用
|
||||
private Integer useType;
|
||||
@Schema(description = "商品范围", example = "1")
|
||||
@InEnum(value = PromotionProductScopeEnum.class, message = "商品范围,必须是 {value}")
|
||||
private Integer productScope;
|
||||
|
||||
@Schema(description = "商品标号", example = "1")
|
||||
private Long spuId;
|
||||
|
||||
}
|
||||
|
@@ -23,14 +23,6 @@ public class AppCouponTemplateRespVO {
|
||||
// 单位:分;0 - 不限制
|
||||
private Integer usePrice;
|
||||
|
||||
// TODO 芋艿:这两要改的
|
||||
// @Schema(description = "商品范围", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
// @InEnum(PromotionProductScopeEnum.class)
|
||||
// private Integer productScope;
|
||||
//
|
||||
// @Schema(description = "商品范围编号的数组", example = "1,3")
|
||||
// private List<Long> productScopeValues;
|
||||
|
||||
@Schema(description = "生效日期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer validityType;
|
||||
|
||||
|
@@ -3,6 +3,10 @@ package cn.iocoder.yudao.module.promotion.convert.coupon;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageItemRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
|
||||
@@ -11,6 +15,8 @@ import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠劵 Convert
|
||||
@@ -49,4 +55,11 @@ public interface CouponConvert {
|
||||
}
|
||||
return couponDO;
|
||||
}
|
||||
|
||||
CouponPageReqVO convert(AppCouponPageReqVO pageReqVO, Collection<Long> userIds);
|
||||
|
||||
PageResult<AppCouponRespVO> convertAppPage(PageResult<CouponDO> pageResult);
|
||||
|
||||
List<AppCouponMatchRespVO> convertList(List<CouponDO> list);
|
||||
|
||||
}
|
||||
|
@@ -1,13 +1,20 @@
|
||||
package cn.iocoder.yudao.module.promotion.convert.coupon;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template.CouponTemplateUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template.AppCouponTemplateRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 优惠劵模板 Convert
|
||||
*
|
||||
@@ -26,4 +33,25 @@ public interface CouponTemplateConvert {
|
||||
|
||||
PageResult<CouponTemplateRespVO> convertPage(PageResult<CouponTemplateDO> page);
|
||||
|
||||
CouponTemplatePageReqVO convert(AppCouponTemplatePageReqVO pageReqVO, List<Integer> canTakeTypes, Integer productScope, Long productScopeValue);
|
||||
|
||||
PageResult<AppCouponTemplateRespVO> convertAppPage(PageResult<CouponTemplateDO> pageResult);
|
||||
|
||||
default PageResult<AppCouponTemplateRespVO> convertAppPage(PageResult<CouponTemplateDO> pageResult, Map<Long, Integer> couponTakeCountMap) {
|
||||
PageResult<AppCouponTemplateRespVO> result = convertAppPage(pageResult);
|
||||
if (MapUtil.isEmpty(couponTakeCountMap)) {
|
||||
return result;
|
||||
}
|
||||
for (AppCouponTemplateRespVO template : result.getList()) {
|
||||
// 每人领取数量无限制
|
||||
if (template.getTakeLimitCount() == -1) {
|
||||
template.setTakeStatus(false);
|
||||
continue;
|
||||
}
|
||||
// 检查已领取数量是否超过限领数量
|
||||
template.setTakeStatus(MapUtil.getInt(couponTakeCountMap, template.getId(), 0) >= template.getTakeLimitCount());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -110,7 +110,7 @@ public class RewardActivityDO extends BaseDO {
|
||||
*/
|
||||
private List<Long> couponIds;
|
||||
/**
|
||||
* 赠送的优惠卷数量的数组
|
||||
* 赠送的优惠券数量的数组
|
||||
*/
|
||||
private List<Integer> couponCounts;
|
||||
|
||||
|
@@ -1,15 +1,23 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.mysql.coupon;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.service.coupon.bo.CouponTakeCountBO;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.github.yulichang.toolkit.MPJWrappers;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 优惠劵 Mapper
|
||||
@@ -19,11 +27,11 @@ import java.util.List;
|
||||
@Mapper
|
||||
public interface CouponMapper extends BaseMapperX<CouponDO> {
|
||||
|
||||
default PageResult<CouponDO> selectPage(CouponPageReqVO reqVO, Collection<Long> userIds) {
|
||||
default PageResult<CouponDO> selectPage(CouponPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<CouponDO>()
|
||||
.eqIfPresent(CouponDO::getTemplateId, reqVO.getTemplateId())
|
||||
.eqIfPresent(CouponDO::getStatus, reqVO.getStatus())
|
||||
.inIfPresent(CouponDO::getUserId, userIds)
|
||||
.inIfPresent(CouponDO::getUserId, reqVO.getUserIds())
|
||||
.betweenIfPresent(CouponDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(CouponDO::getId));
|
||||
}
|
||||
@@ -62,4 +70,37 @@ public interface CouponMapper extends BaseMapperX<CouponDO> {
|
||||
);
|
||||
}
|
||||
|
||||
// TODO @疯狂:这个是不是搞个 Map 就可以呀?
|
||||
default List<CouponTakeCountBO> selectCountByUserIdAndTemplateIdIn(Long userId, Collection<Long> templateIds) {
|
||||
return BeanUtil.copyToList(selectMaps(MPJWrappers.lambdaJoin(CouponDO.class)
|
||||
.select(CouponDO::getTemplateId)
|
||||
.selectCount(CouponDO::getId, CouponTakeCountBO::getCount)
|
||||
.eq(CouponDO::getUserId, userId)
|
||||
.in(CouponDO::getTemplateId, templateIds)
|
||||
.groupBy(CouponDO::getTemplateId)), CouponTakeCountBO.class);
|
||||
}
|
||||
|
||||
default List<CouponDO> selectListByUserIdAndStatusAndUsePriceLeAndProductScope(
|
||||
Long userId, Integer status, Integer usePrice, List<Long> spuIds, List<Long> categoryIds) {
|
||||
Function<List<Long>, String> productScopeValuesFindInSetFunc = ids -> ids.stream()
|
||||
.map(id -> StrUtil.format("FIND_IN_SET({}, product_scope_values) ", id))
|
||||
.collect(Collectors.joining(" OR "));
|
||||
return selectList(new LambdaQueryWrapperX<CouponDO>()
|
||||
.eq(CouponDO::getUserId, userId)
|
||||
.eq(CouponDO::getStatus, status)
|
||||
.le(CouponDO::getUsePrice, usePrice) // 价格小于等于,满足价格使用条件
|
||||
.and(w -> w.eq(CouponDO::getProductScope, PromotionProductScopeEnum.ALL.getScope()) // 商品范围一:全部
|
||||
.or(ww -> ww.eq(CouponDO::getProductScope, PromotionProductScopeEnum.SPU.getScope()) // 商品范围二:满足指定商品
|
||||
.apply(productScopeValuesFindInSetFunc.apply(spuIds)))
|
||||
.or(ww -> ww.eq(CouponDO::getProductScope, PromotionProductScopeEnum.CATEGORY.getScope()) // 商品范围三:满足指定分类
|
||||
.apply(productScopeValuesFindInSetFunc.apply(categoryIds)))));
|
||||
}
|
||||
|
||||
default List<CouponDO> selectListByStatusAndValidEndTimeLe(Integer status, LocalDateTime validEndTime) {
|
||||
return selectList(new LambdaQueryWrapperX<CouponDO>()
|
||||
.eq(CouponDO::getStatus, status)
|
||||
.le(CouponDO::getValidEndTime, validEndTime)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -39,6 +39,9 @@ public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> {
|
||||
.eqIfPresent(CouponTemplateDO::getStatus, reqVO.getStatus())
|
||||
.eqIfPresent(CouponTemplateDO::getDiscountType, reqVO.getDiscountType())
|
||||
.betweenIfPresent(CouponTemplateDO::getCreateTime, reqVO.getCreateTime())
|
||||
.eqIfPresent(CouponTemplateDO::getProductScope, reqVO.getProductScope())
|
||||
.and(reqVO.getProductScopeValue() != null, w -> w.apply("FIND_IN_SET({0}, product_scope_values)",
|
||||
reqVO.getProductScopeValue()))
|
||||
.and(canTakeConsumer != null, canTakeConsumer)
|
||||
.orderByDesc(CouponTemplateDO::getId));
|
||||
}
|
||||
|
@@ -0,0 +1,30 @@
|
||||
package cn.iocoder.yudao.module.promotion.job.coupon;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
|
||||
import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
|
||||
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
// TODO 芋艿:配置一个 Job
|
||||
/**
|
||||
* 优惠券过期 Job
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Component
|
||||
public class CouponExpireJob implements JobHandler {
|
||||
|
||||
@Resource
|
||||
private CouponService couponService;
|
||||
|
||||
@Override
|
||||
@TenantJob
|
||||
public String execute(String param) {
|
||||
int count = couponService.expireCoupon();
|
||||
return StrUtil.format("过期优惠券 {} 个", count);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* TODO 占位,无具体含义
|
||||
*/
|
||||
package cn.iocoder.yudao.module.promotion.job;
|
@@ -3,11 +3,14 @@ package cn.iocoder.yudao.module.promotion.service.coupon;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.service.coupon.bo.CouponTakeCountBO;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
|
||||
/**
|
||||
* 优惠劵 Service 接口
|
||||
@@ -18,11 +21,11 @@ public interface CouponService {
|
||||
|
||||
/**
|
||||
* 校验优惠劵,包括状态、有限期
|
||||
*
|
||||
* <p>
|
||||
* 1. 如果校验通过,则返回优惠劵信息
|
||||
* 2. 如果校验不通过,则直接抛出业务异常
|
||||
*
|
||||
* @param id 优惠劵编号
|
||||
* @param id 优惠劵编号
|
||||
* @param userId 用户编号
|
||||
* @return 优惠劵信息
|
||||
*/
|
||||
@@ -31,9 +34,8 @@ public interface CouponService {
|
||||
/**
|
||||
* 校验优惠劵,包括状态、有限期
|
||||
*
|
||||
* @see #validCoupon(Long, Long) 逻辑相同,只是入参不同
|
||||
*
|
||||
* @param coupon 优惠劵
|
||||
* @see #validCoupon(Long, Long) 逻辑相同,只是入参不同
|
||||
*/
|
||||
void validCoupon(CouponDO coupon);
|
||||
|
||||
@@ -124,4 +126,56 @@ public interface CouponService {
|
||||
takeCoupon(templateId, CollUtil.newHashSet(userId), CouponTakeTypeEnum.REGISTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会员领取指定优惠券的数量
|
||||
*
|
||||
* @param templateId 优惠券模板编号
|
||||
* @param userId 用户编号
|
||||
* @return 领取优惠券的数量
|
||||
*/
|
||||
default Integer getTakeCount(Long templateId, Long userId) {
|
||||
return CollUtil.emptyIfNull(getTakeCountListByTemplateIds(Collections.singleton(templateId), userId))
|
||||
.stream()
|
||||
.findFirst()
|
||||
.map(CouponTakeCountBO::getCount)
|
||||
.orElse(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计会员领取优惠券的数量
|
||||
*
|
||||
* @param templateIds 优惠券模板编号列表
|
||||
* @param userId 用户编号
|
||||
* @return 领取优惠券的数量
|
||||
*/
|
||||
default Map<Long, Integer> getTakeCountMapByTemplateIds(Collection<Long> templateIds, Long userId) {
|
||||
return convertMap(getTakeCountListByTemplateIds(templateIds, userId),
|
||||
CouponTakeCountBO::getTemplateId, CouponTakeCountBO::getCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计会员领取优惠券的数量
|
||||
*
|
||||
* @param templateIds 优惠券模板编号列表
|
||||
* @param userId 用户编号
|
||||
* @return 领取优惠券的数量
|
||||
*/
|
||||
List<CouponTakeCountBO> getTakeCountListByTemplateIds(Collection<Long> templateIds, Long userId);
|
||||
|
||||
/**
|
||||
* 获取用户匹配的优惠券列表
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param matchReqVO 匹配参数
|
||||
* @return 优惠券列表
|
||||
*/
|
||||
List<CouponDO> getMatchCouponList(Long userId, AppCouponMatchReqVO matchReqVO);
|
||||
|
||||
/**
|
||||
* 过期优惠券
|
||||
*
|
||||
* @return 过期数量
|
||||
*/
|
||||
int expireCoupon();
|
||||
|
||||
}
|
||||
|
@@ -2,15 +2,18 @@ package cn.iocoder.yudao.module.promotion.service.coupon;
|
||||
|
||||
import cn.hutool.core.collection.CollStreamUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
|
||||
@@ -18,12 +21,15 @@ import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponMapper;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTemplateValidityTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.service.coupon.bo.CouponTakeCountBO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -34,11 +40,13 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
// TODO @疯狂:注册时,赠送用户优惠劵;为了解耦,可以考虑注册时发个 MQ 消息;然后营销这里监听后消费;
|
||||
/**
|
||||
* 优惠劵 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@Validated
|
||||
public class CouponServiceImpl implements CouponService {
|
||||
@@ -77,16 +85,16 @@ public class CouponServiceImpl implements CouponService {
|
||||
@Override
|
||||
public PageResult<CouponDO> getCouponPage(CouponPageReqVO pageReqVO) {
|
||||
// 获得用户编号
|
||||
Set<Long> userIds = null;
|
||||
if (StrUtil.isNotEmpty(pageReqVO.getNickname())) {
|
||||
userIds = CollectionUtils.convertSet(memberUserApi.getUserListByNickname(pageReqVO.getNickname()),
|
||||
Set<Long> userIds = CollectionUtils.convertSet(memberUserApi.getUserListByNickname(pageReqVO.getNickname()),
|
||||
MemberUserRespDTO::getId);
|
||||
if (CollUtil.isEmpty(userIds)) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
pageReqVO.setUserIds(userIds);
|
||||
}
|
||||
// 分页查询
|
||||
return couponMapper.selectPage(pageReqVO, userIds);
|
||||
return couponMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -175,6 +183,63 @@ public class CouponServiceImpl implements CouponService {
|
||||
couponTemplateService.updateCouponTemplateTakeCount(templateId, userIds.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CouponTakeCountBO> getTakeCountListByTemplateIds(Collection<Long> templateIds, Long userId) {
|
||||
if (CollUtil.isEmpty(templateIds)) {
|
||||
return ListUtil.empty();
|
||||
}
|
||||
return couponMapper.selectCountByUserIdAndTemplateIdIn(userId, templateIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CouponDO> getMatchCouponList(Long userId, AppCouponMatchReqVO matchReqVO) {
|
||||
return couponMapper.selectListByUserIdAndStatusAndUsePriceLeAndProductScope(userId,
|
||||
CouponStatusEnum.UNUSED.getStatus(),
|
||||
matchReqVO.getPrice(), matchReqVO.getSpuIds(), matchReqVO.getCategoryIds());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int expireCoupon() {
|
||||
// 1. 查询待过期的优惠券
|
||||
List<CouponDO> list = couponMapper.selectListByStatusAndValidEndTimeLe(
|
||||
CouponStatusEnum.UNUSED.getStatus(), LocalDateTime.now());
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 2. 遍历执行
|
||||
int count = 0;
|
||||
for (CouponDO coupon : list) {
|
||||
try {
|
||||
boolean success = getSelf().expireCoupon(coupon);
|
||||
if (success) {
|
||||
count++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[expireCoupon][coupon({}) 更新为已过期失败]", coupon.getId(), e);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过期单个优惠劵
|
||||
*
|
||||
* @param coupon 优惠劵
|
||||
* @return 是否过期成功
|
||||
*/
|
||||
private boolean expireCoupon(CouponDO coupon) {
|
||||
// 更新记录状态
|
||||
int updateRows = couponMapper.updateByIdAndStatus(coupon.getId(), CouponStatusEnum.UNUSED.getStatus(),
|
||||
new CouponDO().setStatus(CouponStatusEnum.EXPIRE.getStatus()));
|
||||
if (updateRows == 0) {
|
||||
log.error("[expireCoupon][coupon({}) 更新为已过期失败]", coupon.getId());
|
||||
return false;
|
||||
}
|
||||
log.info("[expireCoupon][coupon({}) 更新为已过期成功]", coupon.getId());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验优惠券是否可以领取
|
||||
*
|
||||
@@ -211,7 +276,7 @@ public class CouponServiceImpl implements CouponService {
|
||||
/**
|
||||
* 过滤掉达到领取上线的用户
|
||||
*
|
||||
* @param userIds 用户编号数组
|
||||
* @param userIds 用户编号数组
|
||||
* @param couponTemplate 优惠劵模版
|
||||
*/
|
||||
private void removeTakeLimitUser(Set<Long> userIds, CouponTemplateDO couponTemplate) {
|
||||
@@ -228,4 +293,12 @@ public class CouponServiceImpl implements CouponService {
|
||||
userIds.removeIf(userId -> MapUtil.getInt(userTakeCountMap, userId, 0) >= couponTemplate.getTakeLimitCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得自身的代理对象,解决 AOP 生效问题
|
||||
*
|
||||
* @return 自己
|
||||
*/
|
||||
private CouponServiceImpl getSelf() {
|
||||
return SpringUtil.getBean(getClass());
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,7 @@ public class CouponTemplateServiceImpl implements CouponTemplateService {
|
||||
@Resource
|
||||
private CouponTemplateMapper couponTemplateMapper;
|
||||
|
||||
// TODO @疯狂:新增/修改时,需要校验对应的商品、分类是否存在
|
||||
@Override
|
||||
public Long createCouponTemplate(CouponTemplateCreateReqVO createReqVO) {
|
||||
// 插入
|
||||
|
@@ -0,0 +1,22 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.coupon.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 优惠券领取数量 BO
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Data
|
||||
public class CouponTakeCountBO {
|
||||
|
||||
/**
|
||||
* 优惠劵模板编号
|
||||
*/
|
||||
private Long templateId;
|
||||
/**
|
||||
* 领取数量
|
||||
*/
|
||||
private Integer count;
|
||||
|
||||
}
|
33
yudao-module-mall/yudao-module-statistics-api/pom.xml
Normal file
33
yudao-module-mall/yudao-module-statistics-api/pom.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-mall</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>yudao-module-statistics-api</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>
|
||||
statistics 模块 API,暴露给其它模块调用
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 参数校验 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* TODO 占位,无特殊含义
|
||||
*/
|
||||
package cn.iocoder.yudao.module.statistics.api;
|
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* TODO 占位,无特殊含义
|
||||
*/
|
||||
package cn.iocoder.yudao.module.statistics.enums;
|
90
yudao-module-mall/yudao-module-statistics-biz/pom.xml
Normal file
90
yudao-module-mall/yudao-module-statistics-biz/pom.xml
Normal file
@@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-mall</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>yudao-module-statistics-biz</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>
|
||||
statistics 模块,主要实现统计相关功能
|
||||
例如:统计商品、会员、交易等功能。
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-statistics-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-promotion-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-product-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-trade-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-member-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 业务组件 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Web 相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- DB 相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test 测试相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 工具类相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-excel</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-dict</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@@ -0,0 +1,71 @@
|
||||
package cn.iocoder.yudao.module.statistics.controller.admin.trade;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.*;
|
||||
import cn.iocoder.yudao.module.statistics.convert.trade.TradeStatisticsConvert;
|
||||
import cn.iocoder.yudao.module.statistics.service.trade.TradeStatisticsService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 交易统计")
|
||||
@RestController
|
||||
@RequestMapping("/statistics/trade")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class TradeStatisticsController {
|
||||
|
||||
@Resource
|
||||
private TradeStatisticsService tradeStatisticsService;
|
||||
|
||||
@GetMapping("/summary")
|
||||
@Operation(summary = "获得交易统计")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:trade:query')")
|
||||
public CommonResult<TradeStatisticsComparisonRespVO<TradeSummaryRespVO>> getTradeSummaryComparison() {
|
||||
return success(tradeStatisticsService.getTradeSummaryComparison());
|
||||
}
|
||||
|
||||
@GetMapping("/trend/summary")
|
||||
@Operation(summary = "获得交易状况统计")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:trade:query')")
|
||||
public CommonResult<TradeStatisticsComparisonRespVO<TradeTrendSummaryRespVO>> getTradeTrendSummaryComparison(
|
||||
TradeTrendReqVO reqVO) {
|
||||
return success(tradeStatisticsService.getTradeTrendSummaryComparison(ArrayUtil.get(reqVO.getTimes(), 0),
|
||||
ArrayUtil.get(reqVO.getTimes(), 1)));
|
||||
}
|
||||
|
||||
@GetMapping("/trend/list")
|
||||
@Operation(summary = "获得交易状况明细")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:trade:query')")
|
||||
public CommonResult<List<TradeTrendSummaryRespVO>> getTradeStatisticsList(
|
||||
TradeTrendReqVO reqVO) {
|
||||
return success(tradeStatisticsService.getTradeStatisticsList(ArrayUtil.get(reqVO.getTimes(), 0),
|
||||
ArrayUtil.get(reqVO.getTimes(), 1)));
|
||||
}
|
||||
|
||||
@GetMapping("/trend/export-excel")
|
||||
@Operation(summary = "导出获得交易状况明细 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:trade:export')")
|
||||
public void exportTradeStatisticsExcel(TradeTrendReqVO reqVO, HttpServletResponse response) throws IOException {
|
||||
List<TradeTrendSummaryRespVO> list = tradeStatisticsService.getTradeStatisticsList(ArrayUtil.get(reqVO.getTimes(), 0),
|
||||
ArrayUtil.get(reqVO.getTimes(), 1));
|
||||
// 导出 Excel
|
||||
List<TradeTrendSummaryExcelVO> data = TradeStatisticsConvert.INSTANCE.convertList02(list);
|
||||
ExcelUtils.write(response, "交易状况.xls", "数据", TradeTrendSummaryExcelVO.class, data);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Schema(description = "管理后台 - 交易统计对照 Response VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TradeStatisticsComparisonRespVO<T> {
|
||||
|
||||
@Schema(description = "当前数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private T value;
|
||||
|
||||
@Schema(description = "参照数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private T reference;
|
||||
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 交易统计 Response VO")
|
||||
@Data
|
||||
public class TradeSummaryRespVO {
|
||||
@Schema(description = "昨日订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer yesterdayOrderCount;
|
||||
@Schema(description = "昨日支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer yesterdayPayPrice;
|
||||
|
||||
@Schema(description = "本月订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer monthOrderCount;
|
||||
@Schema(description = "本月支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer monthPayPrice;
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 交易状况 Request VO")
|
||||
@Data
|
||||
public class TradeTrendReqVO {
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@Schema(description = "时间范围")
|
||||
private LocalDateTime[] times;
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.alibaba.excel.annotation.format.DateTimeFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
|
||||
|
||||
/**
|
||||
* 交易状况统计 Excel VO
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Data
|
||||
public class TradeTrendSummaryExcelVO {
|
||||
|
||||
@ExcelProperty(value = "日期")
|
||||
@DateTimeFormat(FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate date;
|
||||
|
||||
@ExcelProperty(value = "营业额", converter = MoneyConvert.class)
|
||||
private Integer turnover;
|
||||
|
||||
@ExcelProperty(value = "商品支付金额", converter = MoneyConvert.class)
|
||||
private Integer orderPayPrice;
|
||||
|
||||
@ExcelProperty(value = "充值金额", converter = MoneyConvert.class)
|
||||
private Integer rechargePrice;
|
||||
|
||||
@ExcelProperty(value = "支出金额", converter = MoneyConvert.class)
|
||||
private Integer expensePrice;
|
||||
|
||||
@ExcelProperty(value = "余额支付金额", converter = MoneyConvert.class)
|
||||
private Integer balancePrice;
|
||||
|
||||
@ExcelProperty(value = "支付佣金金额", converter = MoneyConvert.class)
|
||||
private Integer brokerageSettlementPrice;
|
||||
|
||||
@ExcelProperty(value = "商品退款金额", converter = MoneyConvert.class)
|
||||
private Integer orderRefundPrice;
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
|
||||
|
||||
@Schema(description = "管理后台 - 交易状况统计 Response VO")
|
||||
@Data
|
||||
public class TradeTrendSummaryRespVO {
|
||||
|
||||
@Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate date;
|
||||
|
||||
@Schema(description = "营业额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer turnover;
|
||||
|
||||
@Schema(description = "商品支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer orderPayPrice;
|
||||
|
||||
@Schema(description = "充值金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer rechargePrice;
|
||||
|
||||
@Schema(description = "支出金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer expensePrice;
|
||||
|
||||
@Schema(description = "余额支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer balancePrice;
|
||||
|
||||
@Schema(description = "支付佣金金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer brokerageSettlementPrice;
|
||||
|
||||
@Schema(description = "商品退款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer orderRefundPrice;
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* TODO
|
||||
* 1. 会员总数据
|
||||
* 2. 性别统计
|
||||
* 3. 渠道统计
|
||||
* 4. 地域统计
|
||||
* 5. 会员概览
|
||||
*/
|
||||
package cn.iocoder.yudao.module.statistics.controller.member;
|
@@ -0,0 +1 @@
|
||||
package cn.iocoder.yudao.module.statistics.controller;
|
@@ -0,0 +1,41 @@
|
||||
package cn.iocoder.yudao.module.statistics.controller.product;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.statistics.dal.mysql.product.ProductSpuStatisticsDO;
|
||||
import cn.iocoder.yudao.module.statistics.dal.mysql.product.ProductStatisticsDO;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "管理后台 - 商品统计")
|
||||
@RestController
|
||||
@RequestMapping("/statistics/product")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class ProductStatisticsController {
|
||||
|
||||
// TODO @麦子:返回 ProductStatisticsComparisonResp, 里面有两个字段,一个是选择的时间范围的合计结果,一个是对比的时间范围的合计结果;
|
||||
// 例如说,选择时间范围是 2023-10-01 ~ 2023-10-02,那么对比就是 2023-09-30,再倒推 2 天;
|
||||
public CommonResult<Object> getProductStatisticsComparison() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO @麦子:查询指定时间范围内的商品统计数据;DO 到时需要改成 VO 哈
|
||||
public CommonResult<List<ProductStatisticsDO>> getProductStatisticsList(
|
||||
LocalDateTime[] times) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO @麦子:查询指定时间范围内的商品 SPU 统计数据;DO 到时需要改成 VO 哈
|
||||
// 入参是分页参数 + 时间范围 + 排序字段
|
||||
public CommonResult<PageResult<ProductSpuStatisticsDO>> getProductSpuStatisticsPage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
package cn.iocoder.yudao.module.statistics.convert.trade;
|
||||
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO;
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeSummaryRespVO;
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryExcelVO;
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO;
|
||||
import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 交易统计 Convert
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Mapper
|
||||
public interface TradeStatisticsConvert {
|
||||
|
||||
TradeStatisticsConvert INSTANCE = Mappers.getMapper(TradeStatisticsConvert.class);
|
||||
|
||||
default TradeStatisticsComparisonRespVO<TradeSummaryRespVO> convert(TradeSummaryRespBO yesterdayData,
|
||||
TradeSummaryRespBO beforeYesterdayData,
|
||||
TradeSummaryRespBO monthData,
|
||||
TradeSummaryRespBO lastMonthData) {
|
||||
return convert(convert(yesterdayData, monthData), convert(beforeYesterdayData, lastMonthData));
|
||||
}
|
||||
|
||||
|
||||
default TradeSummaryRespVO convert(TradeSummaryRespBO yesterdayData, TradeSummaryRespBO monthData) {
|
||||
return new TradeSummaryRespVO()
|
||||
.setYesterdayOrderCount(yesterdayData.getCount()).setYesterdayPayPrice(yesterdayData.getSummary())
|
||||
.setMonthOrderCount(monthData.getCount()).setMonthPayPrice(monthData.getSummary());
|
||||
}
|
||||
|
||||
TradeStatisticsComparisonRespVO<TradeSummaryRespVO> convert(TradeSummaryRespVO value, TradeSummaryRespVO reference);
|
||||
|
||||
TradeStatisticsComparisonRespVO<TradeTrendSummaryRespVO> convert(TradeTrendSummaryRespVO value, TradeTrendSummaryRespVO reference);
|
||||
|
||||
List<TradeTrendSummaryExcelVO> convertList02(List<TradeTrendSummaryRespVO> list);
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* 占位 todo
|
||||
*/
|
||||
package cn.iocoder.yudao.module.statistics.dal.dataobject;
|
@@ -0,0 +1,89 @@
|
||||
package cn.iocoder.yudao.module.statistics.dal.dataobject.trade;
|
||||
|
||||
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 交易统计 DO
|
||||
* <p>
|
||||
* 以天为维度,统计全部的数据
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("trade_statistics")
|
||||
@KeySequence("trade_statistics_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TradeStatisticsDO extends TenantBaseDO {
|
||||
|
||||
/**
|
||||
* 编号,主键自增
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 统计日期
|
||||
*/
|
||||
private LocalDateTime time;
|
||||
|
||||
/**
|
||||
* 创建订单数
|
||||
*/
|
||||
private Integer orderCreateCount;
|
||||
/**
|
||||
* 支付订单商品数
|
||||
*/
|
||||
private Integer orderPayCount;
|
||||
/**
|
||||
* 总支付金额,单位:分
|
||||
*/
|
||||
private Integer orderPayPrice;
|
||||
/**
|
||||
* 总支付金额(余额),单位:分
|
||||
*/
|
||||
private Integer orderWalletPayPrice;
|
||||
|
||||
/**
|
||||
* 退款订单数
|
||||
*/
|
||||
private Integer afterSaleCount;
|
||||
/**
|
||||
* 总退款金额,单位:分
|
||||
*/
|
||||
private Integer afterSaleRefundPrice;
|
||||
|
||||
/**
|
||||
* 佣金金额(已结算),单位:分
|
||||
*/
|
||||
private Integer brokerageSettlementPrice;
|
||||
|
||||
/**
|
||||
* 充值订单数
|
||||
* <p>
|
||||
* 从 PayWalletRechargeDO 计算
|
||||
*/
|
||||
private Integer rechargePayCount;
|
||||
/**
|
||||
* 充值金额,单位:分
|
||||
*/
|
||||
private Integer rechargePayPrice;
|
||||
/**
|
||||
* 充值退款订单数
|
||||
*/
|
||||
private Integer rechargeRefundCount;
|
||||
/**
|
||||
* 充值退款金额,单位:分
|
||||
*/
|
||||
private Integer rechargeRefundPrice;
|
||||
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
package cn.iocoder.yudao.module.statistics.dal.mysql.product;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 商品 SPU 统计 DO
|
||||
*
|
||||
* 以天为维度,统计商品 SPU 的数据
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("product_spu_statistics")
|
||||
@KeySequence("product_spu_statistics_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ProductSpuStatisticsDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号,主键自增
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 商品 SPU 编号
|
||||
*
|
||||
* 关联 ProductSpuDO 的 id 字段
|
||||
*/
|
||||
private Long spuId;
|
||||
/**
|
||||
* 统计日期
|
||||
*/
|
||||
private LocalDateTime time;
|
||||
|
||||
/**
|
||||
* 浏览量
|
||||
*/
|
||||
private Integer browseCount;
|
||||
/**
|
||||
* 收藏量
|
||||
*/
|
||||
private Integer favoriteCount;
|
||||
|
||||
/**
|
||||
* 添加购物车次数
|
||||
*
|
||||
* 以商品被添加到购物车的 createTime 计算,后续多次添加,不会增加该值。
|
||||
* 直到该次被下单、或者被删除,后续再次被添加到购物车。
|
||||
*/
|
||||
private Integer addCartCount;
|
||||
/**
|
||||
* 创建订单商品数
|
||||
*/
|
||||
private Integer createOrderCount;
|
||||
/**
|
||||
* 支付订单商品数
|
||||
*/
|
||||
private Integer payOrderCount;
|
||||
/**
|
||||
* 总支付金额,单位:分
|
||||
*/
|
||||
private Integer payPrice;
|
||||
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
package cn.iocoder.yudao.module.statistics.dal.mysql.product;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 商品统计 DO
|
||||
*
|
||||
* 以天为维度,统计全部的数据
|
||||
*
|
||||
* 和 {@link ProductSpuStatisticsDO} 的差异是,它是全局的统计
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("product_spu_statistics")
|
||||
@KeySequence("product_spu_statistics_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ProductStatisticsDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号,主键自增
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 统计日期
|
||||
*/
|
||||
private LocalDateTime time;
|
||||
|
||||
/**
|
||||
* 浏览量
|
||||
*/
|
||||
private Integer browseCount;
|
||||
/**
|
||||
* 收藏量
|
||||
*/
|
||||
private Integer favoriteCount;
|
||||
|
||||
/**
|
||||
* 添加购物车次数
|
||||
*
|
||||
* 以商品被添加到购物车的 createTime 计算,后续多次添加,不会增加该值。
|
||||
* 直到该次被下单、或者被删除,后续再次被添加到购物车。
|
||||
*/
|
||||
private Integer addCartCount;
|
||||
/**
|
||||
* 创建订单商品数
|
||||
*/
|
||||
private Integer createOrderCount;
|
||||
/**
|
||||
* 支付订单商品数
|
||||
*/
|
||||
private Integer payOrderCount;
|
||||
/**
|
||||
* 总支付金额,单位:分
|
||||
*/
|
||||
private Integer payPrice;
|
||||
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.yudao.module.statistics.dal.mysql.trade;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO;
|
||||
import cn.iocoder.yudao.module.statistics.dal.dataobject.trade.TradeStatisticsDO;
|
||||
import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 交易统计 Mapper
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Mapper
|
||||
public interface TradeStatisticsMapper extends BaseMapperX<TradeStatisticsDO> {
|
||||
|
||||
@Select("SELECT IFNULL(SUM(order_create_count), 0) AS count, IFNULL(SUM(order_pay_price), 0) AS summary " +
|
||||
"FROM trade_statistics " +
|
||||
"WHERE time BETWEEN #{beginTime} AND #{endTime} AND deleted = FALSE")
|
||||
TradeSummaryRespBO selectOrderCreateCountSumAndOrderPayPriceSumByTimeBetween(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
TradeTrendSummaryRespVO selectByTimeBetween(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
List<TradeTrendSummaryRespVO> selectListByTimeBetween(@Param("beginTime") LocalDateTime beginTime,
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* TODO 芋艿,占坑,无特殊含义
|
||||
*/
|
||||
package cn.iocoder.yudao.module.statistics.job;
|
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* statistics 模块,主要实现统计相关功能。
|
||||
* 例如:统计商品、会员、交易等功能。
|
||||
*
|
||||
* 1. Controller URL:以 /statistics/ 开头,避免和其它 Module 冲突
|
||||
* 2. DataObject 表名:以 statistics_ 为后缀,方便在数据库中区分【特殊】
|
||||
*/
|
||||
package cn.iocoder.yudao.module.statistics;
|
@@ -0,0 +1,37 @@
|
||||
package cn.iocoder.yudao.module.statistics.service.trade;
|
||||
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO;
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeSummaryRespVO;
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 交易统计 Service 接口
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
public interface TradeStatisticsService {
|
||||
|
||||
/**
|
||||
* 获得交易统计
|
||||
*
|
||||
* @return 统计数据对照
|
||||
*/
|
||||
TradeStatisticsComparisonRespVO<TradeSummaryRespVO> getTradeSummaryComparison();
|
||||
|
||||
/**
|
||||
* 获得交易状况统计
|
||||
*
|
||||
* @return 统计数据对照
|
||||
*/
|
||||
TradeStatisticsComparisonRespVO<TradeTrendSummaryRespVO> getTradeTrendSummaryComparison(LocalDateTime beginTime, LocalDateTime endTime);
|
||||
|
||||
/**
|
||||
* 获得交易状况明细
|
||||
*
|
||||
* @return 统计数据列表
|
||||
*/
|
||||
List<TradeTrendSummaryRespVO> getTradeStatisticsList(LocalDateTime beginTime, LocalDateTime endTime);
|
||||
}
|
@@ -0,0 +1,95 @@
|
||||
package cn.iocoder.yudao.module.statistics.service.trade;
|
||||
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeStatisticsComparisonRespVO;
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeSummaryRespVO;
|
||||
import cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO;
|
||||
import cn.iocoder.yudao.module.statistics.convert.trade.TradeStatisticsConvert;
|
||||
import cn.iocoder.yudao.module.statistics.dal.mysql.trade.TradeStatisticsMapper;
|
||||
import cn.iocoder.yudao.module.statistics.service.trade.bo.TradeSummaryRespBO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 交易统计 Service 实现类
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class TradeStatisticsServiceImpl implements TradeStatisticsService {
|
||||
|
||||
@Resource
|
||||
private TradeStatisticsMapper tradeStatisticsMapper;
|
||||
|
||||
@Override
|
||||
public TradeStatisticsComparisonRespVO<TradeSummaryRespVO> getTradeSummaryComparison() {
|
||||
// 昨天的数据
|
||||
TradeSummaryRespBO yesterdayData = getTradeSummaryByDays(-1);
|
||||
// 前天的数据(用于对照昨天的数据)
|
||||
TradeSummaryRespBO beforeYesterdayData = getTradeSummaryByDays(-2);
|
||||
|
||||
// 本月数据;
|
||||
TradeSummaryRespBO monthData = getTradeSummaryByMonths(0);
|
||||
// 上月数据(用于对照本月的数据)
|
||||
TradeSummaryRespBO lastMonthData = getTradeSummaryByMonths(-1);
|
||||
|
||||
return TradeStatisticsConvert.INSTANCE.convert(yesterdayData, beforeYesterdayData, monthData, lastMonthData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradeStatisticsComparisonRespVO<TradeTrendSummaryRespVO> getTradeTrendSummaryComparison(LocalDateTime beginTime,
|
||||
LocalDateTime endTime) {
|
||||
// 统计数据
|
||||
TradeTrendSummaryRespVO value = tradeStatisticsMapper.selectByTimeBetween(beginTime, endTime);
|
||||
// 对照数据
|
||||
LocalDateTime referenceBeginTime = beginTime.minus(Duration.between(beginTime, endTime));
|
||||
TradeTrendSummaryRespVO reference = tradeStatisticsMapper.selectByTimeBetween(referenceBeginTime, beginTime);
|
||||
return TradeStatisticsConvert.INSTANCE.convert(value, reference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TradeTrendSummaryRespVO> getTradeStatisticsList(LocalDateTime beginTime, LocalDateTime endTime) {
|
||||
return tradeStatisticsMapper.selectListByTimeBetween(beginTime, endTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计指定日期的交易数据
|
||||
*
|
||||
* @param days 增加的天数
|
||||
* @return 交易数据
|
||||
*/
|
||||
private TradeSummaryRespBO getTradeSummaryByDays(int days) {
|
||||
LocalDateTime date = LocalDateTime.now().plusDays(days);
|
||||
return tradeStatisticsMapper.selectOrderCreateCountSumAndOrderPayPriceSumByTimeBetween(
|
||||
LocalDateTimeUtil.beginOfDay(date), LocalDateTimeUtil.endOfDay(date));
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计指定月份的交易数据
|
||||
*
|
||||
* @param months 增加的月数
|
||||
* @return 交易数据
|
||||
*/
|
||||
private TradeSummaryRespBO getTradeSummaryByMonths(int months) {
|
||||
// 月份开始时间
|
||||
LocalDateTime beginOfMonth = LocalDateTime.now()
|
||||
.plusMonths(months)
|
||||
.with(TemporalAdjusters.firstDayOfMonth())
|
||||
.with(LocalTime.MIN);
|
||||
// 月份截止时间
|
||||
LocalDateTime endOfToday = LocalDateTime.now()
|
||||
.plusMonths(months)
|
||||
.with(TemporalAdjusters.lastDayOfMonth())
|
||||
.with(LocalTime.MAX);
|
||||
return tradeStatisticsMapper.selectOrderCreateCountSumAndOrderPayPriceSumByTimeBetween(beginOfMonth, endOfToday);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package cn.iocoder.yudao.module.statistics.service.trade.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 交易统计 Resp BO
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Data
|
||||
public class TradeSummaryRespBO {
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
private Integer count;
|
||||
|
||||
/**
|
||||
* 合计
|
||||
*/
|
||||
private Integer summary;
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="cn.iocoder.yudao.module.statistics.dal.mysql.trade.TradeStatisticsMapper">
|
||||
<select id="selectByTimeBetween"
|
||||
resultType="cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO">
|
||||
SELECT
|
||||
-- 营业额 = 商品支付金额 + 充值金额
|
||||
SUM(order_pay_price + recharge_pay_price) AS turnover,
|
||||
SUM(order_pay_price) AS orderPayPrice,
|
||||
SUM(recharge_pay_price) AS rechargePrice,
|
||||
-- 支出金额 = 余额支付金额 + 支付佣金金额 + 商品退款金额
|
||||
SUM(order_wallet_pay_price + brokerage_settlement_price + after_sale_refund_price) AS expensePrice,
|
||||
SUM(order_wallet_pay_price) AS balancePrice,
|
||||
SUM(brokerage_settlement_price) AS brokerageSettlementPrice,
|
||||
SUM(after_sale_refund_price) AS orderRefundPrice
|
||||
FROM trade_statistics
|
||||
WHERE time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND deleted = FALSE
|
||||
</select>
|
||||
|
||||
<select id="selectListByTimeBetween"
|
||||
resultType="cn.iocoder.yudao.module.statistics.controller.admin.trade.vo.TradeTrendSummaryRespVO">
|
||||
SELECT DATE_FORMAT(time, '%Y-%m-%d') AS date,
|
||||
-- 营业额 = 商品支付金额 + 充值金额
|
||||
SUM(order_pay_price + recharge_pay_price) AS turnover,
|
||||
SUM(order_pay_price) AS orderPayPrice,
|
||||
SUM(recharge_pay_price) AS rechargePrice,
|
||||
-- 支出金额 = 余额支付金额 + 支付佣金金额 + 商品退款金额
|
||||
SUM(order_wallet_pay_price + brokerage_settlement_price + after_sale_refund_price) AS expensePrice,
|
||||
SUM(order_wallet_pay_price) AS balancePrice,
|
||||
SUM(brokerage_settlement_price) AS brokerageSettlementPrice,
|
||||
SUM(after_sale_refund_price) AS orderRefundPrice
|
||||
FROM trade_statistics
|
||||
WHERE time BETWEEN #{beginTime} AND #{endTime}
|
||||
AND deleted = FALSE
|
||||
GROUP BY date
|
||||
</select>
|
||||
</mapper>
|
@@ -11,83 +11,82 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||
*/
|
||||
public interface ErrorCodeConstants {
|
||||
|
||||
// ========== Order 模块 1011000000 ==========
|
||||
ErrorCode ORDER_ITEM_NOT_FOUND = new ErrorCode(1011000010, "交易订单项不存在");
|
||||
ErrorCode ORDER_NOT_FOUND = new ErrorCode(1011000011, "交易订单不存在");
|
||||
ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1011000012, "交易订单项更新售后状态失败,请重试");
|
||||
ErrorCode ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1011000013, "交易订单更新支付状态失败,订单不是【未支付】状态");
|
||||
ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1011000014, "交易订单更新支付状态失败,支付单编号不匹配");
|
||||
ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1011000015, "交易订单更新支付状态失败,支付单状态不是【支付成功】状态");
|
||||
ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1011000016, "交易订单更新支付状态失败,支付单金额不匹配");
|
||||
ErrorCode ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED = new ErrorCode(1011000017, "交易订单发货失败,订单不是【待发货】状态");
|
||||
ErrorCode ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED = new ErrorCode(1011000018, "交易订单收货失败,订单不是【待收货】状态");
|
||||
ErrorCode ORDER_COMMENT_FAIL_STATUS_NOT_COMPLETED = new ErrorCode(1011000019, "创建交易订单项的评价失败,订单不是【已完成】状态");
|
||||
ErrorCode ORDER_COMMENT_STATUS_NOT_FALSE = new ErrorCode(1011000020, "创建交易订单项的评价失败,订单已评价");
|
||||
ErrorCode ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE = new ErrorCode(1011000021, "交易订单发货失败,订单已退款或部分退款");
|
||||
ErrorCode ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000022, "交易订单发货失败,拼团未成功");
|
||||
ErrorCode ORDER_DELIVERY_FAIL_BARGAIN_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000023, "交易订单发货失败,砍价未成功");
|
||||
ErrorCode ORDER_DELIVERY_FAIL_DELIVERY_TYPE_NOT_EXPRESS = new ErrorCode(1011000024, "交易订单发货失败,发货类型不是快递");
|
||||
ErrorCode ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID = new ErrorCode(1011000025, "交易订单取消失败,订单不是【待支付】状态");
|
||||
ErrorCode ORDER_UPDATE_PRICE_FAIL_PAID = new ErrorCode(1011000026, "支付订单调价失败,原因:支付订单已付款,不能调价");
|
||||
ErrorCode ORDER_UPDATE_PRICE_FAIL_EQUAL = new ErrorCode(1011000027, "支付订单调价失败,原因:价格没有变化");
|
||||
ErrorCode ORDER_UPDATE_PRICE_FAIL_NOT_ITEM = new ErrorCode(1011000028, "支付订单调价失败,原因:订单项不存在");
|
||||
ErrorCode ORDER_DELETE_FAIL_STATUS_NOT_CANCEL = new ErrorCode(1011000029, "交易订单删除失败,订单不是【已取消】状态");
|
||||
// ========== Order 模块 1-011-000-000 ==========
|
||||
ErrorCode ORDER_ITEM_NOT_FOUND = new ErrorCode(1_011_000_010, "交易订单项不存在");
|
||||
ErrorCode ORDER_NOT_FOUND = new ErrorCode(1_011_000_011, "交易订单不存在");
|
||||
ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1_011_000_012, "交易订单项更新售后状态失败,请重试");
|
||||
ErrorCode ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1_011_000_013, "交易订单更新支付状态失败,订单不是【未支付】状态");
|
||||
ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1_011_000_014, "交易订单更新支付状态失败,支付单编号不匹配");
|
||||
ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1_011_000_015, "交易订单更新支付状态失败,支付单状态不是【支付成功】状态");
|
||||
ErrorCode ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1_011_000_016, "交易订单更新支付状态失败,支付单金额不匹配");
|
||||
ErrorCode ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED = new ErrorCode(1_011_000_017, "交易订单发货失败,订单不是【待发货】状态");
|
||||
ErrorCode ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED = new ErrorCode(1_011_000_018, "交易订单收货失败,订单不是【待收货】状态");
|
||||
ErrorCode ORDER_COMMENT_FAIL_STATUS_NOT_COMPLETED = new ErrorCode(1_011_000_019, "创建交易订单项的评价失败,订单不是【已完成】状态");
|
||||
ErrorCode ORDER_COMMENT_STATUS_NOT_FALSE = new ErrorCode(1_011_000_020, "创建交易订单项的评价失败,订单已评价");
|
||||
ErrorCode ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE = new ErrorCode(1_011_000_021, "交易订单发货失败,订单已退款或部分退款");
|
||||
ErrorCode ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1_011_000_022, "交易订单发货失败,拼团未成功");
|
||||
ErrorCode ORDER_DELIVERY_FAIL_BARGAIN_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1_011_000_023, "交易订单发货失败,砍价未成功");
|
||||
ErrorCode ORDER_DELIVERY_FAIL_DELIVERY_TYPE_NOT_EXPRESS = new ErrorCode(1_011_000_024, "交易订单发货失败,发货类型不是快递");
|
||||
ErrorCode ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID = new ErrorCode(1_011_000_025, "交易订单取消失败,订单不是【待支付】状态");
|
||||
ErrorCode ORDER_UPDATE_PRICE_FAIL_PAID = new ErrorCode(1_011_000_026, "支付订单调价失败,原因:支付订单已付款,不能调价");
|
||||
ErrorCode ORDER_UPDATE_PRICE_FAIL_ALREADY = new ErrorCode(1_011_000_027, "支付订单调价失败,原因:已经修改过价格");
|
||||
ErrorCode ORDER_UPDATE_PRICE_FAIL_PRICE_ERROR = new ErrorCode(1_011_000_028, "支付订单调价失败,原因:调整后支付价格不能小于 0.01 元");
|
||||
ErrorCode ORDER_DELETE_FAIL_STATUS_NOT_CANCEL = new ErrorCode(1_011_000_029, "交易订单删除失败,订单不是【已取消】状态");
|
||||
|
||||
// ========== After Sale 模块 1011000100 ==========
|
||||
ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在");
|
||||
ErrorCode AFTER_SALE_CREATE_FAIL_REFUND_PRICE_ERROR = new ErrorCode(1011000101, "申请退款金额错误");
|
||||
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_CANCELED = new ErrorCode(1011000102, "订单已关闭,无法申请售后");
|
||||
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_PAID = new ErrorCode(1011000103, "订单未支付,无法申请售后");
|
||||
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_DELIVERED = new ErrorCode(1011000104, "订单未发货,无法申请【退货退款】售后");
|
||||
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_ITEM_APPLIED = new ErrorCode(1011000105, "订单项已申请售后,无法重复申请");
|
||||
ErrorCode AFTER_SALE_AUDIT_FAIL_STATUS_NOT_APPLY = new ErrorCode(1011000106, "审批失败,售后状态不处于审批中");
|
||||
ErrorCode AFTER_SALE_UPDATE_STATUS_FAIL = new ErrorCode(1011000107, "操作售后单失败,请刷新后重试");
|
||||
ErrorCode AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_AGREE = new ErrorCode(1011000108, "退货失败,售后单状态不处于【待买家退货】");
|
||||
ErrorCode AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY = new ErrorCode(1011000109, "确认收货失败,售后单状态不处于【待确认收货】");
|
||||
ErrorCode AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND = new ErrorCode(1011000110, "退款失败,售后单状态不是【待退款】");
|
||||
// ========== After Sale 模块 1-011-000-100 ==========
|
||||
ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在");
|
||||
ErrorCode AFTER_SALE_CREATE_FAIL_REFUND_PRICE_ERROR = new ErrorCode(1_011_000_101, "申请退款金额错误");
|
||||
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_CANCELED = new ErrorCode(1_011_000_102, "订单已关闭,无法申请售后");
|
||||
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_PAID = new ErrorCode(1_011_000_103, "订单未支付,无法申请售后");
|
||||
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_DELIVERED = new ErrorCode(1_011_000_104, "订单未发货,无法申请【退货退款】售后");
|
||||
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_ITEM_APPLIED = new ErrorCode(1_011_000_105, "订单项已申请售后,无法重复申请");
|
||||
ErrorCode AFTER_SALE_AUDIT_FAIL_STATUS_NOT_APPLY = new ErrorCode(1_011_000_106, "审批失败,售后状态不处于审批中");
|
||||
ErrorCode AFTER_SALE_UPDATE_STATUS_FAIL = new ErrorCode(1_011_000_107, "操作售后单失败,请刷新后重试");
|
||||
ErrorCode AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_AGREE = new ErrorCode(1_011_000_108, "退货失败,售后单状态不处于【待买家退货】");
|
||||
ErrorCode AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY = new ErrorCode(1_011_000_109, "确认收货失败,售后单状态不处于【待确认收货】");
|
||||
ErrorCode AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND = new ErrorCode(1_011_000_110, "退款失败,售后单状态不是【待退款】");
|
||||
ErrorCode AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE_OR_BUYER_DELIVERY =
|
||||
new ErrorCode(1011000111, "取消售后单失败,售后单状态不是【待审核】或【卖家同意】或【商家待收货】");
|
||||
new ErrorCode(1_011_000_111, "取消售后单失败,售后单状态不是【待审核】或【卖家同意】或【商家待收货】");
|
||||
|
||||
// ========== Cart 模块 1011002000 ==========
|
||||
ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1011002000, "购物车项不存在");
|
||||
// ========== Cart 模块 1-011-002-000 ==========
|
||||
ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1_011_002_000, "购物车项不存在");
|
||||
|
||||
// ========== Price 相关 1011003000 ============
|
||||
ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011003000, "支付价格计算异常,原因:价格小于等于 0");
|
||||
ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1011003002, "计算快递运费异常,找不到对应的运费模板");
|
||||
ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1011003004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵");
|
||||
// ========== Price 相关 1-011-003-000 ============
|
||||
ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1_011_003_000, "支付价格计算异常,原因:价格小于等于 0");
|
||||
ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1_011_003_002, "计算快递运费异常,找不到对应的运费模板");
|
||||
ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1_011_003_004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵");
|
||||
|
||||
// ========== 物流 Express 模块 1011004000 ==========
|
||||
ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1011004000, "快递公司不存在");
|
||||
ErrorCode EXPRESS_CODE_DUPLICATE = new ErrorCode(1011004001, "已经存在该编码的快递公司");
|
||||
ErrorCode EXPRESS_CLIENT_NOT_PROVIDE = new ErrorCode(1011004002, "需要接入快递服务商,比如【快递100】");
|
||||
ErrorCode EXPRESS_STATUS_NOT_ENABLE = new ErrorCode(1011004003, "快递公司未启用");
|
||||
// ========== 物流 Express 模块 1-011-004-000 ==========
|
||||
ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1_011_004_000, "快递公司不存在");
|
||||
ErrorCode EXPRESS_CODE_DUPLICATE = new ErrorCode(1_011_004_001, "已经存在该编码的快递公司");
|
||||
ErrorCode EXPRESS_CLIENT_NOT_PROVIDE = new ErrorCode(1_011_004_002, "需要接入快递服务商,比如【快递100】");
|
||||
ErrorCode EXPRESS_STATUS_NOT_ENABLE = new ErrorCode(1_011_004_003, "快递公司未启用");
|
||||
|
||||
ErrorCode EXPRESS_API_QUERY_ERROR = new ErrorCode(1011004101, "快递查询接口异常");
|
||||
ErrorCode EXPRESS_API_QUERY_FAILED = new ErrorCode(1011004102, "快递查询返回失败,原因:{}");
|
||||
ErrorCode EXPRESS_API_QUERY_ERROR = new ErrorCode(1_011_004_101, "快递查询接口异常");
|
||||
ErrorCode EXPRESS_API_QUERY_FAILED = new ErrorCode(1_011_004_102, "快递查询返回失败,原因:{}");
|
||||
|
||||
// ========== 物流 Template 模块 1011005000 ==========
|
||||
ErrorCode EXPRESS_TEMPLATE_NAME_DUPLICATE = new ErrorCode(1011005000, "已经存在该运费模板名");
|
||||
ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1011005001, "运费模板不存在");
|
||||
// ========== 物流 Template 模块 1-011-005-000 ==========
|
||||
ErrorCode EXPRESS_TEMPLATE_NAME_DUPLICATE = new ErrorCode(1_011_005_000, "已经存在该运费模板名");
|
||||
ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1_011_005_001, "运费模板不存在");
|
||||
|
||||
// ========== 物流 PICK_UP 模块 1011006000 ==========
|
||||
ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1011006000, "自提门店不存在");
|
||||
// ========== 物流 PICK_UP 模块 1-011-006-000 ==========
|
||||
ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1_011_006_000, "自提门店不存在");
|
||||
|
||||
// ========== 分销用户 模块 1-011-007-000 ==========
|
||||
ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1_011_007_000, "分销用户不存在");
|
||||
ErrorCode BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH = new ErrorCode(1_011_007_001, "用户冻结佣金({})数量不足");
|
||||
ErrorCode BROKERAGE_BIND_SELF = new ErrorCode(1_011_007_002, "不能绑定自己");
|
||||
ErrorCode BROKERAGE_BIND_USER_NOT_ENABLED = new ErrorCode(1_011_007_003, "绑定用户没有推广资格");
|
||||
ErrorCode BROKERAGE_BIND_CONDITION_ADMIN = new ErrorCode(1_011_007_004, "仅可在后台绑定推广员");
|
||||
ErrorCode BROKERAGE_BIND_MODE_REGISTER = new ErrorCode(1_011_007_005, "只有在注册时可以绑定");
|
||||
ErrorCode BROKERAGE_BIND_OVERRIDE = new ErrorCode(1_011_007_006, "已绑定了推广人");
|
||||
ErrorCode BROKERAGE_BIND_LOOP = new ErrorCode(1_011_007_007, "下级不能绑定自己的上级");
|
||||
|
||||
|
||||
// ========== 分销用户 模块 1011007000 ==========
|
||||
ErrorCode BROKERAGE_USER_NOT_EXISTS = new ErrorCode(1011007000, "分销用户不存在");
|
||||
ErrorCode BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH = new ErrorCode(1011007001, "用户冻结佣金({})数量不足");
|
||||
ErrorCode BROKERAGE_BIND_SELF = new ErrorCode(1011007002, "不能绑定自己");
|
||||
ErrorCode BROKERAGE_BIND_USER_NOT_ENABLED = new ErrorCode(1011007003, "绑定用户没有推广资格");
|
||||
ErrorCode BROKERAGE_BIND_CONDITION_ADMIN = new ErrorCode(1011007004, "仅可在后台绑定推广员");
|
||||
ErrorCode BROKERAGE_BIND_MODE_REGISTER = new ErrorCode(1011007005, "只有在注册时可以绑定");
|
||||
ErrorCode BROKERAGE_BIND_OVERRIDE = new ErrorCode(1011007006, "已绑定了推广人");
|
||||
ErrorCode BROKERAGE_BIND_LOOP = new ErrorCode(1011007007, "下级不能绑定自己的上级");
|
||||
|
||||
|
||||
// ========== 分销提现 模块 1011008000 ==========
|
||||
ErrorCode BROKERAGE_WITHDRAW_NOT_EXISTS = new ErrorCode(1011008000, "佣金提现记录不存在");
|
||||
ErrorCode BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING = new ErrorCode(1011008001, "佣金提现记录状态不是审核中");
|
||||
ErrorCode BROKERAGE_WITHDRAW_MIN_PRICE = new ErrorCode(1011008002, "提现金额不能低于 {} 元");
|
||||
ErrorCode BROKERAGE_WITHDRAW_USER_BALANCE_NOT_ENOUGH = new ErrorCode(1011008003, "您当前最多可提现 {} 元");
|
||||
// ========== 分销提现 模块 1-011-008-000 ==========
|
||||
ErrorCode BROKERAGE_WITHDRAW_NOT_EXISTS = new ErrorCode(1_011_008_000, "佣金提现记录不存在");
|
||||
ErrorCode BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING = new ErrorCode(1_011_008_001, "佣金提现记录状态不是审核中");
|
||||
ErrorCode BROKERAGE_WITHDRAW_MIN_PRICE = new ErrorCode(1_011_008_002, "提现金额不能低于 {} 元");
|
||||
ErrorCode BROKERAGE_WITHDRAW_USER_BALANCE_NOT_ENOUGH = new ErrorCode(1_011_008_003, "您当前最多可提现 {} 元");
|
||||
|
||||
}
|
||||
|
@@ -1,28 +1,35 @@
|
||||
package cn.iocoder.yudao.module.trade.enums.aftersale;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* 售后操作类型的枚举
|
||||
*
|
||||
* @author 陈賝
|
||||
* @since 2023/6/13 13:53
|
||||
*/
|
||||
// TODO @chenchen:可以 lombok 简化构造方法,和 get 方法
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum AfterSaleOperateTypeEnum {
|
||||
|
||||
/**
|
||||
* 用户申请
|
||||
*/
|
||||
APPLY("用户申请"),
|
||||
MEMBER_CREATE(10, "会员申请退款"),
|
||||
ADMIN_AGREE_APPLY(11, "商家同意退款"),
|
||||
ADMIN_DISAGREE_APPLY(12, "商家拒绝退款"),
|
||||
MEMBER_DELIVERY(20, "会员填写退货物流信息,快递公司:{deliveryName},快递单号:{logisticsNo}"),
|
||||
ADMIN_AGREE_RECEIVE(21, "商家收货"),
|
||||
ADMIN_DISAGREE_RECEIVE(22, "商家拒绝收货,原因:{reason}"),
|
||||
ADMIN_REFUND(30, "商家退款"),
|
||||
MEMBER_CANCEL(40, "会员取消退款"),
|
||||
;
|
||||
|
||||
private final String description;
|
||||
|
||||
AfterSaleOperateTypeEnum(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String description() {
|
||||
return description;
|
||||
}
|
||||
/**
|
||||
* 操作类型
|
||||
*/
|
||||
private final Integer type;
|
||||
/**
|
||||
* 操作描述
|
||||
*/
|
||||
private final String content;
|
||||
|
||||
}
|
||||
|
@@ -18,15 +18,15 @@ public enum BrokerageBindModeEnum implements IntArrayValuable {
|
||||
/**
|
||||
* 只要用户没有推广人,随时都可以绑定分销关系
|
||||
*/
|
||||
ANYTIME(1, "没有推广人"),
|
||||
ANYTIME(1, "首次绑定"),
|
||||
/**
|
||||
* 仅新用户注册时才能绑定推广关系
|
||||
*/
|
||||
REGISTER(2, "新用户"),
|
||||
REGISTER(2, "注册绑定"),
|
||||
/**
|
||||
* 每次扫码都覆盖
|
||||
*/
|
||||
OVERRIDE(3, "扫码覆盖"),
|
||||
OVERRIDE(3, "覆盖绑定"),
|
||||
;
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageBindModeEnum::getMode).toArray();
|
||||
|
@@ -17,7 +17,7 @@ public enum BrokerageRecordBizTypeEnum implements IntArrayValuable {
|
||||
|
||||
ORDER(1, "获得推广佣金", "获得推广佣金 {}", true),
|
||||
WITHDRAW(2, "提现申请", "提现申请扣除佣金 {}", false),
|
||||
WITHDRAW_REJECT(3, "提现申请驳回", "提现申请驳回返还佣金 {}", true),
|
||||
WITHDRAW_REJECT(3, "提现申请驳回", "提现申请驳回,返还佣金 {}", true),
|
||||
;
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(BrokerageRecordBizTypeEnum::getType).toArray();
|
||||
|
@@ -6,6 +6,7 @@ import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
// TODO 芋艿:提现的打通,在纠结下;
|
||||
/**
|
||||
* 佣金提现状态枚举
|
||||
*
|
||||
|
@@ -17,8 +17,7 @@ public enum TradeOrderCancelTypeEnum implements IntArrayValuable {
|
||||
|
||||
PAY_TIMEOUT(10, "超时未支付"),
|
||||
AFTER_SALE_CLOSE(20, "退款关闭"),
|
||||
MEMBER_CANCEL(30, "买家取消"),
|
||||
PAY_ON_DELIVERY(40, "已通过货到付款交易"),; // TODO 芋艿:这个类型,是不是可以去掉
|
||||
MEMBER_CANCEL(30, "买家取消");
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderCancelTypeEnum::getType).toArray();
|
||||
|
||||
|
@@ -14,18 +14,26 @@ import lombok.RequiredArgsConstructor;
|
||||
public enum TradeOrderOperateTypeEnum {
|
||||
|
||||
MEMBER_CREATE(1, "用户下单"),
|
||||
ADMIN_UPDATE_PRICE(2, "订单价格 {oldPayPrice} 修改,实际支付金额为 {newPayPrice} 元"),
|
||||
MEMBER_PAY(10, "用户付款成功"),
|
||||
ADMIN_DELIVERY(20, "已发货,快递公司:{deliveryName},快递单号:{logisticsNo}"),
|
||||
MEMBER_RECEIVE(30, "用户已收货"),
|
||||
MEMBER_COMMENT(31, "用户评价"),
|
||||
SYSTEM_RECEIVE(31, "到期未收货,系统自动确认收货"),
|
||||
MEMBER_COMMENT(33, "用户评价"),
|
||||
SYSTEM_COMMENT(34, "到期未评价,系统自动评价"),
|
||||
MEMBER_CANCEL(40, "取消订单"),
|
||||
MEMBER_DELETE(41, "删除订单"),
|
||||
SYSTEM_CANCEL(41, "到期未支付,系统自动取消订单"),
|
||||
// 42 预留:管理员取消订单
|
||||
ADMIN_CANCEL_AFTER_SALE(43, "订单全部售后,管理员自动取消订单"),
|
||||
MEMBER_DELETE(49, "删除订单"),
|
||||
;
|
||||
|
||||
/**
|
||||
* 类型
|
||||
* 操作类型
|
||||
*/
|
||||
private final Integer type;
|
||||
/**
|
||||
* 类型
|
||||
* 操作描述
|
||||
*/
|
||||
private final String content;
|
||||
|
||||
|
@@ -10,11 +10,11 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;
|
||||
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserWithdrawSummaryBO;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryRespBO;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -88,27 +88,24 @@ public class BrokerageUserController {
|
||||
// 分页查询
|
||||
PageResult<BrokerageUserDO> pageResult = brokerageUserService.getBrokerageUserPage(pageVO);
|
||||
|
||||
// 涉及到的用户
|
||||
Set<Long> userIds = convertSet(pageResult.getList(), BrokerageUserDO::getId);
|
||||
// 查询用户信息
|
||||
Set<Long> userIds = convertSet(pageResult.getList(), BrokerageUserDO::getId);
|
||||
Map<Long, MemberUserRespDTO> userMap = memberUserApi.getUserMap(userIds);
|
||||
// TODO @疯狂:看看下面两个 getBrokerageUserCountByBindUserId、getWithdrawSummaryByUserId 有没可能一次性出结果,不然 n 次有点太花性能了;
|
||||
// 合计分佣订单
|
||||
Map<Long, UserBrokerageSummaryBO> userOrderSummaryMap = convertMap(userIds,
|
||||
userId -> userId,
|
||||
userId -> brokerageRecordService.getUserBrokerageSummaryByUserId(userId,
|
||||
BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus()));
|
||||
// 合计推广用户数量
|
||||
// 合计分佣的推广订单
|
||||
Map<Long, UserBrokerageSummaryRespBO> brokerageOrderSummaryMap = brokerageRecordService.getUserBrokerageSummaryMapByUserId(
|
||||
userIds, BrokerageRecordBizTypeEnum.ORDER.getType(), BrokerageRecordStatusEnum.SETTLEMENT.getStatus());
|
||||
// 合计分佣的推广用户
|
||||
// TODO @疯狂:转成 map 批量读取
|
||||
Map<Long, Long> brokerageUserCountMap = convertMap(userIds,
|
||||
userId -> userId,
|
||||
userId -> brokerageUserService.getBrokerageUserCountByBindUserId(userId, null));
|
||||
// 合计提现
|
||||
Map<Long, UserWithdrawSummaryBO> withdrawMap = convertMap(userIds,
|
||||
userId -> userId,
|
||||
userId -> brokerageWithdrawService.getWithdrawSummaryByUserId(userId, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS));
|
||||
// 合计分佣的提现
|
||||
// TODO @疯狂:如果未来支持了打款这个动作,可能 status 会不对;
|
||||
Map<Long, BrokerageWithdrawSummaryRespBO> withdrawMap = brokerageWithdrawService.getWithdrawSummaryMapByUserId(
|
||||
userIds, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS);
|
||||
// 拼接返回
|
||||
return success(BrokerageUserConvert.INSTANCE.convertPage(pageResult, userMap, brokerageUserCountMap,
|
||||
userOrderSummaryMap, withdrawMap));
|
||||
brokerageOrderSummaryMap, withdrawMap));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -21,25 +21,25 @@ public class BrokerageUserRespVO extends BrokerageUserBaseVO {
|
||||
|
||||
// ========== 用户信息 ==========
|
||||
|
||||
@Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png")
|
||||
@Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xxx.png")
|
||||
private String avatar;
|
||||
@Schema(description = "用户昵称", example = "李四")
|
||||
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
|
||||
private String nickname;
|
||||
|
||||
// ========== 推广信息 ==========
|
||||
|
||||
@Schema(description = "推广用户数量", example = "20019")
|
||||
@Schema(description = "推广用户数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
|
||||
private Integer brokerageUserCount;
|
||||
@Schema(description = "推广订单数量", example = "20019")
|
||||
@Schema(description = "推广订单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
|
||||
private Integer brokerageOrderCount;
|
||||
@Schema(description = "推广订单金额", example = "20019")
|
||||
@Schema(description = "推广订单金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
|
||||
private Integer brokerageOrderPrice;
|
||||
|
||||
// ========== 提现信息 ==========
|
||||
|
||||
@Schema(description = "已提现金额", example = "20019")
|
||||
@Schema(description = "已提现金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
|
||||
private Integer withdrawPrice;
|
||||
@Schema(description = "已提现次数", example = "20019")
|
||||
@Schema(description = "已提现次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20019")
|
||||
private Integer withdrawCount;
|
||||
|
||||
}
|
||||
|
@@ -19,6 +19,19 @@ import java.util.List;
|
||||
*/
|
||||
@Data
|
||||
public class TradeConfigBaseVO {
|
||||
|
||||
// ========== 售后相关 ==========
|
||||
|
||||
@Schema(description = "售后的退款理由", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "售后的退款理由不能为空")
|
||||
private List<String> afterSaleRefundReasons;
|
||||
|
||||
@Schema(description = "售后的退货理由", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "售后的退货理由不能为空")
|
||||
private List<String> afterSaleReturnReasons;
|
||||
|
||||
// ========== 配送相关 ==========
|
||||
|
||||
/**
|
||||
* 是否启用全场包邮
|
||||
*/
|
||||
@@ -80,7 +93,7 @@ public class TradeConfigBaseVO {
|
||||
private Integer brokerageFrozenDays;
|
||||
|
||||
@Schema(description = "提现方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "[0, 1]")
|
||||
@NotNull(message = "提现方式不能为空")
|
||||
@NotEmpty(message = "提现方式不能为空")
|
||||
@InEnum(value = BrokerageWithdrawTypeEnum.class, message = "提现方式必须是 {value}")
|
||||
private List<Integer> brokerageWithdrawTypes;
|
||||
|
||||
|
@@ -73,7 +73,7 @@ public class TradeOrderController {
|
||||
|
||||
// 查询订单项
|
||||
List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id);
|
||||
// orderLog
|
||||
// TODO @puhui999:orderLog
|
||||
// 拼接数据
|
||||
MemberUserRespDTO user = memberUserApi.getUser(order.getUserId());
|
||||
return success(TradeOrderConvert.INSTANCE.convert(order, orderItems, user));
|
||||
@@ -120,4 +120,6 @@ public class TradeOrderController {
|
||||
return success(true);
|
||||
}
|
||||
|
||||
// TODO :核销逻辑
|
||||
|
||||
}
|
||||
|
@@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSa
|
||||
import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert;
|
||||
import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleOperateTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum;
|
||||
import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.annotations.AfterSaleLog;
|
||||
import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.util.AfterSaleLogUtils;
|
||||
import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService;
|
||||
@@ -21,9 +20,6 @@ import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
@@ -58,20 +54,9 @@ public class AppTradeAfterSaleController {
|
||||
return success(afterSaleService.getApplyingAfterSaleCount(getLoginUserId()));
|
||||
}
|
||||
|
||||
// TODO 芋艿:待实现
|
||||
@GetMapping(value = "/get-reason-list")
|
||||
@Operation(summary = "获得售后原因")
|
||||
@Parameter(name = "way", description = "售后类型", required = true, example = "10")
|
||||
public CommonResult<List<String>> getAfterSaleReasonList(@RequestParam("way") Integer way) {
|
||||
if (Objects.equals(TradeAfterSaleWayEnum.REFUND.getWay(), way)) {
|
||||
return success(Arrays.asList("不想要了", "商品质量问题", "商品描述不符"));
|
||||
}
|
||||
return success(Arrays.asList("不想要了", "商品质量问题", "商品描述不符", "商品错发漏发", "商品包装破损"));
|
||||
}
|
||||
|
||||
@PostMapping(value = "/create")
|
||||
@Operation(summary = "申请售后")
|
||||
@AfterSaleLog(id = "#info.data", content = "'申请售后:售后编号['+#info.data+'],订单编号['+#createReqVO.orderItemId+'], '", operateType = AfterSaleOperateTypeEnum.APPLY)
|
||||
@AfterSaleLog(id = "#info.data", content = "'申请售后:售后编号['+#info.data+'],订单编号['+#createReqVO.orderItemId+'], '", operateType = AfterSaleOperateTypeEnum.MEMBER_CREATE)
|
||||
public CommonResult<Long> createAfterSale(@RequestBody AppTradeAfterSaleCreateReqVO createReqVO) {
|
||||
AfterSaleLogUtils.setBeforeStatus(0);
|
||||
AfterSaleLogUtils.setAfterStatus(TradeAfterSaleStatusEnum.APPLY.getStatus());
|
||||
|
@@ -45,7 +45,7 @@ public class AppBrokerageRecordController {
|
||||
@GetMapping("/get-product-brokerage-price")
|
||||
@Operation(summary = "获得商品的分销金额")
|
||||
public CommonResult<AppBrokerageProductPriceRespVO> getProductBrokeragePrice(@RequestParam("spuId") Long spuId) {
|
||||
return success(brokerageRecordService.calculateProductBrokeragePrice(spuId, getLoginUserId()));
|
||||
return success(brokerageRecordService.calculateProductBrokeragePrice(getLoginUserId(), spuId));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@ import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserWithdrawSummaryBO;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -27,6 +27,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -41,6 +42,7 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class AppBrokerageUserController {
|
||||
|
||||
@Resource
|
||||
private BrokerageUserService brokerageUserService;
|
||||
@Resource
|
||||
@@ -68,31 +70,32 @@ public class AppBrokerageUserController {
|
||||
@Operation(summary = "绑定推广员")
|
||||
@PreAuthenticated
|
||||
public CommonResult<Boolean> bindBrokerageUser(@Valid @RequestBody AppBrokerageUserBindReqVO reqVO) {
|
||||
MemberUserRespDTO user = memberUserApi.getUser(getLoginUserId());
|
||||
return success(brokerageUserService.bindBrokerageUser(user.getId(), reqVO.getBindUserId(), user.getCreateTime()));
|
||||
return success(brokerageUserService.bindBrokerageUser(getLoginUserId(), reqVO.getBindUserId()));
|
||||
}
|
||||
|
||||
@GetMapping("/get-summary")
|
||||
@Operation(summary = "获得个人分销统计")
|
||||
@PreAuthenticated
|
||||
public CommonResult<AppBrokerageUserMySummaryRespVO> getBrokerageUserSummary() {
|
||||
Long userId = getLoginUserId();
|
||||
// TODO @疯狂:后面这种,要不也改成 convert;感觉 controller 这样更容易看到整体;核心其实是 86、8/87、9/90、9/91 这阶段
|
||||
// 统计 yesterdayPrice、withdrawPrice、firstBrokerageUserCount、secondBrokerageUserCount 字段
|
||||
// 查询当前登录用户信息
|
||||
BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(getLoginUserId());
|
||||
// 统计用户昨日的佣金
|
||||
LocalDateTime yesterday = LocalDateTime.now().minusDays(1);
|
||||
LocalDateTime beginTime = LocalDateTimeUtil.beginOfDay(yesterday);
|
||||
LocalDateTime endTime = LocalDateTimeUtil.endOfDay(yesterday);
|
||||
AppBrokerageUserMySummaryRespVO respVO = new AppBrokerageUserMySummaryRespVO()
|
||||
.setYesterdayPrice(brokerageRecordService.getSummaryPriceByUserId(userId, BrokerageRecordBizTypeEnum.ORDER.getType(), beginTime, endTime))
|
||||
.setWithdrawPrice(Optional.ofNullable(brokerageWithdrawService.getWithdrawSummaryByUserId(userId, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS))
|
||||
.map(UserWithdrawSummaryBO::getPrice).orElse(0))
|
||||
.setBrokeragePrice(0).setFrozenPrice(0)
|
||||
.setFirstBrokerageUserCount(brokerageUserService.getBrokerageUserCountByBindUserId(userId, 1))
|
||||
.setSecondBrokerageUserCount(brokerageUserService.getBrokerageUserCountByBindUserId(userId, 2));
|
||||
// 设置 brokeragePrice、frozenPrice 字段
|
||||
Optional.ofNullable(brokerageUserService.getBrokerageUser(userId))
|
||||
.ifPresent(user -> respVO.setBrokeragePrice(user.getBrokeragePrice()).setFrozenPrice(user.getFrozenPrice()));
|
||||
return success(respVO);
|
||||
Integer yesterdayPrice = brokerageRecordService.getSummaryPriceByUserId(brokerageUser.getId(),
|
||||
BrokerageRecordBizTypeEnum.ORDER.getType(), beginTime, endTime);
|
||||
// 统计用户提现的佣金
|
||||
Integer withdrawPrice = brokerageWithdrawService.getWithdrawSummaryListByUserId(Collections.singleton(brokerageUser.getId()),
|
||||
BrokerageWithdrawStatusEnum.AUDIT_SUCCESS).stream()
|
||||
.findFirst().map(BrokerageWithdrawSummaryRespBO::getPrice).orElse(0);
|
||||
// 统计分销用户数量(一级)
|
||||
Long firstBrokerageUserCount = brokerageUserService.getBrokerageUserCountByBindUserId(brokerageUser.getId(), 1);
|
||||
// 统计分销用户数量(二级)
|
||||
Long secondBrokerageUserCount = brokerageUserService.getBrokerageUserCountByBindUserId(brokerageUser.getId(), 2);
|
||||
|
||||
// 拼接返回
|
||||
return success(BrokerageUserConvert.INSTANCE.convert(yesterdayPrice, withdrawPrice, firstBrokerageUserCount, secondBrokerageUserCount, brokerageUser));
|
||||
}
|
||||
|
||||
@GetMapping("/rank-page-by-user-count")
|
||||
|
@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
|
||||
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawCreateReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawRespVO;
|
||||
@@ -32,14 +31,10 @@ public class AppBrokerageWithdrawController {
|
||||
@Resource
|
||||
private BrokerageWithdrawService brokerageWithdrawService;
|
||||
|
||||
@Resource
|
||||
private DictDataApi dictDataApi;
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得分销提现分页")
|
||||
@PreAuthenticated
|
||||
public CommonResult<PageResult<AppBrokerageWithdrawRespVO>> getBrokerageWithdrawPage(AppBrokerageWithdrawPageReqVO pageReqVO) {
|
||||
// 分页查询
|
||||
PageResult<BrokerageWithdrawDO> pageResult = brokerageWithdrawService.getBrokerageWithdrawPage(
|
||||
BrokerageWithdrawConvert.INSTANCE.convert(pageReqVO, getLoginUserId()));
|
||||
return success(BrokerageWithdrawConvert.INSTANCE.convertPage03(pageResult));
|
||||
@@ -49,7 +44,7 @@ public class AppBrokerageWithdrawController {
|
||||
@Operation(summary = "创建分销提现")
|
||||
@PreAuthenticated
|
||||
public CommonResult<Long> createBrokerageWithdraw(@RequestBody @Valid AppBrokerageWithdrawCreateReqVO createReqVO) {
|
||||
return success(brokerageWithdrawService.createBrokerageWithdraw(createReqVO, getLoginUserId()));
|
||||
return success(brokerageWithdrawService.createBrokerageWithdraw(getLoginUserId(), createReqVO));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -4,6 +4,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.SortingField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Range;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "用户 App - 下级分销统计分页 Request VO")
|
||||
@Data
|
||||
@@ -19,7 +22,9 @@ public class AppBrokerageUserChildSummaryPageReqVO extends PageParam {
|
||||
@Schema(description = "排序字段", example = "userCount")
|
||||
private SortingField sortingField;
|
||||
|
||||
@Schema(description = "下级的级别", example = "1") // 1 - 直接下级;2 - 间接下级
|
||||
@Schema(description = "下级的级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") // 1 - 直接下级;2 - 间接下级
|
||||
@NotNull(message = "下级的级别不能为空")
|
||||
@Range(min = 1, max = 2, message = "下级的级别只能是 {min} 或者 {max}")
|
||||
private Integer level;
|
||||
|
||||
}
|
||||
|
@@ -9,6 +9,16 @@ import java.util.List;
|
||||
@Data
|
||||
public class AppTradeConfigRespVO {
|
||||
|
||||
// ========== 售后相关 ==========
|
||||
|
||||
@Schema(description = "售后的退款理由", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<String> afterSaleRefundReasons;
|
||||
|
||||
@Schema(description = "售后的退货理由", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<String> afterSaleReturnReasons;
|
||||
|
||||
// ========== 分销相关 ==========
|
||||
|
||||
@Schema(description = "分销海报地址数组", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<String> brokeragePosterUrls;
|
||||
|
||||
|
@@ -8,10 +8,10 @@ import lombok.Data;
|
||||
@Data
|
||||
public class AppDeliveryConfigRespVO {
|
||||
|
||||
@Schema(description = "腾讯地图 KEY", required = true, example = "123456")
|
||||
@Schema(description = "腾讯地图 KEY", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
|
||||
private String tencentLbsKey;
|
||||
|
||||
@Schema(description = "是否开启自提", required = true, example = "true")
|
||||
@Schema(description = "是否开启自提", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
private Boolean pickUpEnable;
|
||||
|
||||
}
|
||||
|
@@ -7,10 +7,10 @@ import lombok.Data;
|
||||
@Data
|
||||
public class AppDeliveryExpressRespVO {
|
||||
|
||||
@Schema(description = "编号", required = true, example = "1")
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "门店名称", required = true, example = "顺丰")
|
||||
@Schema(description = "门店名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "顺丰")
|
||||
private String name;
|
||||
|
||||
}
|
||||
|
@@ -75,6 +75,7 @@ public class AppTradeOrderController {
|
||||
}
|
||||
|
||||
// TODO @芋艿:如果拼团活动、秒杀活动、砍价活动时,是不是要额外在返回活动之类的信息;
|
||||
// TODO @puhui999:需要的
|
||||
@GetMapping("/get-detail")
|
||||
@Operation(summary = "获得交易订单")
|
||||
@Parameter(name = "id", description = "交易订单编号")
|
||||
@@ -140,7 +141,7 @@ public class AppTradeOrderController {
|
||||
@Operation(summary = "确认交易订单收货")
|
||||
@Parameter(name = "id", description = "交易订单编号")
|
||||
public CommonResult<Boolean> receiveOrder(@RequestParam("id") Long id) {
|
||||
tradeOrderUpdateService.receiveOrder(getLoginUserId(), id);
|
||||
tradeOrderUpdateService.receiveOrderByMember(getLoginUserId(), id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@@ -148,7 +149,7 @@ public class AppTradeOrderController {
|
||||
@Operation(summary = "取消交易订单")
|
||||
@Parameter(name = "id", description = "交易订单编号")
|
||||
public CommonResult<Boolean> cancelOrder(@RequestParam("id") Long id) {
|
||||
tradeOrderUpdateService.cancelOrder(getLoginUserId(), id);
|
||||
tradeOrderUpdateService.cancelOrderByMember(getLoginUserId(), id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@@ -173,7 +174,7 @@ public class AppTradeOrderController {
|
||||
@PostMapping("/item/create-comment")
|
||||
@Operation(summary = "创建交易订单项的评价")
|
||||
public CommonResult<Long> createOrderItemComment(@RequestBody AppTradeOrderItemCommentCreateReqVO createReqVO) {
|
||||
return success(tradeOrderUpdateService.createOrderItemComment(getLoginUserId(), createReqVO));
|
||||
return success(tradeOrderUpdateService.createOrderItemCommentByMember(getLoginUserId(), createReqVO));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -25,12 +25,12 @@ public class AppTradeOrderSettlementReqVO {
|
||||
@Schema(description = "优惠劵编号", example = "1024")
|
||||
private Long couponId;
|
||||
|
||||
@Schema(description = "是否使用积分", required = true, example = "true")
|
||||
@Schema(description = "是否使用积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
@NotNull(message = "是否使用积分不能为空")
|
||||
private Boolean pointStatus;
|
||||
|
||||
// ========== 配送相关相关字段 ==========
|
||||
@Schema(description = "配送方式", example = "1")
|
||||
@Schema(description = "配送方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@InEnum(value = DeliveryTypeEnum.class, message = "配送方式不正确")
|
||||
private Integer deliveryType;
|
||||
|
||||
|
@@ -13,7 +13,7 @@ import java.util.List;
|
||||
@Data
|
||||
public class AppTradeOrderSettlementRespVO {
|
||||
|
||||
@Schema(description = "交易类型", required = true, example = "1") // 对应 TradeOrderTypeEnum 枚举
|
||||
@Schema(description = "交易类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") // 对应 TradeOrderTypeEnum 枚举
|
||||
private Integer type = 1; // TODO 芋艿:改成计算
|
||||
|
||||
@Schema(description = "购物项数组", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@@ -37,6 +37,8 @@ public class AppTradeOrderSettlementRespVO {
|
||||
|
||||
// ========== SPU 信息 ==========
|
||||
|
||||
@Schema(description = "品类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
|
||||
private Long categoryId;
|
||||
@Schema(description = "SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
|
||||
private Long spuId;
|
||||
@Schema(description = "SPU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "Apple iPhone 12")
|
||||
|
@@ -1,13 +1,17 @@
|
||||
package cn.iocoder.yudao.module.trade.convert.brokerage;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user.BrokerageUserRespVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserMySummaryRespVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByUserCountRespVO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserWithdrawSummaryBO;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryRespBO;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingTarget;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
@@ -30,29 +34,27 @@ public interface BrokerageUserConvert {
|
||||
|
||||
List<BrokerageUserRespVO> convertList(List<BrokerageUserDO> list);
|
||||
|
||||
PageResult<BrokerageUserRespVO> convertPage(PageResult<BrokerageUserDO> page, Map<Long, MemberUserRespDTO> userMap, Map<Long, Long> brokerageUserCountMap, Map<Long, UserBrokerageSummaryBO> userOrderSummaryMap);
|
||||
PageResult<BrokerageUserRespVO> convertPage(PageResult<BrokerageUserDO> page, Map<Long, MemberUserRespDTO> userMap, Map<Long, Long> brokerageUserCountMap, Map<Long, UserBrokerageSummaryRespBO> userOrderSummaryMap);
|
||||
|
||||
default PageResult<BrokerageUserRespVO> convertPage(PageResult<BrokerageUserDO> pageResult,
|
||||
Map<Long, MemberUserRespDTO> userMap,
|
||||
Map<Long, Long> brokerageUserCountMap,
|
||||
Map<Long, UserBrokerageSummaryBO> userOrderSummaryMap,
|
||||
Map<Long, UserWithdrawSummaryBO> withdrawMap) {
|
||||
Map<Long, UserBrokerageSummaryRespBO> userOrderSummaryMap,
|
||||
Map<Long, BrokerageWithdrawSummaryRespBO> withdrawMap) {
|
||||
PageResult<BrokerageUserRespVO> result = convertPage(pageResult, userMap, brokerageUserCountMap, userOrderSummaryMap);
|
||||
for (BrokerageUserRespVO userVO : result.getList()) {
|
||||
// 用户信息
|
||||
copyTo(userMap.get(userVO.getId()), userVO);
|
||||
|
||||
// 推广用户数量
|
||||
userVO.setBrokerageUserCount(MapUtil.getInt(brokerageUserCountMap, userVO.getId(), 0));
|
||||
// 推广订单数量、推广订单金额
|
||||
Optional<UserBrokerageSummaryBO> orderSummaryOptional = Optional.ofNullable(userOrderSummaryMap.get(userVO.getId()));
|
||||
userVO.setBrokerageOrderCount(orderSummaryOptional.map(UserBrokerageSummaryBO::getCount).orElse(0))
|
||||
.setBrokerageOrderPrice(orderSummaryOptional.map(UserBrokerageSummaryBO::getPrice).orElse(0));
|
||||
Optional<UserBrokerageSummaryRespBO> orderSummaryOptional = Optional.ofNullable(userOrderSummaryMap.get(userVO.getId()));
|
||||
userVO.setBrokerageOrderCount(orderSummaryOptional.map(UserBrokerageSummaryRespBO::getCount).orElse(0))
|
||||
.setBrokerageOrderPrice(orderSummaryOptional.map(UserBrokerageSummaryRespBO::getPrice).orElse(0));
|
||||
// 已提现次数、已提现金额
|
||||
Optional<UserWithdrawSummaryBO> withdrawSummaryOptional = Optional.ofNullable(withdrawMap.get(userVO.getId()));
|
||||
userVO.setWithdrawCount(withdrawSummaryOptional.map(UserWithdrawSummaryBO::getCount).orElse(0))
|
||||
.setWithdrawPrice(withdrawSummaryOptional.map(UserWithdrawSummaryBO::getPrice).orElse(0));
|
||||
userVO.setWithdrawCount(0).setWithdrawPrice(0);
|
||||
Optional<BrokerageWithdrawSummaryRespBO> withdrawSummaryOptional = Optional.ofNullable(withdrawMap.get(userVO.getId()));
|
||||
userVO.setWithdrawCount(withdrawSummaryOptional.map(BrokerageWithdrawSummaryRespBO::getCount).orElse(0))
|
||||
.setWithdrawPrice(withdrawSummaryOptional.map(BrokerageWithdrawSummaryRespBO::getPrice).orElse(0));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -71,4 +73,25 @@ public interface BrokerageUserConvert {
|
||||
|
||||
void copyTo(MemberUserRespDTO from, @MappingTarget AppBrokerageUserRankByUserCountRespVO to);
|
||||
|
||||
default AppBrokerageUserMySummaryRespVO convert(Integer yesterdayPrice, Integer withdrawPrice,
|
||||
Long firstBrokerageUserCount, Long secondBrokerageUserCount,
|
||||
BrokerageUserDO brokerageUser) {
|
||||
AppBrokerageUserMySummaryRespVO respVO = new AppBrokerageUserMySummaryRespVO()
|
||||
.setYesterdayPrice(ObjUtil.defaultIfNull(yesterdayPrice, 0))
|
||||
.setWithdrawPrice(ObjUtil.defaultIfNull(withdrawPrice, 0))
|
||||
.setBrokeragePrice(0).setFrozenPrice(0)
|
||||
.setFirstBrokerageUserCount(ObjUtil.defaultIfNull(firstBrokerageUserCount, 0L))
|
||||
.setSecondBrokerageUserCount(ObjUtil.defaultIfNull(secondBrokerageUserCount, 0L));
|
||||
// 设置 brokeragePrice、frozenPrice 字段
|
||||
Optional.ofNullable(brokerageUser)
|
||||
.ifPresent(user -> respVO.setBrokeragePrice(user.getBrokeragePrice()).setFrozenPrice(user.getFrozenPrice()));
|
||||
return respVO;
|
||||
}
|
||||
|
||||
default void copyTo(IPage<AppBrokerageUserChildSummaryRespVO> pageResult, Map<Long, MemberUserRespDTO> userMap) {
|
||||
for (AppBrokerageUserChildSummaryRespVO vo : pageResult.getRecords()) {
|
||||
Optional.ofNullable(userMap.get(vo.getId())).ifPresent(user ->
|
||||
vo.setNickname(user.getNickname()).setAvatar(user.getAvatar()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -90,7 +90,7 @@ public interface TradeOrderConvert {
|
||||
|
||||
default ProductSkuUpdateStockReqDTO convert(List<TradeOrderItemDO> list) {
|
||||
List<ProductSkuUpdateStockReqDTO.Item> items = CollectionUtils.convertList(list, item ->
|
||||
new ProductSkuUpdateStockReqDTO.Item().setId(item.getSkuId()).setIncrCount(-item.getCount()));
|
||||
new ProductSkuUpdateStockReqDTO.Item().setId(item.getSkuId()).setIncrCount(item.getCount()));
|
||||
return new ProductSkuUpdateStockReqDTO(items);
|
||||
}
|
||||
default ProductSkuUpdateStockReqDTO convertNegative(List<AppTradeOrderSettlementReqVO.Item> list) {
|
||||
@@ -110,7 +110,7 @@ public interface TradeOrderConvert {
|
||||
createReqDTO.setSubject(subject);
|
||||
createReqDTO.setBody(subject); // TODO 芋艿:临时写死
|
||||
// 订单相关字段
|
||||
createReqDTO.setPrice(order.getPayPrice()).setExpireTime(addTime(orderProperties.getExpireTime()));
|
||||
createReqDTO.setPrice(order.getPayPrice()).setExpireTime(addTime(orderProperties.getPayExpireTime()));
|
||||
return createReqDTO;
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ public interface TradeOrderConvert {
|
||||
TradeOrderProperties tradeOrderProperties,
|
||||
DeliveryExpressDO express) {
|
||||
AppTradeOrderDetailRespVO orderVO = convert3(order, orderItems);
|
||||
orderVO.setPayExpireTime(addTime(tradeOrderProperties.getExpireTime()));
|
||||
orderVO.setPayExpireTime(addTime(tradeOrderProperties.getPayExpireTime()));
|
||||
if (StrUtil.isNotEmpty(order.getPayChannelCode())) {
|
||||
orderVO.setPayChannelName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.CHANNEL_CODE, order.getPayChannelCode()));
|
||||
}
|
||||
|
@@ -35,6 +35,19 @@ public class TradeConfigDO extends BaseDO {
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
// ========== 售后相关 ==========
|
||||
|
||||
/**
|
||||
* 售后的退款理由
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private List<String> afterSaleRefundReasons;
|
||||
/**
|
||||
* 售后的退货理由
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private List<String> afterSaleReturnReasons;
|
||||
|
||||
// ========== 配送相关 ==========
|
||||
|
||||
/**
|
||||
|
@@ -105,6 +105,8 @@ public class TradeOrderDO extends BaseDO {
|
||||
*/
|
||||
private Boolean commentStatus;
|
||||
|
||||
// TODO @疯狂:加一个推广人编号;
|
||||
|
||||
// ========== 价格 + 支付基本信息 ==========
|
||||
|
||||
// 价格文档 - 淘宝:https://open.taobao.com/docV3.htm?docId=108471&docType=1
|
||||
|
@@ -146,18 +146,20 @@ public class TradeOrderItemDO extends BaseDO {
|
||||
private Integer pointPrice;
|
||||
/**
|
||||
* 使用的积分
|
||||
*
|
||||
* 目的:用于后续取消或者售后订单时,需要归还赠送
|
||||
*/
|
||||
private Integer usePoint;
|
||||
/**
|
||||
* 赠送的积分
|
||||
*
|
||||
* 目的:用于后续取消或者售后订单时,需要扣减赠送
|
||||
*/
|
||||
private Integer givePoint;
|
||||
/**
|
||||
* VIP 减免金额,单位:分
|
||||
*/
|
||||
private Integer vipPrice;
|
||||
// TODO @芋艿:如果商品 vip 折扣时,到底是新增一个 vipPrice 记录优惠记录,还是 vipDiscountPrice,记录 vip 的优惠;还是直接使用 vipPrice;
|
||||
// 目前 crmeb 的选择,单独一个 vipPrice 记录优惠价格;感觉不一定合理,可以在看看有赞的;
|
||||
|
||||
// ========== 售后基本信息 ==========
|
||||
|
||||
|
@@ -1,20 +1,24 @@
|
||||
package cn.iocoder.yudao.module.trade.dal.mysql.brokerage;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByPriceRespVO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryBO;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryRespBO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.github.yulichang.toolkit.MPJWrappers;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 佣金记录 Mapper
|
||||
@@ -52,11 +56,28 @@ public interface BrokerageRecordMapper extends BaseMapperX<BrokerageRecordDO> {
|
||||
BrokerageRecordDO::getUserId, userId);
|
||||
}
|
||||
|
||||
@Select("SELECT COUNT(1), SUM(price) FROM trade_brokerage_record " +
|
||||
"WHERE user_id = #{userId} AND biz_type = #{bizType} AND status = #{status} AND deleted = FALSE")
|
||||
UserBrokerageSummaryBO selectCountAndSumPriceByUserIdAndBizTypeAndStatus(@Param("userId") Long userId,
|
||||
@Param("bizType") Integer bizType,
|
||||
@Param("status") Integer status);
|
||||
default List<UserBrokerageSummaryRespBO> selectCountAndSumPriceByUserIdInAndBizTypeAndStatus(Collection<Long> userIds,
|
||||
Integer bizType,
|
||||
Integer status) {
|
||||
List<Map<String, Object>> list = selectMaps(MPJWrappers.lambdaJoin(BrokerageRecordDO.class)
|
||||
.select(BrokerageRecordDO::getUserId)
|
||||
.selectCount(BrokerageRecordDO::getId, UserBrokerageSummaryRespBO::getCount)
|
||||
.selectSum(BrokerageRecordDO::getPrice)
|
||||
.in(BrokerageRecordDO::getUserId, userIds)
|
||||
.eq(BrokerageRecordDO::getBizId, bizType)
|
||||
.eq(BrokerageRecordDO::getStatus, status)
|
||||
.groupBy(BrokerageRecordDO::getUserId));
|
||||
return BeanUtil.copyToList(list, UserBrokerageSummaryRespBO.class);
|
||||
// selectJoinList有BUG,会与租户插件冲突:解析SQL时,发生异常 https://gitee.com/best_handsome/mybatis-plus-join/issues/I84GYW
|
||||
// return selectJoinList(UserBrokerageSummaryBO.class, MPJWrappers.lambdaJoin(BrokerageRecordDO.class)
|
||||
// .select(BrokerageRecordDO::getUserId)
|
||||
// .selectCount(BrokerageRecordDO::getId, UserBrokerageSummaryBO::getCount)
|
||||
// .selectSum(BrokerageRecordDO::getPrice)
|
||||
// .in(BrokerageRecordDO::getUserId, userIds)
|
||||
// .eq(BrokerageRecordDO::getBizId, bizType)
|
||||
// .eq(BrokerageRecordDO::getStatus, status)
|
||||
// .groupBy(BrokerageRecordDO::getUserId));
|
||||
}
|
||||
|
||||
@Select("SELECT SUM(price) FROM trade_brokerage_record " +
|
||||
"WHERE user_id = #{userId} AND biz_type = #{bizType} " +
|
||||
|
@@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.trade.dal.mysql.brokerage;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.SortingField;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user.BrokerageUserPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserChildSummaryRespVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByUserCountRespVO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;
|
||||
@@ -139,8 +139,11 @@ public interface BrokerageUserMapper extends BaseMapperX<BrokerageUserDO> {
|
||||
@Param("endTime") LocalDateTime endTime);
|
||||
|
||||
IPage<AppBrokerageUserChildSummaryRespVO> selectSummaryPageByUserId(Page<?> page,
|
||||
@Param("param") AppBrokerageUserChildSummaryPageReqVO param,
|
||||
@Param("userId") Long userId);
|
||||
@Param("ids") List<Long> ids,
|
||||
@Param("bizType") Integer bizType,
|
||||
@Param("status") Integer status,
|
||||
@Param("bindUserIds") List<Long> bindUserIds,
|
||||
@Param("sortingField") SortingField sortingField);
|
||||
|
||||
default List<BrokerageUserDO> selectListByBindUserId(Long bindUserId) {
|
||||
return selectList(BrokerageUserDO::getBindUserId, bindUserId);
|
||||
|
@@ -1,15 +1,19 @@
|
||||
package cn.iocoder.yudao.module.trade.dal.mysql.brokerage;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserWithdrawSummaryBO;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 佣金提现 Mapper
|
||||
@@ -37,9 +41,23 @@ public interface BrokerageWithdrawMapper extends BaseMapperX<BrokerageWithdrawDO
|
||||
.eq(BrokerageWithdrawDO::getStatus, status));
|
||||
}
|
||||
|
||||
@Select("SELECT COUNT(1) AS count, SUM(price) AS price FROM trade_brokerage_withdraw " +
|
||||
"WHERE user_id = #{userId} AND status = #{status} AND deleted = FALSE")
|
||||
UserWithdrawSummaryBO selectCountAndSumPriceByUserIdAndStatus(@Param("userId") Long userId,
|
||||
@Param("status") Integer status);
|
||||
default List<BrokerageWithdrawSummaryRespBO> selectCountAndSumPriceByUserIdAndStatus(Collection<Long> userIds, Integer status) {
|
||||
List<Map<String, Object>> list = selectMaps(new MPJLambdaWrapper<BrokerageWithdrawDO>()
|
||||
.select(BrokerageWithdrawDO::getUserId)
|
||||
.selectCount(BrokerageWithdrawDO::getId, BrokerageWithdrawSummaryRespBO::getCount)
|
||||
.selectSum(BrokerageWithdrawDO::getPrice)
|
||||
.in(BrokerageWithdrawDO::getUserId, userIds)
|
||||
.eq(BrokerageWithdrawDO::getStatus, status)
|
||||
.groupBy(BrokerageWithdrawDO::getUserId));
|
||||
return BeanUtil.copyToList(list, BrokerageWithdrawSummaryRespBO.class);
|
||||
// selectJoinList有BUG,会与租户插件冲突:解析SQL时,发生异常 https://gitee.com/best_handsome/mybatis-plus-join/issues/I84GYW
|
||||
// return selectJoinList(UserWithdrawSummaryBO.class, new MPJLambdaWrapper<BrokerageWithdrawDO>()
|
||||
// .select(BrokerageWithdrawDO::getUserId)
|
||||
// .selectCount(BrokerageWithdrawDO::getId, UserWithdrawSummaryBO::getCount)
|
||||
// .selectSum(BrokerageWithdrawDO::getPrice)
|
||||
// .in(BrokerageWithdrawDO::getUserId, userIds)
|
||||
// .eq(BrokerageWithdrawDO::getStatus, status)
|
||||
// .groupBy(BrokerageWithdrawDO::getUserId));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -38,4 +38,10 @@ public interface TradeOrderItemMapper extends BaseMapperX<TradeOrderItemDO> {
|
||||
.eq(TradeOrderItemDO::getUserId, loginUserId));
|
||||
}
|
||||
|
||||
default List<TradeOrderItemDO> selectListByOrderIdAndCommentStatus(Long orderId, Boolean commentStatus) {
|
||||
return selectList(new LambdaQueryWrapperX<TradeOrderItemDO>()
|
||||
.eq(TradeOrderItemDO::getOrderId, orderId)
|
||||
.eq(TradeOrderItemDO::getCommentStatus, commentStatus));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -9,6 +9,8 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Mapper
|
||||
@@ -58,4 +60,25 @@ public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> {
|
||||
.eq(TradeOrderDO::getId, orderId)
|
||||
.eq(TradeOrderDO::getUserId, loginUserId));
|
||||
}
|
||||
|
||||
default List<TradeOrderDO> selectListByStatusAndCreateTimeLt(Integer status, LocalDateTime createTime) {
|
||||
return selectList(new LambdaUpdateWrapper<TradeOrderDO>()
|
||||
.eq(TradeOrderDO::getStatus, status)
|
||||
.lt(TradeOrderDO::getCreateTime, createTime));
|
||||
}
|
||||
|
||||
default List<TradeOrderDO> selectListByStatusAndDeliveryTimeLt(Integer status, LocalDateTime deliveryTime) {
|
||||
return selectList(new LambdaUpdateWrapper<TradeOrderDO>()
|
||||
.eq(TradeOrderDO::getStatus, status)
|
||||
.lt(TradeOrderDO::getDeliveryTime, deliveryTime));
|
||||
}
|
||||
|
||||
default List<TradeOrderDO> selectListByStatusAndReceiveTimeLt(Integer status, LocalDateTime receive,
|
||||
Boolean commentStatus) {
|
||||
return selectList(new LambdaUpdateWrapper<TradeOrderDO>()
|
||||
.eq(TradeOrderDO::getStatus, status)
|
||||
.lt(TradeOrderDO::getReceiveTime, receive)
|
||||
.eq(TradeOrderDO::getCommentStatus, commentStatus));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -21,7 +21,8 @@ public @interface AfterSaleLog {
|
||||
/**
|
||||
* 售后 ID
|
||||
*/
|
||||
String id();
|
||||
@Deprecated
|
||||
String id() default "";
|
||||
|
||||
/**
|
||||
* 操作类型
|
||||
@@ -31,6 +32,7 @@ public @interface AfterSaleLog {
|
||||
/**
|
||||
* 日志内容
|
||||
*/
|
||||
@Deprecated
|
||||
String content() default "";
|
||||
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.aop;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.service.OperateLog;
|
||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.annotations.AfterSaleLog;
|
||||
import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogCreateReqDTO;
|
||||
@@ -96,7 +95,7 @@ public class AfterSaleLogAspect {
|
||||
String id = MapUtil.getStr(spelMap, afterSaleLogPoint.id());
|
||||
result.put(ID, id);
|
||||
// 操作类型
|
||||
String operateType = afterSaleLogPoint.operateType().description();
|
||||
String operateType = afterSaleLogPoint.operateType().getContent();
|
||||
result.put(OPERATE_TYPE, operateType);
|
||||
// 日志内容
|
||||
String content = MapUtil.getStr(spelMap, afterSaleLogPoint.content());
|
||||
|
@@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.util;
|
||||
|
||||
import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.aop.AfterSaleLogAspect;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 操作日志工具类
|
||||
* 目前主要的作用,是提供给业务代码,记录操作明细和拓展字段
|
||||
@@ -19,4 +21,13 @@ public class AfterSaleLogUtils {
|
||||
AfterSaleLogAspect.setAfterStatus(status);
|
||||
}
|
||||
|
||||
public static void setAfterSaleInfo(Long id, Integer beforeStatus, Integer afterStatus) {
|
||||
setAfterSaleInfo(id, beforeStatus, afterStatus, null);
|
||||
}
|
||||
|
||||
public static void setAfterSaleInfo(Long id, Integer beforeStatus, Integer afterStatus,
|
||||
Map<String, Object> exts) {
|
||||
// TODO 待实现
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -28,6 +28,18 @@ public class TradeOrderProperties {
|
||||
* 支付超时时间
|
||||
*/
|
||||
@NotNull(message = "支付超时时间不能为空")
|
||||
private Duration expireTime;
|
||||
private Duration payExpireTime;
|
||||
|
||||
/**
|
||||
* 收货超时时间
|
||||
*/
|
||||
@NotNull(message = "收货超时时间不能为空")
|
||||
private Duration receiveExpireTime;
|
||||
|
||||
/**
|
||||
* 评论超时时间
|
||||
*/
|
||||
@NotNull(message = "评论超时时间不能为空")
|
||||
private Duration commentExpireTime;
|
||||
|
||||
}
|
||||
|
@@ -2,7 +2,10 @@ package cn.iocoder.yudao.module.trade.framework.order.core.annotations;
|
||||
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderOperateTypeEnum;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
|
@@ -31,6 +31,16 @@ import static java.util.Collections.emptyMap;
|
||||
@Slf4j
|
||||
public class TradeOrderLogAspect {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*
|
||||
* 目前的使用场景:支付回调时,需要强制设置下用户编号
|
||||
*/
|
||||
private static final ThreadLocal<Long> USER_ID = new ThreadLocal<>();
|
||||
/**
|
||||
* 用户类型
|
||||
*/
|
||||
private static final ThreadLocal<Integer> USER_TYPE = new ThreadLocal<>();
|
||||
/**
|
||||
* 订单编号
|
||||
*/
|
||||
@@ -112,4 +122,9 @@ public class TradeOrderLogAspect {
|
||||
EXTS.set(exts);
|
||||
}
|
||||
|
||||
public static void setUserInfo(Long userId, Integer userType) {
|
||||
USER_ID.set(userId);
|
||||
USER_TYPE.set(userType);
|
||||
}
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user