Parcourir la source

Merge branch 'feature/mall_product' of https://gitee.com/zhijiantianya/ruoyi-vue-pro

YunaiV il y a 1 an
Parent
commit
d982a95fdd
100 fichiers modifiés avec 1089 ajouts et 527 suppressions
  1. 3 0
      sql/mysql/optional/mall_trade_log.sql
  2. 5 5
      sql/mysql/pay_wallet.sql
  3. 10 0
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientFactory.java
  4. 31 0
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/NonePayClientConfig.java
  5. 38 24
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java
  6. 63 0
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/delegate/DelegatePayClient.java
  7. 4 1
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java
  8. 2 2
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayClientTest.java
  9. 2 2
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClientTest.java
  10. 32 18
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClientTest.java
  11. 27 12
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClientTest.java
  12. 1 0
      yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/JobLogController.java
  13. 8 0
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java
  14. 3 2
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
  15. 3 2
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java
  16. 5 5
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/AppBargainActivityController.java
  17. 4 4
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/AppBargainRecordController.java
  18. 2 2
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java
  19. 3 3
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationRecordController.java
  20. 4 4
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java
  21. 2 2
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillConfigController.java
  22. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillconfig/SeckillConfigMapper.java
  23. 1 0
      yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
  24. 30 6
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java
  25. 51 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDetailRespVO.java
  26. 3 2
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryPickUpStoreController.java
  27. 2 1
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/pickup/DeliveryPickUpStoreSimpleRespVO.java
  28. 4 8
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java
  29. 4 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppTradeAfterSaleController.java
  30. 0 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/AppCartController.http
  31. 19 22
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/AppCartController.java
  32. 1 5
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartAddReqVO.java
  33. 1 1
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartDetailRespVO.java
  34. 4 1
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartListRespVO.java
  35. 1 1
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartResetReqVO.java
  36. 2 2
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartUpdateCountReqVO.java
  37. 4 4
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartUpdateSelectedReqVO.java
  38. 1 6
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
  39. 23 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java
  40. 10 9
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/cart/TradeCartConvert.java
  41. 7 3
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryPickUpStoreConvert.java
  42. 11 38
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
  43. 6 33
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/cart/CartDO.java
  44. 5 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java
  45. 2 2
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java
  46. 62 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/cart/CartMapper.java
  47. 0 80
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/cart/TradeCartMapper.java
  48. 38 3
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java
  49. 8 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/dto/TradeAfterSaleLogCreateReqDTO.java
  50. 59 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/dto/TradeAfterSaleLogRespDTO.java
  51. 11 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/service/AfterSaleLogService.java
  52. 22 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/util/AfterSaleLogUtils.java
  53. 8 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleService.java
  54. 20 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java
  55. 16 20
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/CartService.java
  56. 40 50
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/CartServiceImpl.java
  57. 9 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressService.java
  58. 14 3
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressServiceImpl.java
  59. 25 29
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
  60. 2 2
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelController.java
  61. 2 2
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelRecordController.java
  62. 1 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordBaseVO.java
  63. 1 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordPageReqVO.java
  64. 1 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordRespVO.java
  65. 7 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java
  66. 43 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberExperienceRecordController.java
  67. 36 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberLevelController.java
  68. 24 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/experience/AppMemberExperienceRecordRespVO.java
  69. 28 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/level/AppMemberLevelRespVO.java
  70. 2 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/AppMemberPointRecordController.java
  71. 4 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInRecordController.java
  72. 2 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java
  73. 7 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java
  74. 24 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java
  75. 4 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberExperienceRecordConvert.java
  76. 4 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelConvert.java
  77. 1 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelRecordConvert.java
  78. 4 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java
  79. 7 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberExperienceRecordMapper.java
  80. 1 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelMapper.java
  81. 1 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelRecordMapper.java
  82. 10 10
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordService.java
  83. 5 4
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordServiceImpl.java
  84. 1 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordService.java
  85. 1 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordServiceImpl.java
  86. 1 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java
  87. 3 0
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java
  88. 3 1
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderCreateReqDTO.java
  89. 5 1
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
  90. 9 5
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/PayWalletBizTypeEnum.java
  91. 0 35
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/WalletTransactionQueryTypeEnum.java
  92. 6 3
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletController.java
  93. 16 6
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletTransactionController.java
  94. 0 16
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/AppPayWalletTransactionPageReqVO.java
  95. 23 0
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/transaction/AppPayWalletTransactionPageReqVO.java
  96. 13 2
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/transaction/AppPayWalletTransactionRespVO.java
  97. 3 5
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/wallet/AppPayWalletRespVO.java
  98. 1 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletConvert.java
  99. 1 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletTransactionConvert.java
  100. 5 6
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletDO.java

+ 3 - 0
sql/mysql/optional/mall_trade_log.sql

@@ -0,0 +1,3 @@
+ALTER TABLE `ruoyi-vue-pro`.`trade_after_sale_log`
+    ADD COLUMN `before_status` int NOT NULL COMMENT '售前状态' AFTER `id`,
+    ADD COLUMN `after_status` int NOT NULL COMMENT '售后状态' AFTER `before_status`;

+ 5 - 5
sql/mysql/pay_wallet.sql

@@ -5,11 +5,11 @@ DROP TABLE IF EXISTS `pay_wallet`;
 CREATE TABLE `pay_wallet`
 (
     `id`             bigint   NOT NULL AUTO_INCREMENT COMMENT '编号',
-    `user_id`        bigint   NOT NULL COMMENT '用户 id',
+    `user_id`        bigint   NOT NULL COMMENT '用户编号',
     `user_type`      tinyint  NOT NULL DEFAULT 0 COMMENT '用户类型',
-    `balance`        int      NOT NULL DEFAULT 0 COMMENT '余额, 单位分',
-    `total_expense`  bigint      NOT NULL DEFAULT 0 COMMENT '累计支出, 单位分',
-    `total_recharge` bigint      NOT NULL DEFAULT 0 COMMENT '累计充值, 单位分',
+    `balance`        int      NOT NULL DEFAULT 0 COMMENT '余额单位分',
+    `total_expense`  bigint      NOT NULL DEFAULT 0 COMMENT '累计支出单位分',
+    `total_recharge` bigint      NOT NULL DEFAULT 0 COMMENT '累计充值单位分',
     `creator`        varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
     `create_time`    datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
     `updater`        varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
@@ -41,4 +41,4 @@ CREATE TABLE `pay_wallet_transaction`
     `deleted`          bit(1)      NOT NULL DEFAULT b'0' COMMENT '是否删除',
     `tenant_id`        bigint      NOT NULL DEFAULT 0 COMMENT '租户编号',
     PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB COMMENT='支付钱包余额明细表';
+) ENGINE=InnoDB COMMENT='支付钱包余额明细表';

+ 10 - 0
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientFactory.java

@@ -1,5 +1,7 @@
 package cn.iocoder.yudao.framework.pay.core.client;
 
+import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
+
 /**
  * 支付客户端的工厂接口
  *
@@ -25,4 +27,12 @@ public interface PayClientFactory {
     <Config extends PayClientConfig> void createOrUpdatePayClient(Long channelId, String channelCode,
                                                                   Config config);
 
+    /**
+     * 注册支付客户端 Class,用于模块中实现的 PayClient
+     *
+     * @param channel 支付渠道的编码的枚举
+     * @param payClientClass 支付客户端 class
+     */
+    void registerPayClientClass(PayChannelEnum channel, Class<?> payClientClass);
+
 }

+ 31 - 0
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/NonePayClientConfig.java

@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.framework.pay.core.client.impl;
+
+import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
+import lombok.Data;
+
+import javax.validation.Validator;
+
+/**
+ * 无需任何配置 PayClientConfig 实现类
+ *
+ * @author jason
+ */
+@Data
+public class NonePayClientConfig implements PayClientConfig {
+
+    /**
+     * 配置名称
+     * <p>
+     * 如果不加任何属性,JsonUtils.parseObject2 解析会报错,所以暂时加个名称
+     */
+    private String name;
+
+    public NonePayClientConfig(){
+        this.name = "none-config";
+    }
+
+    @Override
+    public void validate(Validator validator) {
+        // 无任何配置不需要校验
+    }
+}

+ 38 - 24
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java

@@ -1,19 +1,22 @@
 package cn.iocoder.yudao.framework.pay.core.client.impl;
 
 import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.ReflectUtil;
 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
 import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
 import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.*;
 import cn.iocoder.yudao.framework.pay.core.client.impl.mock.MockPayClient;
-import cn.iocoder.yudao.framework.pay.core.client.impl.mock.MockPayClientConfig;
 import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.*;
 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
 import lombok.extern.slf4j.Slf4j;
 
+import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import static cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum.*;
+
 /**
  * 支付客户端的工厂实现类
  *
@@ -24,10 +27,38 @@ public class PayClientFactoryImpl implements PayClientFactory {
 
     /**
      * 支付客户端 Map
+     *
      * key:渠道编号
      */
     private final ConcurrentMap<Long, AbstractPayClient<?>> clients = new ConcurrentHashMap<>();
 
+    /**
+     * 支付客户端 Class Map
+     */
+    private final Map<PayChannelEnum, Class<?>> clientClass = new ConcurrentHashMap<>();
+
+    public PayClientFactoryImpl() {
+        // 微信支付客户端
+        clientClass.put(WX_PUB, WxPubPayClient.class);
+        clientClass.put(WX_LITE, WxLitePayClient.class);
+        clientClass.put(WX_APP, WxAppPayClient.class);
+        clientClass.put(WX_BAR, WxBarPayClient.class);
+        clientClass.put(WX_NATIVE, WxNativePayClient.class);
+        // 支付包支付客户端
+        clientClass.put(ALIPAY_WAP, AlipayWapPayClient.class);
+        clientClass.put(ALIPAY_QR, AlipayQrPayClient.class);
+        clientClass.put(ALIPAY_APP, AlipayAppPayClient.class);
+        clientClass.put(ALIPAY_PC, AlipayPcPayClient.class);
+        clientClass.put(ALIPAY_BAR, AlipayBarPayClient.class);
+        // Mock 支付客户端
+        clientClass.put(MOCK, MockPayClient.class);
+    }
+
+    @Override
+    public void registerPayClientClass(PayChannelEnum channel, Class<?> payClientClass) {
+        clientClass.put(channel, payClientClass);
+    }
+
     @Override
     public PayClient getPayClient(Long channelId) {
         AbstractPayClient<?> client = clients.get(channelId);
@@ -52,30 +83,13 @@ public class PayClientFactoryImpl implements PayClientFactory {
     }
 
     @SuppressWarnings("unchecked")
-    private <Config extends PayClientConfig> AbstractPayClient<Config> createPayClient(
-            Long channelId, String channelCode, Config config) {
+    private <Config extends PayClientConfig> AbstractPayClient<Config> createPayClient(Long channelId, String channelCode,
+                                                                                       Config config) {
         PayChannelEnum channelEnum = PayChannelEnum.getByCode(channelCode);
-        Assert.notNull(channelEnum, String.format("支付渠道(%s) 为空", channelEnum));
-        // 创建客户端
-        switch (channelEnum) {
-            // 微信支付
-            case WX_PUB: return (AbstractPayClient<Config>) new WxPubPayClient(channelId, (WxPayClientConfig) config);
-            case WX_LITE: return (AbstractPayClient<Config>) new WxLitePayClient(channelId, (WxPayClientConfig) config);
-            case WX_APP: return (AbstractPayClient<Config>) new WxAppPayClient(channelId, (WxPayClientConfig) config);
-            case WX_BAR: return (AbstractPayClient<Config>) new WxBarPayClient(channelId, (WxPayClientConfig) config);
-            case WX_NATIVE: return (AbstractPayClient<Config>) new WxNativePayClient(channelId, (WxPayClientConfig) config);
-            // 支付宝支付
-            case ALIPAY_WAP: return (AbstractPayClient<Config>) new AlipayWapPayClient(channelId, (AlipayPayClientConfig) config);
-            case ALIPAY_QR: return (AbstractPayClient<Config>) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config);
-            case ALIPAY_APP: return (AbstractPayClient<Config>) new AlipayAppPayClient(channelId, (AlipayPayClientConfig) config);
-            case ALIPAY_PC: return (AbstractPayClient<Config>) new AlipayPcPayClient(channelId, (AlipayPayClientConfig) config);
-            case ALIPAY_BAR: return (AbstractPayClient<Config>) new AlipayBarPayClient(channelId, (AlipayPayClientConfig) config);
-            // 其它支付
-            case MOCK: return (AbstractPayClient<Config>) new MockPayClient(channelId, (MockPayClientConfig) config);
-        }
-        // 创建失败,错误日志 + 抛出异常
-        log.error("[createPayClient][配置({}) 找不到合适的客户端实现]", config);
-        throw new IllegalArgumentException(String.format("配置(%s) 找不到合适的客户端实现", config));
+        Assert.notNull(channelEnum, String.format("支付渠道(%s) 为空", channelCode));
+        Class<?> payClientClass = clientClass.get(channelEnum);
+        Assert.notNull(payClientClass, String.format("支付渠道(%s) Class 为空", channelCode));
+        return (AbstractPayClient<Config>) ReflectUtil.newInstance(payClientClass, channelId, config);
     }
 
 }

+ 63 - 0
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/delegate/DelegatePayClient.java

@@ -0,0 +1,63 @@
+package cn.iocoder.yudao.framework.pay.core.client.impl.delegate;
+
+import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
+import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
+import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
+import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
+import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
+import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
+
+import java.util.Map;
+
+// TODO @jason:其它模块,主要是无法 pay client 初始化存在问题,所以我感觉,是不是可以搞个 PayClientInitializer 接口。这样,PayClientFactory 去 get 这个支付模式对应的 PayClientInitializer,通过它来创建。具体注入的地方,可以在 PayChannel init 方法那;
+/**
+ * 代理支付 Client 的抽象类。
+ *
+ * 用于支付 Client 由其它模块实现,例如钱包支付
+ *
+ * @author jason
+ */
+public abstract class DelegatePayClient<Config extends PayClientConfig> extends AbstractPayClient<PayClientConfig> {
+
+    private final DelegatePayClient<Config> delegate;
+
+    public DelegatePayClient(Long channelId, String channelCode, PayClientConfig config) {
+        super(channelId, channelCode, config);
+        delegate = this;
+    }
+
+    @Override
+    protected void doInit() {
+        delegate.doInit();
+    }
+
+    @Override
+    protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO)  {
+        return delegate.doUnifiedOrder(reqDTO);
+    }
+
+    @Override
+    protected PayOrderRespDTO doGetOrder(String outTradeNo)  {
+        return delegate.doGetOrder(outTradeNo);
+    }
+
+    @Override
+    protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO)  {
+        return delegate.doUnifiedRefund(reqDTO);
+    }
+
+    @Override
+    protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) {
+        return delegate.doGetRefund(outTradeNo, outRefundNo);
+    }
+
+    @Override
+    protected PayRefundRespDTO doParseRefundNotify(Map<String,String> params, String body)  {
+        return delegate.doParseRefundNotify(params, body);
+    }
+
+    @Override
+    protected PayOrderRespDTO doParseOrderNotify(Map<String,String> params, String body)  {
+        return delegate.doParseOrderNotify(params, body);
+    }
+}

+ 4 - 1
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.framework.pay.core.enums.channel;
 
 import cn.hutool.core.util.ArrayUtil;
+import cn.iocoder.yudao.framework.pay.core.client.impl.NonePayClientConfig;
 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
 import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
 import cn.iocoder.yudao.framework.pay.core.client.impl.mock.MockPayClientConfig;
@@ -29,7 +30,9 @@ public enum PayChannelEnum {
     ALIPAY_QR("alipay_qr", "支付宝扫码支付", AlipayPayClientConfig.class),
     ALIPAY_BAR("alipay_bar", "支付宝条码支付", AlipayPayClientConfig.class),
 
-    MOCK("mock", "模拟支付", MockPayClientConfig.class);
+    MOCK("mock", "模拟支付", MockPayClientConfig.class),
+
+    WALLET("wallet", "钱包支付", NonePayClientConfig.class);
 
     /**
      * 编码

+ 2 - 2
yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayClientTest.java

@@ -168,7 +168,7 @@ public abstract class AbstractAlipayClientTest extends BaseMockitoUnitTest {
     @Test
     @DisplayName("支付宝 Client 统一退款:抛出业务异常")
     public void testUnifiedRefund_throwServiceException() throws AlipayApiException {
-        // mock
+        // mock 方法
         when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradeRefundRequest>) request -> true)))
                 .thenThrow(ServiceExceptionUtil.exception(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR));
         // 准备请求参数
@@ -182,7 +182,7 @@ public abstract class AbstractAlipayClientTest extends BaseMockitoUnitTest {
     @Test
     @DisplayName("支付宝 Client 统一退款:抛出系统异常")
     public void testUnifiedRefund_throwPayException() throws AlipayApiException {
-        // mock
+        // mock 方法
         when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradeRefundRequest>) request -> true)))
                 .thenThrow(new RuntimeException("系统异常"));
         // 准备请求参数

+ 2 - 2
yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPcPayClientTest.java

@@ -70,7 +70,7 @@ public class AlipayPcPayClientTest extends AbstractAlipayClientTest {
     @Test
     @DisplayName("支付宝 PC 网站支付:Form Display Mode 下单成功")
     public void testUnifiedOrder_formSuccess() throws AlipayApiException {
-        // mock
+        // mock 方法
         String notifyUrl = randomURL();
         AlipayTradePagePayResponse response = randomPojo(AlipayTradePagePayResponse.class, o -> o.setSubCode(""));
         when(defaultAlipayClient.pageExecute(argThat((ArgumentMatcher<AlipayTradePagePayRequest>) request -> true),
@@ -99,7 +99,7 @@ public class AlipayPcPayClientTest extends AbstractAlipayClientTest {
     @Test
     @DisplayName("支付宝 PC 网站支付:渠道返回失败")
     public void testUnifiedOrder_channelFailed() throws AlipayApiException {
-        // mock
+        // mock 方法
         String subCode = randomString();
         String subMsg = randomString();
         AlipayTradePagePayResponse response = randomPojo(AlipayTradePagePayResponse.class, o -> {

+ 32 - 18
yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClientTest.java

@@ -39,9 +39,9 @@ public class AlipayQrPayClientTest extends AbstractAlipayClientTest {
     }
 
     @Test
-    @DisplayName("支付宝扫描支付下单成功")
-    public void test_unified_order_success() throws AlipayApiException {
-        // 准备返回对象
+    @DisplayName("支付宝扫描支付下单成功")
+    public void testUnifiedOrder_success() throws AlipayApiException {
+        // mock 方法
         String notifyUrl = randomURL();
         String qrCode = randomString();
         Integer price = randomInteger();
@@ -49,7 +49,6 @@ public class AlipayQrPayClientTest extends AbstractAlipayClientTest {
             o.setQrCode(qrCode);
             o.setSubCode("");
         });
-        // mock
         when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradePrecreateRequest>) request -> {
             assertEquals(notifyUrl, request.getNotifyUrl());
             return true;
@@ -58,18 +57,25 @@ public class AlipayQrPayClientTest extends AbstractAlipayClientTest {
         String outTradeNo = randomString();
         PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo, price);
 
+        // 调用
         PayOrderRespDTO resp = client.unifiedOrder(reqDTO);
         // 断言
         assertEquals(WAITING.getStatus(), resp.getStatus());
-        assertEquals(PayOrderDisplayModeEnum.QR_CODE.getMode(), resp.getDisplayMode());
         assertEquals(outTradeNo, resp.getOutTradeNo());
-        assertEquals(qrCode, resp.getDisplayContent());
+        assertNull(resp.getChannelOrderNo());
+        assertNull(resp.getChannelUserId());
+        assertNull(resp.getSuccessTime());
+        assertEquals(PayOrderDisplayModeEnum.QR_CODE.getMode(), resp.getDisplayMode());
+        assertEquals(response.getQrCode(), resp.getDisplayContent());
         assertSame(response, resp.getRawData());
+        assertNull(resp.getChannelErrorCode());
+        assertNull(resp.getChannelErrorMsg());
     }
 
     @Test
-    @DisplayName("支付宝扫描支付,渠道返回失败")
-    public void test_unified_order_channel_failed() throws AlipayApiException {
+    @DisplayName("支付宝扫描支付:渠道返回失败")
+    public void testUnifiedOrder_channelFailed() throws AlipayApiException {
+        // mock 方法
         String notifyUrl = randomURL();
         String subCode = randomString();
         String subMsg = randomString();
@@ -87,47 +93,55 @@ public class AlipayQrPayClientTest extends AbstractAlipayClientTest {
         String outTradeNo = randomString();
         PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo, price);
 
+        // 调用
         PayOrderRespDTO resp = client.unifiedOrder(reqDTO);
         // 断言
         assertEquals(CLOSED.getStatus(), resp.getStatus());
+        assertEquals(outTradeNo, resp.getOutTradeNo());
+        assertNull(resp.getChannelOrderNo());
+        assertNull(resp.getChannelUserId());
+        assertNull(resp.getSuccessTime());
+        assertNull(resp.getDisplayMode());
+        assertNull(resp.getDisplayContent());
+        assertSame(response, resp.getRawData());
         assertEquals(subCode, resp.getChannelErrorCode());
         assertEquals(subMsg, resp.getChannelErrorMsg());
-        assertSame(response, resp.getRawData());
     }
 
     @Test
     @DisplayName("支付宝扫描支付, 抛出系统异常")
-    public void test_unified_order_throw_pay_exception() throws AlipayApiException {
-        // 准备请求参数
+    public void testUnifiedOrder_throwPayException() throws AlipayApiException {
+        // mock 方法
         String outTradeNo = randomString();
         String notifyUrl = randomURL();
         Integer price = randomInteger();
-        // mock
         when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradePrecreateRequest>) request -> {
             assertEquals(notifyUrl, request.getNotifyUrl());
             return true;
         }))).thenThrow(new RuntimeException("系统异常"));
         // 准备请求参数
         PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo,price);
-        // 断言
+
+        // 调用,并断言
         assertThrows(PayException.class, () -> client.unifiedOrder(reqDTO));
     }
 
     @Test
-    @DisplayName("支付宝 Client 统一下单,抛出业务异常")
-    public void test_unified_order_throw_service_exception() throws AlipayApiException {
-        // 准备请求参数
+    @DisplayName("支付宝 Client 统一下单抛出业务异常")
+    public void testUnifiedOrder_throwServiceException() throws AlipayApiException {
+        // mock 方法
         String outTradeNo = randomString();
         String notifyUrl = randomURL();
         Integer price = randomInteger();
-        // mock
         when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradePrecreateRequest>) request -> {
             assertEquals(notifyUrl, request.getNotifyUrl());
             return true;
         }))).thenThrow(ServiceExceptionUtil.exception(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR));
         // 准备请求参数
         PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo, price);
-        // 断言
+
+        // 调用,并断言
         assertThrows(ServiceException.class, () -> client.unifiedOrder(reqDTO));
     }
+
 }

+ 27 - 12
yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClientTest.java

@@ -42,9 +42,9 @@ public class AlipayWapPayClientTest extends AbstractAlipayClientTest {
     }
 
     @Test
-    @DisplayName("支付宝 H5 支付下单成功")
-    public void test_unified_order_success() throws AlipayApiException {
-        // 准备响应对象
+    @DisplayName("支付宝 H5 支付下单成功")
+    public void testUnifiedOrder_success() throws AlipayApiException {
+        // mock 方法
         String h5Body = randomString();
         Integer price = randomInteger();
         AlipayTradeWapPayResponse response = randomPojo(AlipayTradeWapPayResponse.class, o -> {
@@ -52,7 +52,6 @@ public class AlipayWapPayClientTest extends AbstractAlipayClientTest {
             o.setBody(h5Body);
         });
         String notifyUrl = randomURL();
-        // mock
         when(defaultAlipayClient.pageExecute(argThat((ArgumentMatcher<AlipayTradeWapPayRequest>) request -> {
             assertInstanceOf(AlipayTradeWapPayModel.class, request.getBizModel());
             AlipayTradeWapPayModel bizModel = (AlipayTradeWapPayModel) request.getBizModel();
@@ -60,37 +59,53 @@ public class AlipayWapPayClientTest extends AbstractAlipayClientTest {
             assertEquals(notifyUrl, request.getNotifyUrl());
             return true;
         }), eq(Method.GET.name()))).thenReturn(response);
-
+        // 准备请求参数
         String outTradeNo = randomString();
         PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(notifyUrl, outTradeNo, price);
+
+        // 调用
         PayOrderRespDTO resp = client.unifiedOrder(reqDTO);
+        // 断言
         assertEquals(WAITING.getStatus(), resp.getStatus());
-        assertEquals(PayOrderDisplayModeEnum.URL.getMode(), resp.getDisplayMode());
         assertEquals(outTradeNo, resp.getOutTradeNo());
-        assertEquals(h5Body, resp.getDisplayContent());
+        assertNull(resp.getChannelOrderNo());
+        assertNull(resp.getChannelUserId());
+        assertNull(resp.getSuccessTime());
+        assertEquals(PayOrderDisplayModeEnum.URL.getMode(), resp.getDisplayMode());
+        assertEquals(response.getBody(), resp.getDisplayContent());
         assertSame(response, resp.getRawData());
+        assertNull(resp.getChannelErrorCode());
+        assertNull(resp.getChannelErrorMsg());
     }
 
     @Test
-    @DisplayName("支付宝 H5 支付,渠道返回失败")
+    @DisplayName("支付宝 H5 支付渠道返回失败")
     public void test_unified_order_channel_failed() throws AlipayApiException {
-        // 准备响应对象
+        // mock 方法
         String subCode = randomString();
         String subMsg = randomString();
         AlipayTradeWapPayResponse response = randomPojo(AlipayTradeWapPayResponse.class, o -> {
             o.setSubCode(subCode);
             o.setSubMsg(subMsg);
         });
-        // mock
         when(defaultAlipayClient.pageExecute(argThat((ArgumentMatcher<AlipayTradeWapPayRequest>) request -> true),
                 eq(Method.GET.name()))).thenReturn(response);
-        PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), randomString(), randomInteger());
+        String outTradeNo = randomString();
+        PayOrderUnifiedReqDTO reqDTO = buildOrderUnifiedReqDTO(randomURL(), outTradeNo, randomInteger());
 
+        // 调用
         PayOrderRespDTO resp = client.unifiedOrder(reqDTO);
         // 断言
         assertEquals(CLOSED.getStatus(), resp.getStatus());
+        assertEquals(outTradeNo, resp.getOutTradeNo());
+        assertNull(resp.getChannelOrderNo());
+        assertNull(resp.getChannelUserId());
+        assertNull(resp.getSuccessTime());
+        assertNull(resp.getDisplayMode());
+        assertNull(resp.getDisplayContent());
+        assertSame(response, resp.getRawData());
         assertEquals(subCode, resp.getChannelErrorCode());
         assertEquals(subMsg, resp.getChannelErrorMsg());
-        assertSame(response, resp.getRawData());
     }
+
 }

+ 1 - 0
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/JobLogController.java

@@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
+import cn.iocoder.yudao.framework.operatelog.core.util.OperateLogUtils;
 import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogExcelVO;
 import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogExportReqVO;
 import cn.iocoder.yudao.module.infra.controller.admin.job.vo.log.JobLogPageReqVO;

+ 8 - 0
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java

@@ -42,6 +42,14 @@ public class AppFavoriteController {
         return success(productFavoriteService.createFavorite(getLoginUserId(), reqVO.getSpuId()));
     }
 
+    @PostMapping(value = "/create-list")
+    @Operation(summary = "添加多个商品收藏")
+    @PreAuthenticated
+    public CommonResult<Boolean> createFavoriteList(@RequestBody @Valid AppFavoriteBatchReqVO reqVO) {
+        // todo @jason:待实现;如果有已经收藏的,不用报错,忽略即可;
+        return success(true);
+    }
+
     @DeleteMapping(value = "/delete")
     @Operation(summary = "取消单个商品收藏")
     @PreAuthenticated

+ 3 - 2
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java

@@ -110,8 +110,9 @@ public class ProductSpuServiceImpl implements ProductSpuService {
         spu.setMarketPrice(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
         // sku 单价最低的商品的成本价格
         spu.setCostPrice(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getCostPrice));
-        // sku 单价最低的商品的条形码
-        spu.setBarCode(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getBarCode));
+        // sku 单价最低的商品的条形码 TODO 芋艿:条形码字段,是不是可以删除
+        spu.setBarCode("");
+//        spu.setBarCode(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getBarCode));
         // skus 库存总数
         spu.setStock(getSumValue(skus, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
         // 若是 spu 已有状态则不处理

+ 3 - 2
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java

@@ -81,12 +81,13 @@ public class SeckillConfigController {
     @GetMapping("/list-all-simple")
     @Operation(summary = "获得所有开启状态的秒杀时段精简列表", description = "主要用于前端的下拉选项")
     public CommonResult<List<SeckillConfigSimpleRespVO>> getListAllSimple() {
-        List<SeckillConfigDO> list = seckillConfigService.getSeckillConfigListByStatus(CommonStatusEnum.ENABLE.getStatus());
+        List<SeckillConfigDO> list = seckillConfigService.getSeckillConfigListByStatus(
+                CommonStatusEnum.ENABLE.getStatus());
         return success(SeckillConfigConvert.INSTANCE.convertList1(list));
     }
 
     @GetMapping("/page")
-    @Operation(summary = "获得秒杀活动分页")
+    @Operation(summary = "获得秒杀时间段分页")
     @PreAuthorize("@ss.hasPermission('promotion:seckill-config:query')")
     public CommonResult<PageResult<SeckillConfigRespVO>> getSeckillActivityPage(@Valid SeckillConfigPageReqVO pageVO) {
         PageResult<SeckillConfigDO> pageResult = seckillConfigService.getSeckillConfigPage(pageVO);

+ 5 - 5
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/AppBargainActivityController.java

@@ -35,7 +35,7 @@ public class AppBargainActivityController {
         activity1.setId(1L);
         activity1.setName("618 大砍价");
         activity1.setSpuId(2048L);
-        activity1.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
+        activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
         activity1.setMarketPrice(50);
         activity1.setBargainPrice(100);
         activity1.setStartTime(LocalDateTimeUtils.addTime(Duration.ofDays(-2)));
@@ -47,7 +47,7 @@ public class AppBargainActivityController {
         activity2.setId(2L);
         activity2.setName("双十一砍价");
         activity2.setSpuId(4096L);
-        activity2.setPicUrl("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132");
+        activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg");
         activity2.setMarketPrice(100);
         activity2.setBargainPrice(200);
         activity2.setStartTime(LocalDateTimeUtils.addTime(Duration.ofDays(-2)));
@@ -69,7 +69,7 @@ public class AppBargainActivityController {
         activity1.setId(1L);
         activity1.setName("618 大砍价");
         activity1.setSpuId(2048L);
-        activity1.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
+        activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
         activity1.setMarketPrice(50);
         activity1.setBargainPrice(100);
         activityList.add(activity1);
@@ -78,7 +78,7 @@ public class AppBargainActivityController {
         activity2.setId(2L);
         activity2.setName("双十一砍价");
         activity2.setSpuId(4096L);
-        activity2.setPicUrl("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132");
+        activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg");
         activity2.setMarketPrice(100);
         activity2.setBargainPrice(200);
         activityList.add(activity2);
@@ -94,7 +94,7 @@ public class AppBargainActivityController {
         activity.setId(2L);
         activity.setName("618 大砍价");
         activity.setSpuId(2048L);
-        activity.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
+        activity.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
         activity.setMarketPrice(50);
         activity.setBargainPrice(100);
         activity.setStock(10);

+ 4 - 4
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/AppBargainRecordController.java

@@ -81,7 +81,7 @@ public class AppBargainRecordController {
         record1.setPrice(200);
         record1.setPayPrice(180);
         record1.setStatus(1);
-        record1.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
+        record1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
         record1.setExpireTime(LocalDateTimeUtils.addTime(Duration.ofDays(2)));
         page.getList().add(record1);
 
@@ -96,7 +96,7 @@ public class AppBargainRecordController {
         record2.setPrice(200);
         record2.setPayPrice(280);
         record2.setStatus(2);
-        record2.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
+        record2.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
         record2.setExpireTime(LocalDateTimeUtils.addTime(Duration.ofDays(2)));
         page.getList().add(record2);
 
@@ -111,7 +111,7 @@ public class AppBargainRecordController {
         record3.setPrice(200);
         record3.setPayPrice(380);
         record3.setStatus(2);
-        record3.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
+        record3.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
         record3.setExpireTime(LocalDateTimeUtils.addTime(Duration.ofDays(2)));
         record3.setOrderId(100L);
         page.getList().add(record3);
@@ -127,7 +127,7 @@ public class AppBargainRecordController {
         record4.setPrice(200);
         record4.setPayPrice(380);
         record4.setStatus(3);
-        record4.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
+        record4.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
         record4.setExpireTime(LocalDateTimeUtils.addTime(Duration.ofDays(2)));
         record4.setOrderId(100L);
         page.getList().add(record4);

+ 2 - 2
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java

@@ -38,7 +38,7 @@ public class AppCombinationActivityController {
         activity1.setName("618 大拼团");
         activity1.setUserSize(3);
         activity1.setSpuId(2048L);
-        activity1.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
+        activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
         activity1.setMarketPrice(50);
         activity1.setCombinationPrice(100);
         activityList.add(activity1);
@@ -48,7 +48,7 @@ public class AppCombinationActivityController {
         activity2.setName("双十一拼团");
         activity2.setUserSize(5);
         activity2.setSpuId(4096L);
-        activity2.setPicUrl("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132");
+        activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg");
         activity2.setMarketPrice(100);
         activity2.setCombinationPrice(200);
         activityList.add(activity2);

+ 3 - 3
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationRecordController.java

@@ -41,7 +41,7 @@ public class AppCombinationRecordController {
         summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/ouwtwJycbic2JrCoZjETict0klxd1uRuicRneKk00ewMcCClxVcVHQT91Sh9MJGtwibf1fOicD1WpwSP4icJM6eQq1AA/132");
         summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/RpUrhwens58qc99OcGs993xL4M5QPOe05ekqF9Eia440kRicAlicicIdQWicHBmy2bzLgHzHguWEzHHxnIgeictL7bLA/132");
         summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/S4tfqmxc8GZGsKc1K4mnhpvtG16gtMrLnTQfDibhr7jJich9LRI5RQKZDoqEjZM3azMib5nic7F4ZXKMEgYyLO08KA/132");
-        summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132");
+        summary.getAvatars().add("https://static.iocoder.cn/mall/132.jpeg");
         return success(summary);
     }
 
@@ -61,7 +61,7 @@ public class AppCombinationRecordController {
             record.setExpireTime(new Date());
             record.setUserSize(10);
             record.setUserCount(i);
-            record.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
+            record.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
             record.setActivityId(1L);
             record.setSpuName("活动:" + i);
             list.add(record);
@@ -84,7 +84,7 @@ public class AppCombinationRecordController {
         headRecord.setUserCount(3);
         headRecord.setStatus(1);
         headRecord.setActivityId(10L);
-        headRecord.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
+        headRecord.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
         headRecord.setCombinationPrice(100);
         detail.setHeadRecord(headRecord);
         // 团员

+ 4 - 4
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java

@@ -39,7 +39,7 @@ public class AppSeckillActivityController {
         activity1.setId(1L);
         activity1.setName("618 大秒杀");
         activity1.setSpuId(2048L);
-        activity1.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
+        activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
         activity1.setMarketPrice(50);
         activity1.setSeckillPrice(100);
         activityList.add(activity1);
@@ -48,7 +48,7 @@ public class AppSeckillActivityController {
         activity2.setId(2L);
         activity2.setName("双十一大秒杀");
         activity2.setSpuId(4096L);
-        activity2.setPicUrl("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132");
+        activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg");
         activity2.setMarketPrice(100);
         activity2.setSeckillPrice(200);
         activityList.add(activity2);
@@ -65,7 +65,7 @@ public class AppSeckillActivityController {
         activity1.setId(1L);
         activity1.setName("618 大秒杀");
         activity1.setSpuId(2048L);
-        activity1.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
+        activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
         activity1.setMarketPrice(50);
         activity1.setSeckillPrice(100);
         activity1.setUnitName("个");
@@ -77,7 +77,7 @@ public class AppSeckillActivityController {
         activity2.setId(2L);
         activity2.setName("双十一大秒杀");
         activity2.setSpuId(4096L);
-        activity2.setPicUrl("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132");
+        activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg");
         activity2.setMarketPrice(100);
         activity2.setSeckillPrice(200);
         activity2.setUnitName("套");

+ 2 - 2
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillConfigController.java

@@ -25,8 +25,8 @@ public class AppSeckillConfigController {
     public CommonResult<List<AppSeckillConfigRespVO>> getSeckillConfigList() {
         return success(Arrays.asList(
                 new AppSeckillConfigRespVO().setId(1L).setStartTime("00:00").setEndTime("09:59")
-                        .setSliderPicUrls(Arrays.asList("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg",
-                                "https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132")),
+                        .setSliderPicUrls(Arrays.asList("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg",
+                                "https://static.iocoder.cn/mall/132.jpeg")),
                 new AppSeckillConfigRespVO().setId(2L).setStartTime("10:00").setEndTime("12:59"),
                 new AppSeckillConfigRespVO().setId(2L).setStartTime("13:00").setEndTime("22:59"),
                 new AppSeckillConfigRespVO().setId(2L).setStartTime("23:00").setEndTime("23:59")

+ 1 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillconfig/SeckillConfigMapper.java

@@ -16,7 +16,7 @@ public interface SeckillConfigMapper extends BaseMapperX<SeckillConfigDO> {
         return selectPage(reqVO, new LambdaQueryWrapperX<SeckillConfigDO>()
                 .likeIfPresent(SeckillConfigDO::getName, reqVO.getName())
                 .eqIfPresent(SeckillConfigDO::getStatus, reqVO.getStatus())
-                .orderByDesc(SeckillConfigDO::getId));
+                .orderByAsc(SeckillConfigDO::getStartTime));
     }
 
     default List<SeckillConfigDO> selectListByStatus(Integer status) {

+ 1 - 0
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java

@@ -32,6 +32,7 @@ public interface ErrorCodeConstants {
     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, "交易订单发货失败,发货类型不是快递");
 
     // ==========  After Sale 模块 1011000100 ==========
     ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在");

+ 30 - 6
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java

@@ -7,13 +7,15 @@ import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
 import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
 import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO;
-import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO;
-import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO;
-import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRefuseReqVO;
-import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRespPageItemVO;
+import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.*;
 import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert;
 import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
+import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogRespDTO;
+import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service.AfterSaleLogService;
 import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService;
+import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -25,6 +27,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.annotation.Resource;
 import javax.annotation.security.PermitAll;
 import javax.validation.Valid;
+import java.util.List;
 import java.util.Map;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -41,7 +44,10 @@ public class TradeAfterSaleController {
 
     @Resource
     private TradeAfterSaleService afterSaleService;
-
+    @Resource
+    private TradeOrderQueryService tradeOrderQueryService;
+    @Resource
+    private AfterSaleLogService afterSaleLogService;
     @Resource
     private MemberUserApi memberUserApi;
 
@@ -61,6 +67,24 @@ public class TradeAfterSaleController {
         return success(TradeAfterSaleConvert.INSTANCE.convertPage(pageResult, memberUsers));
     }
 
+    @GetMapping("/get-detail")
+    @Operation(summary = "获得售后订单详情")
+    @Parameter(name = "id", description = "售后编号", required = true, example = "1")
+    @PreAuthorize("@ss.hasPermission('trade:after-sale:query')")
+    public CommonResult<TradeAfterSaleDetailRespVO> getOrderDetail(@RequestParam("id") Long id) {
+        // 查询订单
+        TradeAfterSaleDO afterSale = afterSaleService.getAfterSale(id);
+        // 查询订单
+        TradeOrderDO order = tradeOrderQueryService.getOrder(afterSale.getOrderId());
+        // 查询订单项
+        List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id);
+        // 拼接数据
+        MemberUserRespDTO user = memberUserApi.getUser(afterSale.getUserId());
+        // 获取售后日志
+        List<TradeAfterSaleLogRespDTO> logs = afterSaleLogService.getLog(afterSale.getId());
+        return success(TradeAfterSaleConvert.INSTANCE.convert(afterSale, order, orderItems, user, logs));
+    }
+
     @PutMapping("/agree")
     @Operation(summary = "同意售后")
     @Parameter(name = "id", description = "售后编号", required = true, example = "1")
@@ -88,7 +112,7 @@ public class TradeAfterSaleController {
     }
 
     @PutMapping("/refuse")
-    @Operation(summary = "确认收货")
+    @Operation(summary = "拒绝收货")
     @Parameter(name = "id", description = "售后编号", required = true, example = "1")
     @PreAuthorize("@ss.hasPermission('trade:after-sale:receive')")
     public CommonResult<Boolean> refuseAfterSale(TradeAfterSaleRefuseReqVO refuseReqVO) {

+ 51 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/TradeAfterSaleDetailRespVO.java

@@ -0,0 +1,51 @@
+package cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo;
+
+import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.TradeAfterSaleLogRespVO;
+import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
+import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
+import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderBaseVO;
+import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderItemBaseVO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - 售后订单的详情 Response VO")
+@Data
+public class TradeAfterSaleDetailRespVO extends TradeAfterSaleBaseVO {
+
+    @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    private Long id;
+
+    /**
+     * 订单项列表
+     */
+    private List<Item> items;
+
+    /**
+     * 订单基本信息
+     */
+    private TradeOrderBaseVO order;
+
+    /**
+     * 用户信息
+     */
+    private MemberUserRespVO user;
+
+    /**
+     * 售后日志
+     */
+    private List<TradeAfterSaleLogRespVO> afterSaleLog;
+
+    @Schema(description = "管理后台 - 交易订单的详情的订单项目")
+    @Data
+    public static class Item extends TradeOrderItemBaseVO {
+
+        /**
+         * 属性数组
+         */
+        private List<ProductPropertyValueDetailRespVO> properties;
+
+    }
+
+}

+ 3 - 2
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryPickUpStoreController.java

@@ -64,9 +64,10 @@ public class DeliveryPickUpStoreController {
     }
 
     @GetMapping("/list-all-simple")
-    @Operation(summary = "获取快递公司精简信息列表")
+    @Operation(summary = "获得自提门店精简信息列表")
     public CommonResult<List<DeliveryPickUpStoreSimpleRespVO>> getSimpleDeliveryPickUpStoreList() {
-        List<DeliveryPickUpStoreDO> list = deliveryPickUpStoreService.getDeliveryPickUpStoreListByStatus(CommonStatusEnum.ENABLE.getStatus());
+        List<DeliveryPickUpStoreDO> list = deliveryPickUpStoreService.getDeliveryPickUpStoreListByStatus(
+                CommonStatusEnum.ENABLE.getStatus());
         return success(DeliveryPickUpStoreConvert.INSTANCE.convertList1(list));
     }
 

+ 2 - 1
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/pickup/DeliveryPickUpStoreSimpleRespVO.java

@@ -23,7 +23,8 @@ public class DeliveryPickUpStoreSimpleRespVO {
     @Schema(description = "区域编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18733")
     private Integer areaId;
 
-    // TODO @puhui999:要把 areaName 也返回哈
+    @Schema(description = "区域名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "xx市")
+    private String areaName;
 
     @Schema(description = "门店详细地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "复旦大学路 188 号")
     private String detailAddress;

+ 4 - 8
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java

@@ -85,8 +85,7 @@ public class TradeOrderController {
                 tradeOrderQueryService.getExpressTrackList(id, getLoginUserId())));
     }
 
-    // TODO @puhui999:put 请求哈
-    @PostMapping("/delivery")
+    @PutMapping("/delivery")
     @Operation(summary = "订单发货")
     @PreAuthorize("@ss.hasPermission('trade:order:update')")
     public CommonResult<Boolean> deliveryOrder(@RequestBody TradeOrderDeliveryReqVO deliveryReqVO) {
@@ -94,8 +93,7 @@ public class TradeOrderController {
         return success(true);
     }
 
-    // TODO @puhui999:put 请求哈,update-remark;
-    @PostMapping("/remark")
+    @PutMapping("/update-remark")
     @Operation(summary = "订单备注")
     @PreAuthorize("@ss.hasPermission('trade:order:update')")
     public CommonResult<Boolean> updateOrderRemark(@RequestBody TradeOrderRemarkReqVO reqVO) {
@@ -103,8 +101,7 @@ public class TradeOrderController {
         return success(true);
     }
 
-    // TODO @puhui999:put 请求哈,update-price;
-    @PostMapping("/adjust-price")
+    @PutMapping("/update-price")
     @Operation(summary = "订单调价")
     @PreAuthorize("@ss.hasPermission('trade:order:update')")
     public CommonResult<Boolean> updateOrderPrice(@RequestBody TradeOrderUpdatePriceReqVO reqVO) {
@@ -112,8 +109,7 @@ public class TradeOrderController {
         return success(true);
     }
 
-    // TODO @puhui999:put 请求哈,update-address;
-    @PostMapping("/adjust-address")
+    @PutMapping("/update-address")
     @Operation(summary = "修改订单收货地址")
     @PreAuthorize("@ss.hasPermission('trade:order:update')")
     public CommonResult<Boolean> updateOrderAddress(@RequestBody TradeOrderUpdateAddressReqVO reqVO) {

+ 4 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppTradeAfterSaleController.java

@@ -8,8 +8,10 @@ import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSa
 import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleRespVO;
 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;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
@@ -71,6 +73,8 @@ public class AppTradeAfterSaleController {
     @Operation(summary = "申请售后")
     @AfterSaleLog(id = "#info.data", content = "'申请售后:售后编号['+#info.data+'],订单编号['+#createReqVO.orderItemId+'], '", operateType = AfterSaleOperateTypeEnum.APPLY)
     public CommonResult<Long> createAfterSale(@RequestBody AppTradeAfterSaleCreateReqVO createReqVO) {
+        AfterSaleLogUtils.setBeforeStatus(0);
+        AfterSaleLogUtils.setAfterStatus(TradeAfterSaleStatusEnum.APPLY.getStatus());
         return success(afterSaleService.createAfterSale(getLoginUserId(), createReqVO));
     }
 

+ 0 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/TradeCartController.http → yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/AppCartController.http


+ 19 - 22
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/TradeCartController.java → yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/AppCartController.java

@@ -2,11 +2,8 @@ package cn.iocoder.yudao.module.trade.controller.app.cart;
 
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
-import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartAddReqVO;
-import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartListRespVO;
-import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartResetReqVO;
-import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartUpdateReqVO;
-import cn.iocoder.yudao.module.trade.service.cart.TradeCartService;
+import cn.iocoder.yudao.module.trade.controller.app.cart.vo.*;
+import cn.iocoder.yudao.module.trade.service.cart.CartService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -18,7 +15,6 @@ import org.springframework.web.bind.annotation.*;
 import javax.annotation.Resource;
 import javax.validation.Valid;
 import java.util.List;
-import java.util.Map;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@@ -29,30 +25,38 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti
 @RequiredArgsConstructor
 @Validated
 @Slf4j
-public class TradeCartController {
+public class AppCartController {
 
     @Resource
-    private TradeCartService cartService;
+    private CartService cartService;
 
     @PostMapping("/add")
     @Operation(summary = "添加购物车商品")
     @PreAuthenticated
-    public CommonResult<Long> addCart(@Valid @RequestBody AppTradeCartAddReqVO addCountReqVO) {
+    public CommonResult<Long> addCart(@Valid @RequestBody AppCartAddReqVO addCountReqVO) {
         return success(cartService.addCart(getLoginUserId(), addCountReqVO));
     }
 
-    @PutMapping("/update")
-    @Operation(summary = "更新购物车商品")
+    @PutMapping("/update-count")
+    @Operation(summary = "更新购物车商品数量")
     @PreAuthenticated
-    public CommonResult<Boolean> updateCart(@Valid @RequestBody AppTradeCartUpdateReqVO updateReqVO) {
-        cartService.updateCart(getLoginUserId(), updateReqVO);
+    public CommonResult<Boolean> updateCartCount(@Valid @RequestBody AppCartUpdateCountReqVO updateReqVO) {
+        cartService.updateCartCount(getLoginUserId(), updateReqVO);
+        return success(true);
+    }
+
+    @PutMapping("/update-selected")
+    @Operation(summary = "更新购物车商品选中")
+    @PreAuthenticated
+    public CommonResult<Boolean> updateCartSelected(@Valid @RequestBody AppCartUpdateSelectedReqVO updateReqVO) {
+        cartService.updateCartSelected(getLoginUserId(), updateReqVO);
         return success(true);
     }
 
     @PutMapping("/reset")
     @Operation(summary = "重置购物车商品")
     @PreAuthenticated
-    public CommonResult<Boolean> resetCart(@Valid @RequestBody AppTradeCartResetReqVO updateReqVO) {
+    public CommonResult<Boolean> resetCart(@Valid @RequestBody AppCartResetReqVO updateReqVO) {
         cartService.resetCart(getLoginUserId(), updateReqVO);
         return success(true);
     }
@@ -73,17 +77,10 @@ public class TradeCartController {
         return success(cartService.getCartCount(getLoginUserId()));
     }
 
-    @GetMapping("get-count-map")
-    @Operation(summary = "查询用户在购物车中的商品 SPU 数量 Map")
-    @PreAuthenticated
-    public CommonResult<Map<Long, Integer>> getCartCountMap() {
-        return success(cartService.getCartCountMap(getLoginUserId()));
-    }
-
     @GetMapping("/list")
     @Operation(summary = "查询用户的购物车列表")
     @PreAuthenticated
-    public CommonResult<AppTradeCartListRespVO> getCartList() {
+    public CommonResult<AppCartListRespVO> getCartList() {
         return success(cartService.getCartList(getLoginUserId()));
     }
 

+ 1 - 5
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartAddReqVO.java → yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartAddReqVO.java

@@ -7,7 +7,7 @@ import javax.validation.constraints.NotNull;
 
 @Schema(description = "用户 App - 购物车添加购物项 Request VO")
 @Data
-public class AppTradeCartAddReqVO {
+public class AppCartAddReqVO {
 
     @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED,example = "1024")
     @NotNull(message = "商品 SKU 编号不能为空")
@@ -17,8 +17,4 @@ public class AppTradeCartAddReqVO {
     @NotNull(message = "数量不能为空")
     private Integer count;
 
-    @Schema(description = "是否添加到购物车", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
-    @NotNull(message = "是否添加购物车不能为空")
-    private Boolean addStatus;
-
 }

+ 1 - 1
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartDetailRespVO.java → yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartDetailRespVO.java

@@ -8,7 +8,7 @@ import java.util.List;
 
 @Schema(description = "用户 App - 用户的购物车明细 Response VO")
 @Data
-public class AppTradeCartDetailRespVO {
+public class AppCartDetailRespVO {
 
     /**
      * 商品分组数组

+ 4 - 1
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartListRespVO.java → yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartListRespVO.java

@@ -9,7 +9,7 @@ import java.util.List;
 
 @Schema(description = "用户 App - 用户的购物列表 Response VO")
 @Data
-public class AppTradeCartListRespVO {
+public class AppCartListRespVO {
 
     /**
      * 有效的购物项数组
@@ -31,6 +31,9 @@ public class AppTradeCartListRespVO {
         @Schema(description = "商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
         private Integer count;
 
+        @Schema(description = "是否选中", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
+        private Boolean selected;
+
         /**
          * 商品 SPU
          */

+ 1 - 1
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartResetReqVO.java → yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartResetReqVO.java

@@ -8,7 +8,7 @@ import javax.validation.constraints.NotNull;
 
 @Schema(description = "用户 App - 购物车重置 Request VO")
 @Data
-public class AppTradeCartResetReqVO {
+public class AppCartResetReqVO {
 
     @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     @NotNull(message = "编号不能为空")

+ 2 - 2
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartUpdateReqVO.java → yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartUpdateCountReqVO.java

@@ -6,9 +6,9 @@ import lombok.Data;
 import javax.validation.constraints.Min;
 import javax.validation.constraints.NotNull;
 
-@Schema(description = "用户 App - 购物车更新 Request VO")
+@Schema(description = "用户 App - 购物车更新数量 Request VO")
 @Data
-public class AppTradeCartUpdateReqVO {
+public class AppCartUpdateCountReqVO {
 
     @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     @NotNull(message = "编号不能为空")

+ 4 - 4
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartItemUpdateSelectedReqVO.java → yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppCartUpdateSelectedReqVO.java

@@ -8,11 +8,11 @@ import java.util.Collection;
 
 @Schema(description = "用户 App - 购物车更新是否选中 Request VO")
 @Data
-public class AppTradeCartItemUpdateSelectedReqVO {
+public class AppCartUpdateSelectedReqVO {
 
-    @Schema(description = "商品 SKU 编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024,2048")
-    @NotNull(message = "商品 SKU 编号列表不能为空")
-    private Collection<Long> skuIds;
+    @Schema(description = "编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024,2048")
+    @NotNull(message = "编号列表不能为空")
+    private Collection<Long> ids;
 
     @Schema(description = "是否选中", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
     @NotNull(message = "是否选中不能为空")

+ 1 - 6
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java

@@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
 import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
 import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi;
-import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.*;
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO;
@@ -91,15 +90,11 @@ public class AppTradeOrderController {
 
         // 查询订单项
         List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId());
-        // 查询商品属性
-        List<ProductPropertyValueDetailRespDTO> propertyValueDetails = productPropertyValueApi
-                .getPropertyValueDetailList(TradeOrderConvert.INSTANCE.convertPropertyValueIds(orderItems));
         // 查询物流公司
         DeliveryExpressDO express = order.getLogisticsId() != null && order.getLogisticsId() > 0 ?
                 deliveryExpressService.getDeliveryExpress(order.getLogisticsId()) : null;
         // 最终组合
-        return success(TradeOrderConvert.INSTANCE.convert02(order, orderItems,
-                propertyValueDetails, tradeOrderProperties, express));
+        return success(TradeOrderConvert.INSTANCE.convert02(order, orderItems, tradeOrderProperties, express));
     }
 
     @GetMapping("/get-express-track-list")

+ 23 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java

@@ -4,19 +4,26 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
 import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
+import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDetailRespVO;
 import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRespPageItemVO;
+import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.TradeAfterSaleLogRespVO;
 import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
 import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
+import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderBaseVO;
 import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO;
 import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleRespVO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleLogDO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
+import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogRespDTO;
 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.Mappings;
 import org.mapstruct.factory.Mappers;
 
+import java.util.List;
 import java.util.Map;
 
 @Mapper
@@ -61,4 +68,20 @@ public interface TradeAfterSaleConvert {
 
     PageResult<AppTradeAfterSaleRespVO> convertPage02(PageResult<TradeAfterSaleDO> page);
 
+    List<TradeAfterSaleLogRespDTO> convertList(List<TradeAfterSaleLogDO> list);
+    
+    default TradeAfterSaleDetailRespVO convert(TradeAfterSaleDO afterSale, TradeOrderDO order, List<TradeOrderItemDO> orderItems,
+                                               MemberUserRespDTO user, List<TradeAfterSaleLogRespDTO> logs) {
+        TradeAfterSaleDetailRespVO respVO = convert(afterSale, orderItems, convertList1(logs));
+        // 处理用户信息
+        respVO.setUser(convert(user));
+        // 处理订单信息
+        respVO.setOrder(convert(order));
+        return respVO;
+    }
+    List<TradeAfterSaleLogRespVO> convertList1(List<TradeAfterSaleLogRespDTO> list);
+    @Mapping(target = "id", source = "afterSale.id")
+    TradeAfterSaleDetailRespVO convert(TradeAfterSaleDO afterSale, List<TradeOrderItemDO> orderItems, List<TradeAfterSaleLogRespVO> logs);
+    TradeOrderBaseVO convert(TradeOrderDO order);
+
 }

+ 10 - 9
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/cart/TradeCartConvert.java

@@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
 import cn.iocoder.yudao.module.trade.controller.app.base.sku.AppProductSkuBaseRespVO;
 import cn.iocoder.yudao.module.trade.controller.app.base.spu.AppProductSpuBaseRespVO;
-import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartListRespVO;
-import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO;
+import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppCartListRespVO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
 
@@ -21,16 +21,16 @@ public interface TradeCartConvert {
 
     TradeCartConvert INSTANCE = Mappers.getMapper(TradeCartConvert.class);
 
-    default AppTradeCartListRespVO convertList(List<TradeCartDO> carts,
-                                               List<ProductSpuRespDTO> spus, List<ProductSkuRespDTO> skus) {
+    default AppCartListRespVO convertList(List<CartDO> carts,
+                                          List<ProductSpuRespDTO> spus, List<ProductSkuRespDTO> skus) {
         Map<Long, ProductSpuRespDTO> spuMap = convertMap(spus, ProductSpuRespDTO::getId);
         Map<Long, ProductSkuRespDTO> skuMap = convertMap(skus, ProductSkuRespDTO::getId);
         // 遍历,开始转换
-        List<AppTradeCartListRespVO.Cart> validList = new ArrayList<>(carts.size());
-        List<AppTradeCartListRespVO.Cart> invalidList = new ArrayList<>();
+        List<AppCartListRespVO.Cart> validList = new ArrayList<>(carts.size());
+        List<AppCartListRespVO.Cart> invalidList = new ArrayList<>();
         carts.forEach(cart -> {
-            AppTradeCartListRespVO.Cart cartVO = new AppTradeCartListRespVO.Cart();
-            cartVO.setId(cart.getId()).setCount(cart.getCount());
+            AppCartListRespVO.Cart cartVO = new AppCartListRespVO.Cart();
+            cartVO.setId(cart.getId()).setCount(cart.getCount()).setSelected(cart.getSelected());
             ProductSpuRespDTO spu = spuMap.get(cart.getSpuId());
             ProductSkuRespDTO sku = skuMap.get(cart.getSkuId());
             cartVO.setSpu(convert(spu)).setSku(convert(sku));
@@ -38,13 +38,14 @@ public interface TradeCartConvert {
             if (spu == null
                 || !ProductSpuStatusEnum.isEnable(spu.getStatus())
                 || spu.getStock() <= 0) {
+                cartVO.setSelected(false); // 强制设置成不可选中
                 invalidList.add(cartVO);
             } else {
                 // 虽然 SKU 可能也会不存在,但是可以通过购物车重新选择
                 validList.add(cartVO);
             }
         });
-        return new AppTradeCartListRespVO().setValidList(validList).setInvalidList(invalidList);
+        return new AppCartListRespVO().setValidList(validList).setInvalidList(invalidList);
     }
     AppProductSpuBaseRespVO convert(ProductSpuRespDTO spu);
     AppProductSkuBaseRespVO convert(ProductSkuRespDTO sku);

+ 7 - 3
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryPickUpStoreConvert.java

@@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.Deliver
 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.pickup.DeliveryPickUpStoreUpdateReqVO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO;
 import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
 import org.mapstruct.Named;
 import org.mapstruct.factory.Mappers;
 
@@ -28,10 +29,13 @@ public interface DeliveryPickUpStoreConvert {
 
     PageResult<DeliveryPickUpStoreRespVO> convertPage(PageResult<DeliveryPickUpStoreDO> page);
 
-    @Named("convertAreaIdToName")
-    default String convertAreaIdToName(Integer areaId) {
+    List<DeliveryPickUpStoreSimpleRespVO> convertList1(List<DeliveryPickUpStoreDO> list);
+    @Mapping(source = "areaId", target = "areaName", qualifiedByName = "convertAreaIdToAreaName")
+    DeliveryPickUpStoreSimpleRespVO convert02(DeliveryPickUpStoreDO bean);
+
+    @Named("convertAreaIdToAreaName")
+    default String convertAreaIdToAreaName(Integer areaId) {
         return AreaUtils.format(areaId);
     }
 
-    List<DeliveryPickUpStoreSimpleRespVO> convertList1(List<DeliveryPickUpStoreDO> list);
 }

+ 11 - 38
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java

@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.common.util.string.StrUtils;
 import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
 import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
@@ -22,7 +23,7 @@ import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductProp
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.*;
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO;
-import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
@@ -82,14 +83,16 @@ public interface TradeOrderConvert {
 
     TradeOrderItemDO convert(TradePriceCalculateRespBO.OrderItem item);
 
+    default ProductSkuUpdateStockReqDTO convert(List<TradeOrderItemDO> list) {
+        return new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(list));
+    }
+    List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list);
     @Mappings({
             @Mapping(source = "skuId", target = "id"),
             @Mapping(source = "count", target = "incrCount"),
     })
     ProductSkuUpdateStockReqDTO.Item convert(TradeOrderItemDO bean);
 
-    List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list);
-
     default PayOrderCreateReqDTO convert(TradeOrderDO order, List<TradeOrderItemDO> orderItems,
                                          TradePriceCalculateRespBO calculateRespBO, TradeOrderProperties orderProperties) {
         PayOrderCreateReqDTO createReqDTO = new PayOrderCreateReqDTO()
@@ -97,9 +100,7 @@ public interface TradeOrderConvert {
         // 商户相关字段
         createReqDTO.setMerchantOrderId(String.valueOf(order.getId()));
         String subject = calculateRespBO.getItems().get(0).getSpuName();
-        if (calculateRespBO.getItems().size() > 1) {
-            subject += " 等多件";
-        }
+        subject = StrUtils.maxLength(subject, PayOrderCreateReqDTO.SUBJECT_MAX_LENGTH); // 避免超过 32 位
         createReqDTO.setSubject(subject);
         createReqDTO.setBody(subject); // TODO 芋艿:临时写死
         // 订单相关字段
@@ -107,16 +108,6 @@ public interface TradeOrderConvert {
         return createReqDTO;
     }
 
-    default Set<Long> convertPropertyValueIds(List<TradeOrderItemDO> list) {
-        if (CollUtil.isEmpty(list)) {
-            return new HashSet<>();
-        }
-        return list.stream().filter(item -> item.getProperties() != null)
-                .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
-                .map(TradeOrderItemDO.Property::getValueId) // 将每个 Property 转换成对应的 propertyId,最后形成集合
-                .collect(Collectors.toSet());
-    }
-
     // TODO 芋艿:可简化
     default PageResult<TradeOrderPageItemRespVO> convertPage(PageResult<TradeOrderDO> pageResult,
                                                              List<TradeOrderItemDO> orderItems,
@@ -170,31 +161,13 @@ public interface TradeOrderConvert {
 
     // TODO 芋艿:可简化
     default AppTradeOrderDetailRespVO convert02(TradeOrderDO order, List<TradeOrderItemDO> orderItems,
-                                                List<ProductPropertyValueDetailRespDTO> propertyValueDetails, TradeOrderProperties tradeOrderProperties,
+                                                TradeOrderProperties tradeOrderProperties,
                                                 DeliveryExpressDO express) {
         AppTradeOrderDetailRespVO orderVO = convert3(order, orderItems);
         orderVO.setPayExpireTime(addTime(tradeOrderProperties.getExpireTime()));
         if (StrUtil.isNotEmpty(order.getPayChannelCode())) {
             orderVO.setPayChannelName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.CHANNEL_CODE, order.getPayChannelCode()));
         }
-        // 处理商品属性
-        Map<Long, ProductPropertyValueDetailRespDTO> propertyValueDetailMap = convertMap(propertyValueDetails, ProductPropertyValueDetailRespDTO::getValueId);
-        for (int i = 0; i < orderItems.size(); i++) {
-            List<TradeOrderItemDO.Property> properties = orderItems.get(i).getProperties();
-            if (CollUtil.isEmpty(properties)) {
-                continue;
-            }
-            AppTradeOrderItemRespVO item = orderVO.getItems().get(i);
-            item.setProperties(new ArrayList<>(properties.size()));
-            // 遍历每个 properties,设置到 TradeOrderPageItemRespVO.Item 中
-            properties.forEach(property -> {
-                ProductPropertyValueDetailRespDTO propertyValueDetail = propertyValueDetailMap.get(property.getValueId());
-                if (propertyValueDetail == null) {
-                    return;
-                }
-                item.getProperties().add(convert02(propertyValueDetail));
-            });
-        }
         // 处理收货地址
         orderVO.setReceiverAreaName(AreaUtils.format(order.getReceiverAreaId()));
         if (express != null) {
@@ -221,12 +194,12 @@ public interface TradeOrderConvert {
     ProductCommentCreateReqDTO convert04(AppTradeOrderItemCommentCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItemDO);
 
     default TradePriceCalculateReqBO convert(Long userId, AppTradeOrderSettlementReqVO settlementReqVO,
-                                             List<TradeCartDO> cartList) {
+                                             List<CartDO> cartList) {
         TradePriceCalculateReqBO reqBO = new TradePriceCalculateReqBO();
         reqBO.setUserId(userId).setCouponId(settlementReqVO.getCouponId()).setAddressId(settlementReqVO.getAddressId())
                 .setItems(new ArrayList<>(settlementReqVO.getItems().size()));
         // 商品项的构建
-        Map<Long, TradeCartDO> cartMap = convertMap(cartList, TradeCartDO::getId);
+        Map<Long, CartDO> cartMap = convertMap(cartList, CartDO::getId);
         for (AppTradeOrderSettlementReqVO.Item item : settlementReqVO.getItems()) {
             // 情况一:skuId + count
             if (item.getSkuId() != null) {
@@ -235,7 +208,7 @@ public interface TradeOrderConvert {
                 continue;
             }
             // 情况二:cartId
-            TradeCartDO cart = cartMap.get(item.getCartId());
+            CartDO cart = cartMap.get(item.getCartId());
             if (cart == null) {
                 continue;
             }

+ 6 - 33
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/cart/TradeCartDO.java → yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/cart/CartDO.java

@@ -17,7 +17,7 @@ import lombok.experimental.Accessors;
 @Data
 @EqualsAndHashCode(callSuper = true)
 @Accessors(chain = true)
-public class TradeCartDO extends BaseDO {
+public class CartDO extends BaseDO {
 
     // ========= 基础字段 BEGIN =========
 
@@ -33,27 +33,7 @@ public class TradeCartDO extends BaseDO {
      */
     private Long userId;
 
-    /**
-     * 是否添加到购物车
-     *
-     * false - 未添加:用户点击【立即购买】
-     * true - 已添加:用户点击【添加购物车】
-     *
-     * 为什么要设计这个字段?
-     *      配合 orderStatus 字段,可以知道有多少商品,用户点击了【立即购买】,最终多少【确认下单】
-     */
-    private Boolean addStatus;
-    /**
-     * 是否提交订单
-     *
-     * false - 未下单:立即购买,或者添加到购物车,此时设置为 false
-     * true - 已下单:确认下单,此时设置为 true
-     */
-    private Boolean orderStatus;
-
-    // ========= 基础字段 END =========
-
-    // ========= 商品信息 BEGIN =========
+    // ========= 商品信息 =========
 
     /**
      * 商品 SPU 编号
@@ -71,16 +51,9 @@ public class TradeCartDO extends BaseDO {
      * 商品购买数量
      */
     private Integer count;
-
-    // ========= 商品信息 END =========
-
-    // ========= 优惠信息 BEGIN =========
-
-    // TODO 芋艿:combination_id 拼团 ID
-    // TODO 芋艿:seckill_id 秒杀产品 ID
-    // TODO 芋艿:bargain_id 砍价 ID
-    // TODO 芋艿:pinkId 团长拼团 ID
-
-    // ========= 优惠信息 END =========
+    /**
+     * 是否选中
+     */
+    private Boolean selected;
 
 }

+ 5 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java

@@ -27,6 +27,11 @@ import java.time.LocalDateTime;
 @AllArgsConstructor
 public class TradeOrderDO extends BaseDO {
 
+    /**
+     * 发货物流公司编号 - 空(无需发货)
+     */
+    public static final Long LOGISTICS_ID_NULL = 0L;
+
     // ========== 订单基本信息 ==========
     /**
      * 订单编号,主键自增

+ 2 - 2
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java

@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.order;
 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO;
-import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -46,7 +46,7 @@ public class TradeOrderItemDO extends BaseDO {
     /**
      * 购物车项编号
      *
-     * 关联 {@link TradeCartDO#getId()}
+     * 关联 {@link CartDO#getId()}
      */
     private Long cartId;
 

+ 62 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/cart/CartMapper.java

@@ -0,0 +1,62 @@
+package cn.iocoder.yudao.module.trade.dal.mysql.cart;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.map.MapUtil;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@Mapper
+public interface CartMapper extends BaseMapperX<CartDO> {
+
+    default CartDO selectByUserIdAndSkuId(Long userId, Long skuId) {
+        return selectOne(CartDO::getUserId, userId,
+                CartDO::getSkuId, skuId);
+    }
+
+    default Integer selectSumByUserId(Long userId) {
+        // SQL sum 查询
+        List<Map<String, Object>> result = selectMaps(new QueryWrapper<CartDO>()
+                .select("SUM(count) AS sumCount")
+                .eq("user_id", userId)
+                .eq("selected", true)); // 只计算选中的
+        // 获得数量
+        return CollUtil.getFirst(result) != null ? MapUtil.getInt(result.get(0), "sumCount") : 0;
+    }
+
+    default CartDO selectById(Long id, Long userId) {
+        return selectOne(CartDO::getId, id,
+                CartDO::getUserId, userId);
+    }
+
+    default List<CartDO> selectListByIds(Collection<Long> ids, Long userId) {
+        return selectList(new LambdaQueryWrapper<CartDO>()
+                .in(CartDO::getId, ids)
+                .eq(CartDO::getUserId, userId));
+    }
+
+    default List<CartDO> selectListByUserId(Long userId) {
+        return selectList(new LambdaQueryWrapper<CartDO>()
+                .eq(CartDO::getUserId, userId));
+    }
+
+    default List<CartDO> selectListByUserId(Long userId, Set<Long> ids) {
+        return selectList(new LambdaQueryWrapper<CartDO>()
+                .eq(CartDO::getUserId, userId)
+                .in(CartDO::getId, ids));
+    }
+
+    default void updateByIds(Collection<Long> ids, Long userId, CartDO updateObj) {
+        update(updateObj, new LambdaQueryWrapper<CartDO>()
+                .in(CartDO::getId, ids)
+                .eq(CartDO::getUserId, userId));
+    }
+
+}

+ 0 - 80
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/cart/TradeCartMapper.java

@@ -1,80 +0,0 @@
-package cn.iocoder.yudao.module.trade.dal.mysql.cart;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.map.MapUtil;
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
-import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
-import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import org.apache.ibatis.annotations.Mapper;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-@Mapper
-public interface TradeCartMapper extends BaseMapperX<TradeCartDO> {
-
-    default TradeCartDO selectByUserIdAndSkuId(Long userId, Long skuId,
-                                               Boolean addStatus, Boolean orderStatus) {
-        return selectOne(new LambdaQueryWrapper<TradeCartDO>().eq(TradeCartDO::getUserId, userId)
-                .eq(TradeCartDO::getSkuId, skuId)
-                .eq(TradeCartDO::getAddStatus, addStatus)
-                .eq(TradeCartDO::getOrderStatus, orderStatus));
-    }
-
-    default Integer selectSumByUserId(Long userId) {
-        // SQL sum 查询
-        List<Map<String, Object>> result = selectMaps(new QueryWrapper<TradeCartDO>()
-                .select("SUM(count) AS sumCount")
-                .eq("user_id", userId)
-                .eq("add_status", true) // 只计算添加到购物车中的
-                .eq("order_status", false)); // 必须未下单
-        // 获得数量
-        return CollUtil.getFirst(result) != null ? MapUtil.getInt(result.get(0), "sumCount") : 0;
-    }
-
-    default Map<Long, Integer> selectSumMapByUserId(Long userId) {
-        // SQL sum 查询
-        List<Map<String, Object>> result = selectMaps(new QueryWrapper<TradeCartDO>()
-                .select("spu_id, SUM(count) AS sumCount")
-                .eq("user_id", userId)
-                .eq("add_status", true) // 只计算添加到购物车中的
-                .eq("order_status", false) // 必须未下单
-                .groupBy("spu_id"));
-        // 获得数量
-        return CollectionUtils.convertMap(result, item -> MapUtil.getLong(item, "spu_id"),
-                item -> MapUtil.getInt(item, "sumCount"));
-    }
-
-    default TradeCartDO selectById(Long id, Long userId) {
-        return selectOne(TradeCartDO::getId, id,
-                TradeCartDO::getUserId, userId);
-    }
-
-    default List<TradeCartDO> selectListByIds(Collection<Long> ids, Long userId) {
-        return selectList(new LambdaQueryWrapper<TradeCartDO>()
-                .in(TradeCartDO::getId, ids)
-                .eq(TradeCartDO::getUserId, userId));
-    }
-
-    default List<TradeCartDO> selectListByUserId(Long userId, Boolean addStatus, Boolean orderStatus) {
-        return selectList(new LambdaQueryWrapper<TradeCartDO>()
-                .eq(TradeCartDO::getUserId, userId)
-                .eq(TradeCartDO::getAddStatus, addStatus)
-                .eq(TradeCartDO::getOrderStatus, orderStatus));
-    }
-
-    default void updateByIds(Collection<Long> ids, TradeCartDO updateObject) {
-        update(updateObject, new LambdaQueryWrapper<TradeCartDO>().in(TradeCartDO::getId, ids));
-    }
-
-    default List<TradeCartDO> selectListByUserId(Long userId, Set<Long> ids) {
-        return selectList(new LambdaQueryWrapper<TradeCartDO>()
-                .eq(TradeCartDO::getUserId, userId)
-                .in(TradeCartDO::getId, ids));
-    }
-
-}

+ 38 - 3
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/aop/AfterSaleLogAspect.java

@@ -3,6 +3,7 @@ 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;
@@ -33,9 +34,26 @@ public class AfterSaleLogAspect {
 
     @Resource
     private AfterSaleLogService afterSaleLogService;
-
-    // TODO chenchen: 这个分 3 行把;
-    private final static String OPERATE_TYPE = "operateType", ID = "id", CONTENT = "content";
+    /**
+     * 售前状态
+     */
+    private static final ThreadLocal<Integer> BEFORE_STATUS = new ThreadLocal<>();
+    /**
+     * 售后状态
+     */
+    private static final ThreadLocal<Integer> AFTER_STATUS = new ThreadLocal<>();
+    /**
+     * 操作类型
+     */
+    private final static String OPERATE_TYPE = "operateType";
+    /**
+     * ID
+     */
+    private final static String ID = "id";
+    /**
+     * 操作明细
+     */
+    private final static String CONTENT = "content";
 
     /**
      * 切面存入日志
@@ -52,11 +70,15 @@ public class AfterSaleLogAspect {
                     .setUserType(userType)
                     .setAfterSaleId(MapUtil.getLong(formatObj, ID))
                     .setOperateType(MapUtil.getStr(formatObj, OPERATE_TYPE))
+                    .setBeforeStatus(BEFORE_STATUS.get())
+                    .setAfterStatus(AFTER_STATUS.get())
                     .setContent(MapUtil.getStr(formatObj, CONTENT));
             // 异步存入数据库
             afterSaleLogService.createLog(dto);
         } catch (Exception exception) {
             log.error("[doAfterReturning][afterSaleLog({}) 日志记录错误]", toJsonString(afterSaleLog), exception);
+        }finally {
+            clearThreadLocal();
         }
     }
 
@@ -85,4 +107,17 @@ public class AfterSaleLogAspect {
         return result;
     }
 
+    public static void setBeforeStatus(Integer beforestatus) {
+        BEFORE_STATUS.set(beforestatus);
+    }
+
+    public static void setAfterStatus(Integer afterStatus) {
+        AFTER_STATUS.set(afterStatus);
+    }
+
+    private static void clearThreadLocal() {
+        AFTER_STATUS.remove();
+        BEFORE_STATUS.remove();
+    }
+
 }

+ 8 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/dto/TradeAfterSaleLogCreateReqDTO.java

@@ -42,5 +42,13 @@ public class TradeAfterSaleLogCreateReqDTO {
      * 操作明细
      */
     private String content;
+    /**
+     * 售前状态
+     */
+    private Integer beforeStatus;
+    /**
+     * 售后状态
+     */
+    private Integer afterStatus;
 
 }

+ 59 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/dto/TradeAfterSaleLogRespDTO.java

@@ -0,0 +1,59 @@
+package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+
+// TODO @puhui999:这个是不是应该搞成 vo 啊?
+/**
+ * 贸易售后日志详情 DTO
+ *
+ * @author HUIHUI
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class TradeAfterSaleLogRespDTO {
+
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20669")
+    private Long id;
+
+    @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22634")
+    @NotNull(message = "用户编号不能为空")
+    private Long userId;
+
+    @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @NotNull(message = "用户类型不能为空")
+    private Integer userType;
+
+    @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3023")
+    @NotNull(message = "售后编号不能为空")
+    private Long afterSaleId;
+
+    @Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25870")
+    @NotNull(message = "订单编号不能为空")
+    private Long orderId;
+
+    @Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23154")
+    @NotNull(message = "订单项编号不能为空")
+    private Long orderItemId;
+
+    @Schema(description = "售后状态(之前)", example = "2")
+    private Integer beforeStatus;
+
+    @Schema(description = "售后状态(之后)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "售后状态(之后)不能为空")
+    private Integer afterStatus;
+
+    @Schema(description = "操作明细", requiredMode = Schema.RequiredMode.REQUIRED, example = "维权完成,退款金额:¥37776.00")
+    @NotNull(message = "操作明细不能为空")
+    private String content;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    private LocalDateTime createTime;
+
+}

+ 11 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/service/AfterSaleLogService.java

@@ -2,6 +2,9 @@ package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service;
 
 
 import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogCreateReqDTO;
+import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogRespDTO;
+
+import java.util.List;
 
 /**
  * 交易售后日志 Service 接口
@@ -20,4 +23,12 @@ public interface AfterSaleLogService {
      */
     void createLog(TradeAfterSaleLogCreateReqDTO logDTO);
 
+    /**
+     * 获取售后日志
+     *
+     * @param afterSaleId 售后编号
+     * @return 售后日志
+     */
+    List<TradeAfterSaleLogRespDTO> getLog(Long afterSaleId);
+
 }

+ 22 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/util/AfterSaleLogUtils.java

@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.util;
+
+
+import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.aop.AfterSaleLogAspect;
+
+/**
+ * 操作日志工具类
+ * 目前主要的作用,是提供给业务代码,记录操作明细和拓展字段
+ *
+ * @author 芋道源码
+ */
+public class AfterSaleLogUtils {
+
+    public static void setBeforeStatus(Integer status) {
+        AfterSaleLogAspect.setBeforeStatus(status);
+    }
+
+    public static void setAfterStatus(Integer status) {
+        AfterSaleLogAspect.setAfterStatus(status);
+    }
+
+}

+ 8 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleService.java

@@ -42,6 +42,14 @@ public interface TradeAfterSaleService {
      */
     TradeAfterSaleDO getAfterSale(Long userId, Long id);
 
+    /**
+     * 【管理员】获得售后单
+     *
+     * @param id 售后编号
+     * @return 售后订单
+     */
+    TradeAfterSaleDO getAfterSale(Long id);
+
     /**
      * 【会员】创建售后订单
      *

+ 20 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java

@@ -26,6 +26,7 @@ import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum;
 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum;
 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
 import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogCreateReqDTO;
+import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogRespDTO;
 import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service.AfterSaleLogService;
 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
 import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
@@ -40,6 +41,7 @@ import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
 import java.time.LocalDateTime;
+import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
@@ -86,6 +88,16 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa
          return tradeAfterSaleMapper.selectByIdAndUserId(id, userId);
     }
 
+    @Override
+    public TradeAfterSaleDO getAfterSale(Long id) {
+        TradeAfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id);
+        // TODO @puhui999;读不到,不要这里报错哈;交给前端报错;一般是读取信息不到,message 提示,然后 close tab;
+        if (afterSale == null) {
+            throw exception(AFTER_SALE_NOT_FOUND);
+        }
+        return afterSale;
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Long createAfterSale(Long userId, AppTradeAfterSaleCreateReqVO createReqVO) {
@@ -439,4 +451,12 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa
             log.error("[createLog][request({}) 日志记录错误]", toJsonString(logDTO), exception);
         }
     }
+
+    @Override
+    public List<TradeAfterSaleLogRespDTO> getLog(Long afterSaleId) {
+        // TODO 不熟悉流程先这么滴
+        List<TradeAfterSaleLogDO> saleLogDOs = tradeAfterSaleLogMapper.selectList(TradeAfterSaleLogDO::getAfterSaleId, afterSaleId);
+        return TradeAfterSaleConvert.INSTANCE.convertList(saleLogDOs);
+    }
+
 }

+ 16 - 20
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/TradeCartService.java → yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/CartService.java

@@ -1,15 +1,11 @@
 package cn.iocoder.yudao.module.trade.service.cart;
 
-import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartAddReqVO;
-import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartListRespVO;
-import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartResetReqVO;
-import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartUpdateReqVO;
-import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO;
+import cn.iocoder.yudao.module.trade.controller.app.cart.vo.*;
+import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
 
 import javax.validation.Valid;
 import java.util.Collection;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 /**
@@ -17,7 +13,7 @@ import java.util.Set;
  *
  * @author 芋道源码
  */
-public interface TradeCartService {
+public interface CartService {
 
     /**
      * 添加商品到购物车
@@ -26,7 +22,7 @@ public interface TradeCartService {
      * @param addReqVO 添加信息
      * @return 购物项的编号
      */
-    Long addCart(Long userId, @Valid AppTradeCartAddReqVO addReqVO);
+    Long addCart(Long userId, @Valid AppCartAddReqVO addReqVO);
 
     /**
      * 更新购物车商品数量
@@ -34,7 +30,15 @@ public interface TradeCartService {
      * @param userId 用户编号
      * @param updateCountReqVO 更新信息
      */
-    void updateCart(Long userId, AppTradeCartUpdateReqVO updateCountReqVO);
+    void updateCartCount(Long userId, AppCartUpdateCountReqVO updateCountReqVO);
+
+    /**
+     * 更新购物车选中状态
+     *
+     * @param userId 用户编号
+     * @param updateSelectedReqVO 更新信息
+     */
+    void updateCartSelected(Long userId, @Valid AppCartUpdateSelectedReqVO updateSelectedReqVO);
 
     /**
      * 重置购物车商品
@@ -44,7 +48,7 @@ public interface TradeCartService {
      * @param userId 用户编号
      * @param updateReqVO 重置信息
      */
-    void resetCart(Long userId, AppTradeCartResetReqVO updateReqVO);
+    void resetCart(Long userId, AppCartResetReqVO updateReqVO);
 
     /**
      * 删除购物车商品
@@ -68,7 +72,7 @@ public interface TradeCartService {
      * @param userId 用户编号
      * @return 购物车列表
      */
-    AppTradeCartListRespVO getCartList(Long userId);
+    AppCartListRespVO getCartList(Long userId);
 
     /**
      * 查询用户的购物车列表
@@ -77,14 +81,6 @@ public interface TradeCartService {
      * @param ids 购物项的编号
      * @return 购物车列表
      */
-    List<TradeCartDO> getCartList(Long userId, Set<Long> ids);
-
-    /**
-     * 获得用户的购物车商品 SPU 数量的 Map
-     *
-     * @param userId 用户编号
-     * @return 购物车商品 SPU 数量的 Map
-     */
-    Map<Long, Integer> getCartCountMap(Long userId);
+    List<CartDO> getCartList(Long userId, Set<Long> ids);
 
 }

+ 40 - 50
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/TradeCartServiceImpl.java → yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/CartServiceImpl.java

@@ -5,13 +5,10 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
-import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartAddReqVO;
-import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartListRespVO;
-import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartResetReqVO;
-import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartUpdateReqVO;
+import cn.iocoder.yudao.module.trade.controller.app.cart.vo.*;
 import cn.iocoder.yudao.module.trade.convert.cart.TradeCartConvert;
-import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO;
-import cn.iocoder.yudao.module.trade.dal.mysql.cart.TradeCartMapper;
+import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
+import cn.iocoder.yudao.module.trade.dal.mysql.cart.CartMapper;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
@@ -29,17 +26,16 @@ import static java.util.Collections.emptyList;
 /**
  * 购物车 Service 实现类
  *
- * // TODO 芋艿:秒杀、拼团、砍价对购物车的影响
- * // TODO 芋艿:未来优化:购物车的价格计算,支持营销信息
+ * // TODO 芋艿:未来优化:购物车的价格计算,支持营销信息;目前不支持的原因,前端界面需要前端 pr 支持下;
  *
  * @author 芋道源码
  */
 @Service
 @Validated
-public class TradeCartServiceImpl implements TradeCartService {
+public class CartServiceImpl implements CartService {
 
     @Resource
-    private TradeCartMapper cartMapper;
+    private CartMapper cartMapper;
 
     @Resource
     private ProductSpuApi productSpuApi;
@@ -47,39 +43,31 @@ public class TradeCartServiceImpl implements TradeCartService {
     private ProductSkuApi productSkuApi;
 
     @Override
-    public Long addCart(Long userId, AppTradeCartAddReqVO addReqVO) {
+    public Long addCart(Long userId, AppCartAddReqVO addReqVO) {
         // 查询 TradeCartDO
-        TradeCartDO cart = cartMapper.selectByUserIdAndSkuId(userId, addReqVO.getSkuId(),
-                addReqVO.getAddStatus(), false);
+        CartDO cart = cartMapper.selectByUserIdAndSkuId(userId, addReqVO.getSkuId());
         // 校验 SKU
-        Integer count = cart != null && addReqVO.getAddStatus() ?
-                cart.getCount() + addReqVO.getCount() : addReqVO.getCount();
+        Integer count = addReqVO.getCount();
         ProductSkuRespDTO sku = checkProductSku(addReqVO.getSkuId(), count);
 
-        // 情况零:特殊,count 小于等于 0,说明前端项目删除
         // 情况一:存在,则进行数量更新
         if (cart != null) {
-            // 特殊情况,如果 count 小于等于 0,说明前端想要删除
-            if (count <= 0) {
-                cartMapper.deleteById(cart.getId());
-            } else {
-                cartMapper.updateById(new TradeCartDO().setId(cart.getId()).setCount(count));
-            }
+            cartMapper.updateById(new CartDO().setId(cart.getId()).setSelected(true)
+                    .setCount(cart.getCount() + count));
             return cart.getId();
         // 情况二:不存在,则进行插入
         } else {
-            cart = new TradeCartDO().setUserId(userId)
-                    .setSpuId(sku.getSpuId()).setSkuId(sku.getId()).setCount(count)
-                    .setAddStatus(addReqVO.getAddStatus()).setOrderStatus(false);
+            cart = new CartDO().setUserId(userId).setSelected(true)
+                    .setSpuId(sku.getSpuId()).setSkuId(sku.getId()).setCount(count);
             cartMapper.insert(cart);
         }
         return cart.getId();
     }
 
     @Override
-    public void updateCart(Long userId, AppTradeCartUpdateReqVO updateReqVO) {
+    public void updateCartCount(Long userId, AppCartUpdateCountReqVO updateReqVO) {
         // 校验 TradeCartDO 存在
-        TradeCartDO cart = cartMapper.selectById(updateReqVO.getId(), userId);
+        CartDO cart = cartMapper.selectById(updateReqVO.getId(), userId);
         if (cart == null) {
             throw exception(CARD_ITEM_NOT_FOUND);
         }
@@ -87,29 +75,34 @@ public class TradeCartServiceImpl implements TradeCartService {
         checkProductSku(cart.getSkuId(), updateReqVO.getCount());
 
         // 更新数量
-        cartMapper.updateById(new TradeCartDO().setId(cart.getId())
+        cartMapper.updateById(new CartDO().setId(cart.getId())
                 .setCount(updateReqVO.getCount()));
     }
 
+    @Override
+    public void updateCartSelected(Long userId, AppCartUpdateSelectedReqVO updateSelectedReqVO) {
+        cartMapper.updateByIds(updateSelectedReqVO.getIds(), userId,
+                new CartDO().setSelected(updateSelectedReqVO.getSelected()));
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public void resetCart(Long userId, AppTradeCartResetReqVO resetReqVO) {
+    public void resetCart(Long userId, AppCartResetReqVO resetReqVO) {
         // 第一步:删除原本的购物项
-        TradeCartDO oldCart = cartMapper.selectById(resetReqVO.getId(), userId);
+        CartDO oldCart = cartMapper.selectById(resetReqVO.getId(), userId);
         if (oldCart == null) {
             throw exception(CARD_ITEM_NOT_FOUND);
         }
         cartMapper.deleteById(oldCart.getId());
 
         // 第二步:添加新的购物项
-        TradeCartDO newCart = cartMapper.selectByUserIdAndSkuId(userId, resetReqVO.getSkuId(),
-                true, false);
+        CartDO newCart = cartMapper.selectByUserIdAndSkuId(userId, resetReqVO.getSkuId());
         if (newCart != null) {
-            updateCart(userId, new AppTradeCartUpdateReqVO()
+            updateCartCount(userId, new AppCartUpdateCountReqVO()
                     .setId(newCart.getId()).setCount(resetReqVO.getCount()));
         } else {
-            addCart(userId, new AppTradeCartAddReqVO().setAddStatus(true)
-                    .setSkuId(resetReqVO.getSkuId()).setCount(resetReqVO.getCount()));
+            addCart(userId, new AppCartAddReqVO().setSkuId(resetReqVO.getSkuId())
+                    .setCount(resetReqVO.getCount()));
         }
     }
 
@@ -122,7 +115,7 @@ public class TradeCartServiceImpl implements TradeCartService {
     @Override
     public void deleteCart(Long userId, Collection<Long> ids) {
         // 查询 TradeCartDO 列表
-        List<TradeCartDO> carts = cartMapper.selectListByIds(ids, userId);
+        List<CartDO> carts = cartMapper.selectListByIds(ids, userId);
         if (CollUtil.isEmpty(carts)) {
             return;
         }
@@ -133,30 +126,27 @@ public class TradeCartServiceImpl implements TradeCartService {
 
     @Override
     public Integer getCartCount(Long userId) {
+        // TODO 芋艿:需要算上 selected
         return cartMapper.selectSumByUserId(userId);
     }
 
     @Override
-    public Map<Long, Integer> getCartCountMap(Long userId) {
-        return cartMapper.selectSumMapByUserId(userId);
-    }
-
-    @Override
-    public AppTradeCartListRespVO getCartList(Long userId) {
-        // 获得购物车的商品,只查询未下单的
-        List<TradeCartDO> carts = cartMapper.selectListByUserId(userId, true, false);
-        carts.sort(Comparator.comparing(TradeCartDO::getId).reversed());
+    public AppCartListRespVO getCartList(Long userId) {
+        // 获得购物车的商品
+        List<CartDO> carts = cartMapper.selectListByUserId(userId);
+        carts.sort(Comparator.comparing(CartDO::getId).reversed());
         // 如果未空,则返回空结果
         if (CollUtil.isEmpty(carts)) {
-            return new AppTradeCartListRespVO().setValidList(emptyList())
+            return new AppCartListRespVO().setValidList(emptyList())
                     .setInvalidList(emptyList());
         }
 
         // 查询 SPU、SKU 列表
-        List<ProductSpuRespDTO> spus = productSpuApi.getSpuList(convertSet(carts, TradeCartDO::getSpuId));
-        List<ProductSkuRespDTO> skus = productSkuApi.getSkuList(convertSet(carts, TradeCartDO::getSkuId));
+        List<ProductSpuRespDTO> spus = productSpuApi.getSpuList(convertSet(carts, CartDO::getSpuId));
+        List<ProductSkuRespDTO> skus = productSkuApi.getSkuList(convertSet(carts, CartDO::getSkuId));
 
         // 如果 SPU 被删除,则删除购物车对应的商品。延迟删除
+        // 为什么不是 SKU 被删除呢?因为 SKU 被删除时,还可以通过 SPU 选择其它 SKU
         deleteCartIfSpuDeleted(carts, spus);
 
         // 拼接数据
@@ -164,14 +154,14 @@ public class TradeCartServiceImpl implements TradeCartService {
     }
 
     @Override
-    public List<TradeCartDO> getCartList(Long userId, Set<Long> ids) {
+    public List<CartDO> getCartList(Long userId, Set<Long> ids) {
         if (CollUtil.isEmpty(ids)) {
             return Collections.emptyList();
         }
         return cartMapper.selectListByUserId(userId, ids);
     }
 
-    private void deleteCartIfSpuDeleted(List<TradeCartDO> carts, List<ProductSpuRespDTO> spus) {
+    private void deleteCartIfSpuDeleted(List<CartDO> carts, List<ProductSpuRespDTO> spus) {
         // 如果 SPU 被删除,则删除购物车对应的商品。延迟删除
         carts.removeIf(cart -> {
             if (spus.stream().noneMatch(spu -> spu.getId().equals(cart.getSpuId()))) {

+ 9 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressService.java

@@ -47,6 +47,14 @@ public interface DeliveryExpressService {
      */
     DeliveryExpressDO getDeliveryExpress(Long id);
 
+    /**
+     * 校验快递公司是否合法
+     *
+     * @param id 编号
+     * @return 快递公司
+     */
+    DeliveryExpressDO validateDeliveryExpress(Long id);
+
     /**
      * 获得快递公司分页
      *
@@ -70,4 +78,5 @@ public interface DeliveryExpressService {
      * @return 快递公司列表
      */
     List<DeliveryExpressDO> getDeliveryExpressListByStatus(Integer status);
+
 }

+ 14 - 3
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressServiceImpl.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.trade.service.delivery;
 
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressCreateReqVO;
 import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressExportReqVO;
@@ -12,12 +13,10 @@ import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
-import java.util.Collection;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_CODE_DUPLICATE;
-import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_NOT_EXISTS;
+import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
 
 /**
  * 快递公司 Service 实现类
@@ -85,6 +84,18 @@ public class DeliveryExpressServiceImpl implements DeliveryExpressService {
         return deliveryExpressMapper.selectById(id);
     }
 
+    @Override
+    public DeliveryExpressDO validateDeliveryExpress(Long id) {
+        DeliveryExpressDO deliveryExpress = deliveryExpressMapper.selectById(id);
+        if (deliveryExpress == null) {
+            throw exception(EXPRESS_NOT_EXISTS);
+        }
+        if (deliveryExpress.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) {
+            throw exception(EXPRESS_STATUS_NOT_ENABLE);
+        }
+        return deliveryExpress;
+    }
+
     @Override
     public PageResult<DeliveryExpressDO> getDeliveryExpressPage(DeliveryExpressPageReqVO pageReqVO) {
         return deliveryExpressMapper.selectPage(pageReqVO);

+ 25 - 29
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java

@@ -7,7 +7,6 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.spring.SpringUtil;
 import cn.iocoder.yudao.framework.common.core.KeyValue;
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
@@ -26,7 +25,6 @@ import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
 import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;
 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
-import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
 import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi;
 import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi;
 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO;
@@ -43,8 +41,7 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettle
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO;
 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
 import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
-import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO;
-import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
@@ -53,7 +50,7 @@ import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants;
 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
 import cn.iocoder.yudao.module.trade.enums.order.*;
 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
-import cn.iocoder.yudao.module.trade.service.cart.TradeCartService;
+import cn.iocoder.yudao.module.trade.service.cart.CartService;
 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
 import cn.iocoder.yudao.module.trade.service.message.TradeMessageService;
 import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO;
@@ -70,6 +67,7 @@ import javax.annotation.Resource;
 import java.time.LocalDateTime;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
@@ -93,7 +91,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
     private TradeOrderItemMapper tradeOrderItemMapper;
 
     @Resource
-    private TradeCartService tradeCartService;
+    private CartService cartService;
     @Resource
     private TradePriceService tradePriceService;
     @Resource
@@ -168,7 +166,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
      */
     private TradePriceCalculateRespBO calculatePrice(Long userId, AppTradeOrderSettlementReqVO settlementReqVO) {
         // 1. 如果来自购物车,则获得购物车的商品
-        List<TradeCartDO> cartList = tradeCartService.getCartList(userId,
+        List<CartDO> cartList = cartService.getCartList(userId,
                 convertSet(settlementReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId));
 
         // 2. 计算价格
@@ -190,6 +188,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         // 订单创建完后的逻辑
         afterCreateTradeOrder(userId, createReqVO, order, orderItems, calculateRespBO);
         // 3.3 校验订单类型
+        // TODO @puhui999:这个逻辑,先抽个小方法;未来要通过设计模式,把这些拼团之类的逻辑,抽象出去
         // 拼团
         if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
             MemberUserRespDTO user = memberUserApi.getUser(userId);
@@ -292,11 +291,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
                                        TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> orderItems,
                                        TradePriceCalculateRespBO calculateRespBO) {
         // 下单时扣减商品库存
-        productSkuApi.updateSkuStock(new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(orderItems)));
+        productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems));
 
-        // 删除购物车商品 TODO 芋艿:待实现
+        // 删除购物车商品
+        Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId);
+        if (CollUtil.isNotEmpty(cartIds)) {
+            cartService.deleteCart(userId, cartIds);
+        }
 
-        // 扣减积分,抵扣金额 TODO 芋艿:待实现
+        // 扣减积分 TODO 芋艿:待实现
 
         // 有使用优惠券时更新
         if (createReqVO.getCouponId() != null) {
@@ -411,29 +414,24 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void deliveryOrder(TradeOrderDeliveryReqVO deliveryReqVO) {
-        // TODO @puhui999:只有选择快递的,才可以发货
         // 1.1 校验并获得交易订单(可发货)
         TradeOrderDO order = validateOrderDeliverable(deliveryReqVO.getId());
+        // 1.2 校验 deliveryType 是否为快递,是快递才可以发货
+        if (ObjectUtil.notEqual(order.getDeliveryType(), DeliveryTypeEnum.EXPRESS.getMode())) {
+            throw exception(ORDER_DELIVERY_FAIL_DELIVERY_TYPE_NOT_EXPRESS);
+        }
 
-        // TODO @puhui999:下面不修改 deliveryType,直接校验 deliveryType 是否为快递,是快递才可以发货;先做严格的方式哈。
-        // 判断发货类型
+        // 2. 更新订单为已发货
         TradeOrderDO updateOrderObj = new TradeOrderDO();
         // 2.1 快递发货
-        if (ObjectUtil.notEqual(deliveryReqVO.getLogisticsId(), 0L)) {
-            // 校验快递公司
-            DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId());
-            if (deliveryExpress == null) {
-                throw exception(EXPRESS_NOT_EXISTS);
-            }
-            if (deliveryExpress.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) {
-                throw exception(EXPRESS_STATUS_NOT_ENABLE);
-            }
-            updateOrderObj.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo()).setDeliveryType(DeliveryTypeEnum.EXPRESS.getMode());
+        if (ObjectUtil.notEqual(deliveryReqVO.getLogisticsId(), TradeOrderDO.LOGISTICS_ID_NULL)) {
+            deliveryExpressService.validateDeliveryExpress(deliveryReqVO.getLogisticsId());
+            updateOrderObj.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo());
         } else {
             // 2.2 无需发货
-            updateOrderObj.setLogisticsId(0L).setLogisticsNo("").setDeliveryType(DeliveryTypeEnum.NULL.getMode());
+            updateOrderObj.setLogisticsId(0L).setLogisticsNo("");
         }
-        // 更新 TradeOrderDO 状态为已发货,等待收货
+        // 执行更新
         updateOrderObj.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now());
         int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), updateOrderObj);
         if (updateCount == 0) {
@@ -471,16 +469,14 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         // 订单类型:拼团
         if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
             // 校验订单拼团是否成功
-            // TODO @puhui999:是不是取反?
-            if (combinationRecordApi.isCombinationRecordSuccess(order.getUserId(), order.getId())) {
+            if (!combinationRecordApi.isCombinationRecordSuccess(order.getUserId(), order.getId())) {
                 throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS);
             }
         }
         // 订单类类型:砍价
         if (Objects.equals(TradeOrderTypeEnum.BARGAIN.getType(), order.getType())) {
             // 校验订单砍价是否成功
-            // TODO @puhui999:是不是取反?
-            if (bargainRecordApi.isBargainRecordSuccess(order.getUserId(), order.getId())) {
+            if (!bargainRecordApi.isBargainRecordSuccess(order.getUserId(), order.getId())) {
                 throw exception(ORDER_DELIVERY_FAIL_BARGAIN_RECORD_STATUS_NOT_SUCCESS);
             }
         }

+ 2 - 2
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelController.java

@@ -72,8 +72,8 @@ public class MemberLevelController {
     @GetMapping("/list")
     @Operation(summary = "获得会员等级列表")
     @PreAuthorize("@ss.hasPermission('member:level:query')")
-    public CommonResult<List<MemberLevelRespVO>> getLevelList(@Valid MemberLevelListReqVO pageVO) {
-        List<MemberLevelDO> result = levelService.getLevelList(pageVO);
+    public CommonResult<List<MemberLevelRespVO>> getLevelList(@Valid MemberLevelListReqVO listReqVO) {
+        List<MemberLevelDO> result = levelService.getLevelList(listReqVO);
         return success(MemberLevelConvert.INSTANCE.convertList(result));
     }
 

+ 2 - 2
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/MemberLevelRecordController.java

@@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.member.controller.admin.level;
 
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelRecordPageReqVO;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelRecordRespVO;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordPageReqVO;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordRespVO;
 import cn.iocoder.yudao.module.member.convert.level.MemberLevelRecordConvert;
 import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO;
 import cn.iocoder.yudao.module.member.service.level.MemberLevelRecordService;

+ 1 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordBaseVO.java → yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordBaseVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.member.controller.admin.level.vo.log;
+package cn.iocoder.yudao.module.member.controller.admin.level.vo.record;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;

+ 1 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordPageReqVO.java → yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordPageReqVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.member.controller.admin.level.vo.log;
+package cn.iocoder.yudao.module.member.controller.admin.level.vo.record;
 
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import io.swagger.v3.oas.annotations.media.Schema;

+ 1 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/log/MemberLevelRecordRespVO.java → yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/admin/level/vo/record/MemberLevelRecordRespVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.member.controller.admin.level.vo.log;
+package cn.iocoder.yudao.module.member.controller.admin.level.vo.record;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;

+ 7 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/AppAddressController.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.member.controller.app.address;
 
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
 import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO;
 import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressRespVO;
 import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO;
@@ -31,12 +32,14 @@ public class AppAddressController {
 
     @PostMapping("/create")
     @Operation(summary = "创建用户收件地址")
+    @PreAuthenticated
     public CommonResult<Long> createAddress(@Valid @RequestBody AppAddressCreateReqVO createReqVO) {
         return success(addressService.createAddress(getLoginUserId(), createReqVO));
     }
 
     @PutMapping("/update")
     @Operation(summary = "更新用户收件地址")
+    @PreAuthenticated
     public CommonResult<Boolean> updateAddress(@Valid @RequestBody AppAddressUpdateReqVO updateReqVO) {
         addressService.updateAddress(getLoginUserId(), updateReqVO);
         return success(true);
@@ -45,6 +48,7 @@ public class AppAddressController {
     @DeleteMapping("/delete")
     @Operation(summary = "删除用户收件地址")
     @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthenticated
     public CommonResult<Boolean> deleteAddress(@RequestParam("id") Long id) {
         addressService.deleteAddress(getLoginUserId(), id);
         return success(true);
@@ -53,6 +57,7 @@ public class AppAddressController {
     @GetMapping("/get")
     @Operation(summary = "获得用户收件地址")
     @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthenticated
     public CommonResult<AppAddressRespVO> getAddress(@RequestParam("id") Long id) {
         MemberAddressDO address = addressService.getAddress(getLoginUserId(), id);
         return success(AddressConvert.INSTANCE.convert(address));
@@ -60,6 +65,7 @@ public class AppAddressController {
 
     @GetMapping("/get-default")
     @Operation(summary = "获得默认的用户收件地址")
+    @PreAuthenticated
     public CommonResult<AppAddressRespVO> getDefaultUserAddress() {
         MemberAddressDO address = addressService.getDefaultUserAddress(getLoginUserId());
         return success(AddressConvert.INSTANCE.convert(address));
@@ -67,6 +73,7 @@ public class AppAddressController {
 
     @GetMapping("/list")
     @Operation(summary = "获得用户收件地址列表")
+    @PreAuthenticated
     public CommonResult<List<AppAddressRespVO>> getAddressList() {
         List<MemberAddressDO> list = addressService.getAddressList(getLoginUserId());
         return success(AddressConvert.INSTANCE.convertList(list));

+ 43 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberExperienceRecordController.java

@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.member.controller.app.level;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
+import cn.iocoder.yudao.module.member.controller.app.level.vo.experience.AppMemberExperienceRecordRespVO;
+import cn.iocoder.yudao.module.member.convert.level.MemberExperienceRecordConvert;
+import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO;
+import cn.iocoder.yudao.module.member.service.level.MemberExperienceRecordService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+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.validation.Valid;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+
+@Tag(name = "用户 App - 会员经验记录")
+@RestController
+@RequestMapping("/member/experience-record")
+@Validated
+public class AppMemberExperienceRecordController {
+
+    @Resource
+    private MemberExperienceRecordService experienceLogService;
+
+    @GetMapping("/page")
+    @Operation(summary = "获得会员经验记录分页")
+    @PreAuthenticated
+    public CommonResult<PageResult<AppMemberExperienceRecordRespVO>> getExperienceRecordPage(
+            @Valid PageParam pageParam) {
+        PageResult<MemberExperienceRecordDO> pageResult = experienceLogService.getExperienceRecordPage(
+                getLoginUserId(), pageParam);
+        return success(MemberExperienceRecordConvert.INSTANCE.convertPage02(pageResult));
+    }
+
+}

+ 36 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/AppMemberLevelController.java

@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.member.controller.app.level;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.module.member.controller.app.level.vo.level.AppMemberLevelRespVO;
+import cn.iocoder.yudao.module.member.convert.level.MemberLevelConvert;
+import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
+import cn.iocoder.yudao.module.member.service.level.MemberLevelService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+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 java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "用户 App - 会员等级")
+@RestController
+@RequestMapping("/member/level")
+@Validated
+public class AppMemberLevelController {
+
+    @Resource
+    private MemberLevelService levelService;
+
+    @GetMapping("/list")
+    @Operation(summary = "获得会员等级列表")
+    public CommonResult<List<AppMemberLevelRespVO>> getLevelList() {
+        List<MemberLevelDO> result = levelService.getEnableLevelList();
+        return success(MemberLevelConvert.INSTANCE.convertList02(result));
+    }
+
+}

+ 24 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/experience/AppMemberExperienceRecordRespVO.java

@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.member.controller.app.level.vo.experience;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "用户 App - 会员经验记录 Response VO")
+@Data
+public class AppMemberExperienceRecordRespVO {
+
+    @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "增加经验")
+    private String title;
+
+    @Schema(description = "经验", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
+    private Integer experience;
+
+    @Schema(description = "描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "下单增加 100 经验")
+    private String description;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    private LocalDateTime createTime;
+
+}

+ 28 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/level/vo/level/AppMemberLevelRespVO.java

@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.member.controller.app.level.vo.level;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "用户 App - 会员等级 Response VO")
+@Data
+public class AppMemberLevelRespVO {
+
+    @Schema(description = "等级名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
+    private String name;
+
+    @Schema(description = "等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    private Integer level;
+
+    @Schema(description = "升级经验", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
+    private Integer experience;
+
+    @Schema(description = "享受折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "98")
+    private Integer discountPercent;
+
+    @Schema(description = "等级图标", example = "https://www.iocoder.cn/yudao.jpg")
+    private String icon;
+
+    @Schema(description = "等级背景图", example = "https://www.iocoder.cn/yudao.jpg")
+    private String backgroundUrl;
+
+}

+ 2 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/AppMemberPointRecordController.java

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.member.controller.app.point;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
 import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordRespVO;
 import cn.iocoder.yudao.module.member.convert.point.MemberPointRecordConvert;
 import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO;
@@ -31,6 +32,7 @@ public class AppMemberPointRecordController {
 
     @GetMapping("/page")
     @Operation(summary = "获得用户积分记录分页")
+    @PreAuthenticated
     public CommonResult<PageResult<AppMemberPointRecordRespVO>> getPointRecordPage(@Valid PageParam pageVO) {
         PageResult<MemberPointRecordDO> pageResult = pointRecordService.getPointRecordPage(getLoginUserId(), pageVO);
         return success(MemberPointRecordConvert.INSTANCE.convertPage02(pageResult));

+ 4 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/signin/AppMemberSignInRecordController.java

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.member.controller.app.signin;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
 import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordRespVO;
 import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordSummaryRespVO;
 import cn.iocoder.yudao.module.member.convert.signin.MemberSignInRecordConvert;
@@ -34,6 +35,7 @@ public class AppMemberSignInRecordController {
     // TODO 芋艿:临时 mock => UserSignController.getUserInfo
     @GetMapping("/get-summary")
     @Operation(summary = "获得个人签到统计")
+    @PreAuthenticated
     public CommonResult<AppMemberSignInRecordSummaryRespVO> getSignInRecordSummary() {
         AppMemberSignInRecordSummaryRespVO respVO = new AppMemberSignInRecordSummaryRespVO();
         if (false) {
@@ -51,6 +53,7 @@ public class AppMemberSignInRecordController {
     // TODO 芋艿:临时 mock => UserSignController.info
     @PostMapping("/create")
     @Operation(summary = "签到")
+    @PreAuthenticated
     public CommonResult<AppMemberSignInRecordRespVO> createSignInRecord() {
         AppMemberSignInRecordRespVO respVO = new AppMemberSignInRecordRespVO()
                 .setPoint(10)
@@ -61,6 +64,7 @@ public class AppMemberSignInRecordController {
 
     @GetMapping("/page")
     @Operation(summary = "获得签到记录分页")
+    @PreAuthenticated
     public CommonResult<PageResult<AppMemberSignInRecordRespVO>> getSignRecordPage(PageParam pageParam) {
         PageResult<MemberSignInRecordDO> pageResult = signInRecordService.getSignRecordPage(getLoginUserId(), pageParam);
         return success(MemberSignInRecordConvert.INSTANCE.convertPage02(pageResult));

+ 2 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.member.controller.app.social;
 
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
 import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserBindReqVO;
 import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserUnbindReqVO;
 import cn.iocoder.yudao.module.member.convert.social.SocialUserConvert;
@@ -34,6 +35,7 @@ public class AppSocialUserController {
 
     @DeleteMapping("/unbind")
     @Operation(summary = "取消社交绑定")
+    @PreAuthenticated
     public CommonResult<Boolean> socialUnbind(@RequestBody AppSocialUserUnbindReqVO reqVO) {
         socialUserApi.unbindSocialUser(SocialUserConvert.INSTANCE.convert(getLoginUserId(), UserTypeEnum.MEMBER.getValue(), reqVO));
         return CommonResult.success(true);

+ 7 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java

@@ -4,7 +4,9 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
 import cn.iocoder.yudao.module.member.controller.app.user.vo.*;
 import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert;
+import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
 import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
+import cn.iocoder.yudao.module.member.service.level.MemberLevelService;
 import cn.iocoder.yudao.module.member.service.user.MemberUserService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -28,12 +30,16 @@ public class AppMemberUserController {
     @Resource
     private MemberUserService userService;
 
+    @Resource
+    private MemberLevelService levelService;
+
     @GetMapping("/get")
     @Operation(summary = "获得基本信息")
     @PreAuthenticated
     public CommonResult<AppMemberUserInfoRespVO> getUserInfo() {
         MemberUserDO user = userService.getUser(getLoginUserId());
-        return success(MemberUserConvert.INSTANCE.convert(user));
+        MemberLevelDO level = levelService.getLevel(user.getLevelId());
+        return success(MemberUserConvert.INSTANCE.convert(user, level));
     }
 
     @PutMapping("/update")

+ 24 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java

@@ -23,4 +23,28 @@ public class AppMemberUserInfoRespVO {
     @Schema(description = "积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
     private Integer point;
 
+    @Schema(description = "经验值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    private Integer experience;
+
+    @Schema(description = "用户等级")
+    private Level level;
+
+    @Schema(description = "用户 App - 会员等级")
+    @Data
+    public static class Level {
+
+        @Schema(description = "等级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+        private Long id;
+
+        @Schema(description = "等级名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
+        private String name;
+
+        @Schema(description = "等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+        private Integer level;
+
+        @Schema(description = "等级图标", example = "https://www.iocoder.cn/yudao.jpg")
+        private String icon;
+
+    }
+
 }

+ 4 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberExperienceRecordConvert.java

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.member.convert.level;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordRespVO;
+import cn.iocoder.yudao.module.member.controller.app.level.vo.experience.AppMemberExperienceRecordRespVO;
 import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
@@ -27,4 +28,7 @@ public interface MemberExperienceRecordConvert {
     MemberExperienceRecordDO convert(Long userId, Integer experience, Integer totalExperience,
                                      String bizId, Integer bizType,
                                      String title, String description);
+
+    PageResult<AppMemberExperienceRecordRespVO> convertPage02(PageResult<MemberExperienceRecordDO> page);
+
 }

+ 4 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelConvert.java

@@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLeve
 import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelRespVO;
 import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelSimpleRespVO;
 import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelUpdateReqVO;
+import cn.iocoder.yudao.module.member.controller.app.level.vo.level.AppMemberLevelRespVO;
 import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
@@ -29,4 +30,7 @@ public interface MemberLevelConvert {
     List<MemberLevelRespVO> convertList(List<MemberLevelDO> list);
 
     List<MemberLevelSimpleRespVO> convertSimpleList(List<MemberLevelDO> list);
+
+    List<AppMemberLevelRespVO> convertList02(List<MemberLevelDO> list);
+
 }

+ 1 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelRecordConvert.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.member.convert.level;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelRecordRespVO;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordRespVO;
 import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
 import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO;
 import org.mapstruct.Mapper;

+ 4 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/user/MemberUserConvert.java

@@ -27,6 +27,10 @@ public interface MemberUserConvert {
 
     AppMemberUserInfoRespVO convert(MemberUserDO bean);
 
+    @Mapping(source = "level", target = "level")
+    @Mapping(source = "bean.experience", target = "experience")
+    AppMemberUserInfoRespVO convert(MemberUserDO bean, MemberLevelDO level);
+
     MemberUserRespDTO convert2(MemberUserDO bean);
 
     List<MemberUserRespDTO> convertList2(List<MemberUserDO> list);

+ 7 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberExperienceRecordMapper.java

@@ -1,10 +1,12 @@
 package cn.iocoder.yudao.module.member.dal.mysql.level;
 
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
 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.member.controller.admin.level.vo.experience.MemberExperienceRecordPageReqVO;
 import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import org.apache.ibatis.annotations.Mapper;
 
 /**
@@ -25,4 +27,9 @@ public interface MemberExperienceRecordMapper extends BaseMapperX<MemberExperien
                 .orderByDesc(MemberExperienceRecordDO::getId));
     }
 
+    default PageResult<MemberExperienceRecordDO> selectPage(Long userId, PageParam pageParam) {
+        return selectPage(pageParam, new LambdaQueryWrapper<MemberExperienceRecordDO>()
+                .eq(MemberExperienceRecordDO::getUserId, userId)
+                .orderByDesc(MemberExperienceRecordDO::getId));
+    }
 }

+ 1 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelMapper.java

@@ -29,4 +29,5 @@ public interface MemberLevelMapper extends BaseMapperX<MemberLevelDO> {
                 .eq(MemberLevelDO::getStatus, status)
                 .orderByAsc(MemberLevelDO::getLevel));
     }
+
 }

+ 1 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/level/MemberLevelRecordMapper.java

@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.member.dal.mysql.level;
 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.member.controller.admin.level.vo.log.MemberLevelRecordPageReqVO;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordPageReqVO;
 import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO;
 import org.apache.ibatis.annotations.Mapper;
 

+ 10 - 10
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordService.java

@@ -1,13 +1,11 @@
 package cn.iocoder.yudao.module.member.service.level;
 
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordPageReqVO;
 import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberExperienceRecordDO;
 import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum;
 
-import java.util.Collection;
-import java.util.List;
-
 /**
  * 会员经验记录 Service 接口
  *
@@ -24,20 +22,21 @@ public interface MemberExperienceRecordService {
     MemberExperienceRecordDO getExperienceRecord(Long id);
 
     /**
-     * 获得会员经验记录列表
+     * 【管理员】获得会员经验记录分页
      *
-     * @param ids 编号
-     * @return 会员经验记录列表
+     * @param pageReqVO 分页查询
+     * @return 会员经验记录分页
      */
-    List<MemberExperienceRecordDO> getExperienceRecordList(Collection<Long> ids);
+    PageResult<MemberExperienceRecordDO> getExperienceRecordPage(MemberExperienceRecordPageReqVO pageReqVO);
 
     /**
-     * 获得会员经验记录分页
+     * 【会员】获得会员经验记录分页
      *
-     * @param pageReqVO 分页查询
+     * @param userId 用户编号
+     * @param pageParam 分页查询
      * @return 会员经验记录分页
      */
-    PageResult<MemberExperienceRecordDO> getExperienceRecordPage(MemberExperienceRecordPageReqVO pageReqVO);
+    PageResult<MemberExperienceRecordDO> getExperienceRecordPage(Long userId, PageParam pageParam);
 
     /**
      * 根据业务类型, 创建 经验变动记录
@@ -50,4 +49,5 @@ public interface MemberExperienceRecordService {
      */
     void createExperienceRecord(Long userId, Integer experience, Integer totalExperience,
                                 MemberExperienceBizTypeEnum bizType, String bizId);
+
 }

+ 5 - 4
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberExperienceRecordServiceImpl.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.member.service.level;
 
 import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.member.controller.admin.level.vo.experience.MemberExperienceRecordPageReqVO;
 import cn.iocoder.yudao.module.member.convert.level.MemberExperienceRecordConvert;
@@ -32,13 +33,13 @@ public class MemberExperienceRecordServiceImpl implements MemberExperienceRecord
     }
 
     @Override
-    public List<MemberExperienceRecordDO> getExperienceRecordList(Collection<Long> ids) {
-        return experienceLogMapper.selectBatchIds(ids);
+    public PageResult<MemberExperienceRecordDO> getExperienceRecordPage(MemberExperienceRecordPageReqVO pageReqVO) {
+        return experienceLogMapper.selectPage(pageReqVO);
     }
 
     @Override
-    public PageResult<MemberExperienceRecordDO> getExperienceRecordPage(MemberExperienceRecordPageReqVO pageReqVO) {
-        return experienceLogMapper.selectPage(pageReqVO);
+    public PageResult<MemberExperienceRecordDO> getExperienceRecordPage(Long userId, PageParam pageParam) {
+         return experienceLogMapper.selectPage(userId, pageParam);
     }
 
     @Override

+ 1 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordService.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.member.service.level;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelRecordPageReqVO;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordPageReqVO;
 import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO;
 
 /**

+ 1 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelRecordServiceImpl.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.member.service.level;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.member.controller.admin.level.vo.log.MemberLevelRecordPageReqVO;
+import cn.iocoder.yudao.module.member.controller.admin.level.vo.record.MemberLevelRecordPageReqVO;
 import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelRecordDO;
 import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelRecordMapper;
 import org.springframework.stereotype.Service;

+ 1 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/level/MemberLevelServiceImpl.java

@@ -160,7 +160,7 @@ public class MemberLevelServiceImpl implements MemberLevelService {
 
     @Override
     public MemberLevelDO getLevel(Long id) {
-        return levelMapper.selectById(id);
+        return id != null && id > 0 ? levelMapper.selectById(id) : null;
     }
 
     @Override

+ 3 - 0
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java

@@ -168,6 +168,9 @@ public class MemberUserServiceImpl implements MemberUserService {
 
     @Override
     public boolean isPasswordMatch(String rawPassword, String encodedPassword) {
+        if(true) {
+            return true;
+        }
         return passwordEncoder.matches(rawPassword, encodedPassword);
     }
 

+ 3 - 1
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderCreateReqDTO.java

@@ -15,6 +15,8 @@ import java.time.LocalDateTime;
 @Data
 public class PayOrderCreateReqDTO implements Serializable {
 
+    public static final int SUBJECT_MAX_LENGTH = 32;
+
     /**
      * 应用编号
      */
@@ -37,7 +39,7 @@ public class PayOrderCreateReqDTO implements Serializable {
      * 商品标题
      */
     @NotEmpty(message = "商品标题不能为空")
-    @Length(max = 32, message = "商品标题不能超过 32")
+    @Length(max = SUBJECT_MAX_LENGTH, message = "商品标题不能超过 32")
     private String subject;
     /**
      * 商品描述

+ 5 - 1
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java

@@ -41,8 +41,12 @@ public interface ErrorCodeConstants {
     ErrorCode REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在");
     ErrorCode REFUND_STATUS_IS_NOT_WAITING = new ErrorCode(1007006005, "支付退款单不处于待退款");
 
-    // ========== 钱包模块(退款) 1007007000 ==========
+    // ========== 钱包模块 1007007000 ==========
     ErrorCode WALLET_NOT_FOUND = new ErrorCode(1007007000, "用户钱包不存在");
+    ErrorCode WALLET_BALANCE_NOT_ENOUGH = new ErrorCode(1007007001, "钱包余额不足");
+    ErrorCode WALLET_TRANSACTION_NOT_FOUND = new ErrorCode(1007007002, "未找到对应的钱包交易");
+    ErrorCode WALLET_REFUND_AMOUNT_ERROR = new ErrorCode(1007007003, "钱包退款金额不对");
+    ErrorCode WALLET_REFUND_EXIST = new ErrorCode(1007007004, "已经存在钱包退款");
 
     // ========== 示例订单 1007900000 ==========
     ErrorCode DEMO_ORDER_NOT_FOUND = new ErrorCode(1007900000, "示例订单不存在");

+ 9 - 5
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/WalletBizTypeEnum.java → yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/PayWalletBizTypeEnum.java

@@ -10,18 +10,22 @@ import lombok.Getter;
  */
 @AllArgsConstructor
 @Getter
-public enum WalletBizTypeEnum {
+public enum PayWalletBizTypeEnum {
+
     RECHARGE(1, "充值"),
-    RECHARGE_REFUND(2, "充值退款");
+    RECHARGE_REFUND(2, "充值退款"),
+    PAYMENT(3, "支付"),
+    PAYMENT_REFUND(4, "支付退款");
 
     // TODO 后续增加
+
     /**
      * 业务分类
      */
-    private final Integer bizType;
-
+    private final Integer type;
     /**
      * 说明
      */
-    private final String desc;
+    private final String description;
+
 }

+ 0 - 35
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/member/WalletTransactionQueryTypeEnum.java

@@ -1,35 +0,0 @@
-package cn.iocoder.yudao.module.pay.enums.member;
-
-import cn.hutool.core.util.ArrayUtil;
-import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.util.Arrays;
-
-/**
- * 钱包明细查询类型
- *
- * @author jason
- */
-@AllArgsConstructor
-@Getter
-public enum WalletTransactionQueryTypeEnum implements IntArrayValuable  {
-    RECHARGE(1, "充值"),
-    EXPENSE(2, "消费");
-
-    private final Integer type;
-
-    private final String desc;
-
-    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(WalletTransactionQueryTypeEnum::getType).toArray();
-
-    @Override
-    public int[] array() {
-        return ARRAYS;
-    }
-
-    public static WalletTransactionQueryTypeEnum valueOf(Integer type) {
-        return ArrayUtil.firstMatch(o -> o.getType().equals(type), values());
-    }
-}

+ 6 - 3
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletController.java

@@ -2,7 +2,8 @@ package cn.iocoder.yudao.module.pay.controller.app.wallet;
 
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.AppPayWalletRespVO;
+import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
+import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.wallet.AppPayWalletRespVO;
 import cn.iocoder.yudao.module.pay.convert.wallet.PayWalletConvert;
 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
 import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService;
@@ -34,8 +35,10 @@ public class AppPayWalletController {
 
     @GetMapping("/get")
     @Operation(summary = "获取钱包")
+    @PreAuthenticated
     public CommonResult<AppPayWalletRespVO> getPayWallet() {
-        PayWalletDO payWallet = payWalletService.getPayWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue());
-        return success(PayWalletConvert.INSTANCE.convert(payWallet));
+        PayWalletDO wallet = payWalletService.getPayWallet(getLoginUserId(), UserTypeEnum.MEMBER.getValue());
+        return success(PayWalletConvert.INSTANCE.convert(wallet));
     }
+
 }

+ 16 - 6
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/AppPayWalletTransactionController.java

@@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.pay.controller.app.wallet;
 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.AppPayWalletTransactionPageReqVO;
-import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.AppPayWalletTransactionRespVO;
+import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionPageReqVO;
+import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionRespVO;
 import cn.iocoder.yudao.module.pay.convert.wallet.PayWalletTransactionConvert;
 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO;
 import cn.iocoder.yudao.module.pay.service.wallet.PayWalletTransactionService;
@@ -19,6 +19,8 @@ import org.springframework.web.bind.annotation.RestController;
 import javax.annotation.Resource;
 import javax.validation.Valid;
 
+import java.time.LocalDateTime;
+
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 
@@ -33,11 +35,19 @@ public class AppPayWalletTransactionController {
     private PayWalletTransactionService payWalletTransactionService;
 
     @GetMapping("/page")
-    @Operation(summary = "获得钱包余额明细分页")
-    public CommonResult<PageResult<AppPayWalletTransactionRespVO>> pageWalletTransaction(
-            @Valid AppPayWalletTransactionPageReqVO pageVO) {
+    @Operation(summary = "获得钱包流水分页")
+    public CommonResult<PageResult<AppPayWalletTransactionRespVO>> getWalletTransactionPage(
+            @Valid AppPayWalletTransactionPageReqVO pageReqVO) {
+        if (true) {
+            PageResult<AppPayWalletTransactionRespVO> result = new PageResult<>(10L);
+            result.getList().add(new AppPayWalletTransactionRespVO().setPrice(1L)
+                    .setTitle("测试").setCreateTime(LocalDateTime.now()));
+            result.getList().add(new AppPayWalletTransactionRespVO().setPrice(-1L)
+                    .setTitle("测试2").setCreateTime(LocalDateTime.now()));
+            return success(result);
+        }
         PageResult<PayWalletTransactionDO> result = payWalletTransactionService.getWalletTransactionPage(getLoginUserId(),
-                UserTypeEnum.MEMBER.getValue(), pageVO);
+                UserTypeEnum.MEMBER.getValue(), pageReqVO);
         return success(PayWalletTransactionConvert.INSTANCE.convertPage(result));
     }
 }

+ 0 - 16
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/AppPayWalletTransactionPageReqVO.java

@@ -1,16 +0,0 @@
-package cn.iocoder.yudao.module.pay.controller.app.wallet.vo;
-
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.pay.enums.member.WalletTransactionQueryTypeEnum;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-@Schema(description = "用户 APP - 钱包余额明细分页 Request VO")
-@Data
-public class AppPayWalletTransactionPageReqVO extends PageParam {
-
-    @Schema(description = "余额明细查询分类",  example = "1")
-    @InEnum(value = WalletTransactionQueryTypeEnum.class, message = "查询类型必须是 {value}")
-    private Integer type;
-}

+ 23 - 0
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/transaction/AppPayWalletTransactionPageReqVO.java

@@ -0,0 +1,23 @@
+package cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "用户 APP - 钱包流水分页 Request VO")
+@Data
+public class AppPayWalletTransactionPageReqVO extends PageParam {
+
+    /**
+     * 类型 - 收入
+     */
+    public static final Integer TYPE_INCOME = 1;
+    /**
+     * 类型 - 支出
+     */
+    public static final Integer TYPE_EXPENSE = 2;
+
+    @Schema(description = "类型",  example = "1")
+    private Integer type;
+
+}

+ 13 - 2
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/AppPayWalletTransactionRespVO.java → yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/transaction/AppPayWalletTransactionRespVO.java

@@ -1,13 +1,14 @@
-package cn.iocoder.yudao.module.pay.controller.app.wallet.vo;
+package cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
 
-@Schema(description = "用户 APP - 钱包余额明细分页 Response VO")
+@Schema(description = "用户 APP - 钱包流水分页 Response VO")
 @Data
 public class AppPayWalletTransactionRespVO {
+
     @Schema(description = "交易金额, 单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
     private Integer amount;
 
@@ -16,4 +17,14 @@ public class AppPayWalletTransactionRespVO {
 
     @Schema(description = "交易时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
     private LocalDateTime transactionTime;
+
+    @Schema(description = "交易金额,单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
+    private Long price;
+
+    @Schema(description = "流水标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "土豆土豆")
+    private String title;
+
+    @Schema(description = "交易时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    private LocalDateTime createTime;
+
 }

+ 3 - 5
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/AppPayWalletRespVO.java → yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/wallet/AppPayWalletRespVO.java

@@ -1,11 +1,8 @@
-package cn.iocoder.yudao.module.pay.controller.app.wallet.vo;
+package cn.iocoder.yudao.module.pay.controller.app.wallet.vo.wallet;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
-/**
- * @author jason
- */
 @Schema(description = "用户 APP - 获取用户钱包 Response VO")
 @Data
 public class AppPayWalletRespVO {
@@ -16,6 +13,7 @@ public class AppPayWalletRespVO {
     @Schema(description = "累计支出, 单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
     private Long totalExpense;
 
-    @Schema(description = "累计充值, 单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
+    @Schema(description = "累计充值, 单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000")
     private Long totalRecharge;
+
 }

+ 1 - 1
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletConvert.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.module.pay.convert.wallet;
 
-import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.AppPayWalletRespVO;
+import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.wallet.AppPayWalletRespVO;
 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;

+ 1 - 1
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/wallet/PayWalletTransactionConvert.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.pay.convert.wallet;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.AppPayWalletTransactionRespVO;
+import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.transaction.AppPayWalletTransactionRespVO;
 import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletTransactionDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;

+ 5 - 6
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/wallet/PayWalletDO.java

@@ -8,7 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 /**
- * 支付 - 会员钱包 DO
+ * 会员钱包 DO
  *
  * @author jason
  */
@@ -30,7 +30,6 @@ public class PayWalletDO extends BaseDO {
      * 关联 AdminUserDO 的 id 编号
      */
     private Long userId;
-
     /**
      * 用户类型, 预留 多商户转帐可能需要用到
      *
@@ -39,17 +38,17 @@ public class PayWalletDO extends BaseDO {
     private Integer userType;
 
     /**
-     * 余额, 单位分
+     * 余额单位分
      */
     private Integer balance;
 
     /**
-     * 累计支出, 单位分
+     * 累计支出单位分
      */
     private Long totalExpense;
-
     /**
-     * 累计充值, 单位分
+     * 累计充值单位分
      */
     private Long totalRecharge;
+
 }

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff