Bläddra i källkod

Merge branch 'dev/2024/0607/update-app-Y' of Harper/feifan-backend-zx-app into master

合并生产环境的代码
Yangzw 10 månader sedan
förälder
incheckning
8772ae9409
100 ändrade filer med 2194 tillägg och 417 borttagningar
  1. 1 0
      feifan-framework/feifan-spring-boot-starter-mybatis/src/main/java/cn/newfeifan/mall/framework/mybatis/core/mapper/BaseMapperX.java
  2. 4 0
      feifan-framework/feifan-spring-boot-starter-web/src/main/java/cn/newfeifan/mall/framework/banner/core/BannerApplicationRunner.java
  3. 25 15
      feifan-module-distri/feifan-module-distri-api/src/main/java/cn/newfeifan/mall/module/distri/enums/CaclEnum.java
  4. 9 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/ptprofitlog/PtProfitLogController.java
  5. 0 2
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/ptprofitlog/vo/PtProfitLogPageReqVO.java
  6. 17 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/ptprofitlog/vo/PtProfitLogRespVO.java
  7. 8 1
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/ptprofitlog/vo/PtProfitLogSaveReqVO.java
  8. 9 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/sharepath/vo/SharePathRespVO.java
  9. 24 1
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/dataobject/ptprofitlog/PtProfitLogDO.java
  10. 69 11
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/mysql/ptprofitlog/PtProfitLogMapper.java
  11. 2 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/mysql/sharepath/SharePathMapper.java
  12. 9 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/duser/DuserServiceImpl.java
  13. 3 1
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/integral/IntegralService.java
  14. 5 2
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/integral/IntegralServiceImpl.java
  15. 6 2
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/partitioncrash/PartitionCrashService.java
  16. 16 3
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/partitioncrash/PartitionCrashServiceImpl.java
  17. 4 1
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/ptprofitlog/PtProfitLogService.java
  18. 29 2
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/ptprofitlog/PtProfitLogServiceImpl.java
  19. 50 0
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/sharepath/SharePathServiceImpl.java
  20. 9 3
      feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/socialstatus/SocialStatusServiceImpl.java
  21. 4 0
      feifan-module-distri/feifan-module-distri-biz/src/main/resources/mapper/sharepath/SharePathMapper.xml
  22. 12 0
      feifan-module-infra/feifan-module-infra-api/src/main/java/cn/newfeifan/mall/module/infra/enums/AppFileConstants.java
  23. 1 0
      feifan-module-infra/feifan-module-infra-api/src/main/java/cn/newfeifan/mall/module/infra/enums/ErrorCodeConstants.java
  24. 19 4
      feifan-module-infra/feifan-module-infra-biz/src/main/java/cn/newfeifan/mall/module/infra/controller/app/file/AppFileController.java
  25. 6 0
      feifan-module-mall/feifan-module-product-api/src/main/java/cn/newfeifan/mall/module/product/api/sku/dto/ProductSkuRespDTO.java
  26. 11 4
      feifan-module-mall/feifan-module-product-api/src/main/java/cn/newfeifan/mall/module/product/api/spu/dto/ProductSpuRespDTO.java
  27. 4 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spu/vo/ProductSkuRespVO.java
  28. 3 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spu/vo/ProductSkuSaveReqVO.java
  29. 6 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
  30. 8 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
  31. 9 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spu/vo/ProductSpuSaveReqVO.java
  32. 10 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java
  33. 21 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java
  34. 13 0
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/app/spu/vo/AppProductSpuRespVO.java
  35. 9 1
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/dataobject/sku/ProductSkuDO.java
  36. 22 11
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/dataobject/spu/ProductSpuDO.java
  37. 12 6
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/service/spu/ProductSpuServiceImpl.java
  38. 1 0
      feifan-module-mall/feifan-module-sale-api/src/main/java/cn/newfeifan/mall/module/sale/enums/ErrorCodeConstants.java
  39. 70 0
      feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/controller/admin/merchantapply/MerchantApplyController.java
  40. 92 0
      feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/controller/admin/merchantapply/vo/MerchantApplyPageReqVO.java
  41. 113 0
      feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/controller/admin/merchantapply/vo/MerchantApplyRespVO.java
  42. 87 0
      feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/controller/admin/merchantapply/vo/MerchantApplySaveReqVO.java
  43. 121 0
      feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/dal/dataobject/merchantapply/MerchantApplyDO.java
  44. 48 0
      feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/dal/mysql/merchantapply/MerchantApplyMapper.java
  45. 53 0
      feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/service/merchantapply/MerchantApplyService.java
  46. 71 0
      feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/service/merchantapply/MerchantApplyServiceImpl.java
  47. 3 1
      feifan-module-mall/feifan-module-trade-api/src/main/java/cn/newfeifan/mall/module/trade/enums/delivery/DeliveryTypeEnum.java
  48. 46 0
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/controller/app/order/AppTradeOrderController.java
  49. 1 1
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/controller/app/order/vo/AppTradeOrderCreateReqVO.java
  50. 1 3
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java
  51. 2 1
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java
  52. 10 1
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/controller/app/order/vo/AppTradeOrderSettlementRespVO.java
  53. 1 1
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/dal/dataobject/order/TradeOrderDO.java
  54. 7 0
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/dal/dataobject/order/TradeOrderItemDO.java
  55. 6 0
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/dal/mysql/order/TradeOrderMapper.java
  56. 2 2
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/aftersale/AfterSaleServiceImpl.java
  57. 10 0
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/order/TradeOrderUpdateService.java
  58. 351 144
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/order/TradeOrderUpdateServiceImpl.java
  59. 19 6
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/price/TradePriceServiceImpl.java
  60. 4 4
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/price/calculator/TradeDeliveryPriceCalculator.java
  61. 10 7
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/price/calculator/TradePriceCalculatorHelper.java
  62. 42 39
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/utils/wechat/WcChatMessageUtils.java
  63. 4 2
      feifan-module-member/feifan-module-member-api/src/main/java/cn/newfeifan/mall/module/member/api/address/MemberAddressApi.java
  64. 5 0
      feifan-module-member/feifan-module-member-api/src/main/java/cn/newfeifan/mall/module/member/enums/DictTypeConstants.java
  65. 5 1
      feifan-module-member/feifan-module-member-api/src/main/java/cn/newfeifan/mall/module/member/enums/ErrorCodeConstants.java
  66. 4 4
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/api/address/MemberAddressApiImpl.java
  67. 8 8
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/address/AppAddressController.java
  68. 3 1
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/address/vo/AppAddressBaseVO.java
  69. 24 6
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/AppAuthController.java
  70. 4 6
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java
  71. 4 0
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java
  72. 16 0
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/AppAuthMemberUserRespVO.java
  73. 18 0
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/AppAuthSelectUsernameLoginReqVO.java
  74. 4 9
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/AppAuthSmsLoginReqVO.java
  75. 28 0
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/AppAuthSmsRegisterReqVO.java
  76. 0 10
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/AppAuthSocialLoginReqVO.java
  77. 26 0
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/AppAuthSocialRegisterReqVO.java
  78. 1 1
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/SocialLoginValidateSmsCodeReqVO.java
  79. 8 0
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/user/AppMemberUserController.java
  80. 3 0
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java
  81. 5 1
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/dal/dataobject/address/MemberAddressDO.java
  82. 5 7
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/dal/dataobject/user/MemberUserDO.java
  83. 8 2
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/dal/mysql/address/MemberAddressMapper.java
  84. 9 0
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/dal/mysql/user/MemberUserMapper.java
  85. 8 4
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/address/AddressService.java
  86. 15 11
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/address/AddressServiceImpl.java
  87. 12 1
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/auth/MemberAuthService.java
  88. 119 37
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/auth/MemberAuthServiceImpl.java
  89. 33 4
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/user/MemberUserService.java
  90. 39 14
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/user/MemberUserServiceImpl.java
  91. 18 0
      feifan-module-member/feifan-module-member-biz/src/main/resources/mapper/user/MemberUserMapper.xml
  92. 5 0
      feifan-module-pay/feifan-module-pay-biz/src/main/java/cn/newfeifan/mall/module/pay/controller/admin/order/vo/PayOrderRespVO.java
  93. 7 3
      feifan-module-pay/feifan-module-pay-biz/src/main/java/cn/newfeifan/mall/module/pay/controller/app/order/AppPayOrderController.java
  94. 6 0
      feifan-module-pay/feifan-module-pay-biz/src/main/java/cn/newfeifan/mall/module/pay/dal/mysql/order/PayOrderExtensionMapper.java
  95. 18 0
      feifan-module-pay/feifan-module-pay-biz/src/main/java/cn/newfeifan/mall/module/pay/service/order/PayOrderService.java
  96. 45 2
      feifan-module-pay/feifan-module-pay-biz/src/main/java/cn/newfeifan/mall/module/pay/service/order/PayOrderServiceImpl.java
  97. 15 0
      feifan-module-system/feifan-module-system-api/src/main/java/cn/newfeifan/mall/module/system/api/social/SocialUserApi.java
  98. 11 0
      feifan-module-system/feifan-module-system-api/src/main/java/cn/newfeifan/mall/module/system/api/social/dto/SocialUserRespDTO.java
  99. 1 3
      feifan-module-system/feifan-module-system-api/src/main/java/cn/newfeifan/mall/module/system/enums/ErrorCodeConstants.java
  100. 10 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/api/social/SocialUserApiImpl.java

+ 1 - 0
feifan-framework/feifan-spring-boot-starter-mybatis/src/main/java/cn/newfeifan/mall/framework/mybatis/core/mapper/BaseMapperX.java

@@ -17,6 +17,7 @@ import com.github.yulichang.base.MPJBaseMapper;
 import com.github.yulichang.interfaces.MPJBaseJoin;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
 import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
 
 import java.util.Collection;
 import java.util.List;

+ 4 - 0
feifan-framework/feifan-spring-boot-starter-web/src/main/java/cn/newfeifan/mall/framework/banner/core/BannerApplicationRunner.java

@@ -18,6 +18,10 @@ public class BannerApplicationRunner implements ApplicationRunner {
 
     @Override
     public void run(ApplicationArguments args) {
+        ThreadUtil.execute(() -> {
+            ThreadUtil.sleep(1, TimeUnit.SECONDS); // 延迟 1 秒,保证输出到结尾
+            log.info("\n----------------------------------------------------------\n\t" + "项目启动成功!\n\t" + "----------------------------------------------------------");
+        });
        /* ThreadUtil.execute(() -> {
             ThreadUtil.sleep(1, TimeUnit.SECONDS); // 延迟 1 秒,保证输出到结尾
             log.info("\n----------------------------------------------------------\n\t" +

+ 25 - 15
feifan-module-distri/feifan-module-distri-api/src/main/java/cn/newfeifan/mall/module/distri/enums/CaclEnum.java

@@ -6,21 +6,26 @@ import lombok.Getter;
 @Getter
 @AllArgsConstructor
 public enum CaclEnum {
-    PLATFORM_SERVICE_FEE(1, "平台服务费"),
-    PLATFORM_REVENUE(2, "平台收益"),
-    RECOMMENDED_PERSON_QUOTA(3, "推荐人额度"),
-    DIRECT_REFERRAL_QUOTA(4, "直推人额度"),
-    TOGETHER_AWARD(5, "合赢奖"),
-    HIGH_QUOTA(6, "最高可以获得积分"),
-    SMALL_QUOTA_CRASH(7, "小区额度分配"),
-    AFTER_CRASH_CALC_PT_TOTAL_QUOTA(8, "碰撞后计算平台总收益"),
-    ORDER_PAY_INTEGRAL(9,"购物使用积分"),//支付了一部分积分作购物用
-    ORDER_REFUND_INTEGRAL(10,"订单退款,积分退回"),//订单已支付,用户退款申请通过,则退回商品项使用的积分
-    ORDER_INTEGRAL_UNFREEZE(11,"订单积分到账"),//购物收货7天后,冻结积分变为可用积分
-    ORDER_GET_FREEZE_INTEGRAL(12,"购物返积分"),//购物获得冻结积分
-    ORDER_CANCEL_BY_USER_REFUND_INTEGRAL(13,"取消订单,退回积分"),//用户手动取消未支付订单,退回购物使用的积分
-    ORDER_CANCEL_BY_SYSTEM_REFUND_INTEGRAL(14,"订单超时未支付,退回积分"),//订单超时未支付,退回购物使用的积分
-    ORDER_REFUND_CANCEL_INTEGRAL(15,"订单退款,减少冻结积分")//订单已支付,用户退款申请通过,则减少之前给用户的冻结积分
+    PLATFORM_TOTAL_ADD(0, "平台总收益","平台总收益"),
+    PLATFORM_SERVICE_FEE(1, "平台服务费","平台服务费"),
+    PLATFORM_REVENUE(2, "平台收益","平台收益"),
+    RECOMMENDED_PERSON_QUOTA(3, "直推奖获得","直推奖获得"),           //直推奖获得可用积分
+    DIRECT_REFERRAL_QUOTA(4, "购物获得","购物获得可用积分"),       //购物用户自得额度
+    TOGETHER_AWARD(5, "合赢奖","合赢奖"),
+    HIGH_QUOTA(6, "最高可以获得积分","最高可以获得积分"),
+    SMALL_QUOTA_CRASH(7, "合赢奖获得","小区额度分配"),
+    AFTER_CRASH_CALC_PT_TOTAL_QUOTA(8, "碰撞后计算平台总收益","碰撞后计算平台总收益"),
+    ORDER_PAY_INTEGRAL(9, "购物支付","购物使用积分进行支付"),      //购物使用积分进行支付
+    ORDER_REFUND_INTEGRAL(10, "退回退款返回","退回退款订单项,消费者支付的积分"),
+    AFTER_CRASH_CALC_PT_TOTAL_GROSS_QUOTA(12, "碰撞后计算平台收益","碰撞后计算平台收益"),
+    GROSS_PROFIT_BONUS_QUOTA_PERC_EXCEED_MAXIMUM_LIMIT(14, "合赢奖超额","合赢奖超额"),
+    GROSS_PROFIT_ANCESTOR_QUOTA_PERC_EXCEED_MAXIMUM_LIMIT(15, "直推奖超额","直推奖超额"),
+    ORDER_CANCEL_BY_USER_REFUND_INTEGRAL(16,"手动取消支付返回","取消订单,退回积分"),
+    ORDER_CANCEL_BY_SYSTEM_REFUND_INTEGRAL(17,"支付超时返回","订单超时未支付,退回积分"),
+    ORDER_PAY_INTEGRAL_ANCESTER(18, "直推奖获得","直推人购物,推荐人获得冻结积分"),//购物 上级直推人 获得积分
+    ORDER_REFUND_INTEGRAL_CONSUMER(19,"订单退款","订单退款,收回消费者获得的冻结积分"),
+    ORDER_REFUND_INTEGRAL_ANCESTER(20,"订单退款","订单退款,收回消费者的推荐人,获得的冻结积分"),
+    ORDER_PAY_INTEGRAL_CONSUMER(21, "购物获得","消费者购物,获得冻结积分"),//购物者本人 获得积分
     ;
 
     /**
@@ -32,6 +37,11 @@ public enum CaclEnum {
      */
     private final String name;
 
+    /**
+     * 描述
+     */
+    private final String mark;
+
     public static CaclEnum getCaclEnumByValue(int value) {
         for (CaclEnum caclEnum : CaclEnum.values()) {
             if (caclEnum.getType() == value) {

+ 9 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/ptprofitlog/PtProfitLogController.java

@@ -6,6 +6,7 @@ import cn.newfeifan.mall.framework.common.pojo.PageResult;
 import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
 import cn.newfeifan.mall.framework.excel.core.util.ExcelUtils;
 import cn.newfeifan.mall.framework.operatelog.core.annotations.OperateLog;
+import cn.newfeifan.mall.framework.security.core.annotations.PreAuthenticated;
 import cn.newfeifan.mall.module.distri.controller.app.ptprofitlog.vo.PtProfitLogPageReqVO;
 import cn.newfeifan.mall.module.distri.controller.app.ptprofitlog.vo.PtProfitLogRespVO;
 import cn.newfeifan.mall.module.distri.controller.app.ptprofitlog.vo.PtProfitLogSaveReqVO;
@@ -71,10 +72,18 @@ public class PtProfitLogController {
 
     @GetMapping("/page")
     @Operation(summary = "获得平台利润记录分页")
+    @PreAuthenticated
     public CommonResult<PageResult<PtProfitLogRespVO>> getPtProfitLogPage(@Valid PtProfitLogPageReqVO pageReqVO) {
         PageResult<PtProfitLogRespVO> pageResult = ptProfitLogService.getPtProfitLogPage(pageReqVO);
         return success(pageResult);
     }
+    @GetMapping("/getMaxAmountPage")
+    @Operation(summary = "获得峰值记录分页")
+    @PreAuthenticated
+    public CommonResult<PageResult<PtProfitLogRespVO>> getMaxAmountPage(@Valid PtProfitLogPageReqVO pageReqVO) {
+        PageResult<PtProfitLogRespVO> pageResult = ptProfitLogService.getMaxAmountPage(pageReqVO);
+        return success(pageResult);
+    }
 
     @GetMapping("/export-excel")
     @Operation(summary = "导出平台利润记录 Excel")

+ 0 - 2
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/ptprofitlog/vo/PtProfitLogPageReqVO.java

@@ -7,7 +7,6 @@ import lombok.EqualsAndHashCode;
 import lombok.ToString;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import javax.validation.constraints.NotNull;
 import java.time.LocalDateTime;
 
 import static cn.newfeifan.mall.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@@ -50,6 +49,5 @@ public class PtProfitLogPageReqVO extends PageParam {
     private String percentTemplate;
 
     @Schema(description = "是否冻结  true-冻结  false-可用")
-    @NotNull(message = "是否冻结不能为空")
     private Boolean isFreeze;
 }

+ 17 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/ptprofitlog/vo/PtProfitLogRespVO.java

@@ -59,4 +59,21 @@ public class PtProfitLogRespVO {
     @ExcelProperty("计算百分比模板")
     private String percentTemplate;
 
+    @Schema(description = "最大可用积分变化值")
+    private Long maxAvailablePointsAmount;
+
+    @Schema(description = "最大可用积分额度")
+    private Long afterMaxAvailablePointsAmount;
+
+    @Schema(description = "合赢奖超出额度")
+    private Long accumulatedQuotaAmount;
+
+    @Schema(description = "直推奖超出额度")
+    private Long ancestorQuotaAmount;
+
+    @Schema(description = "显示这条记录是由谁产生的用户名")
+    private String username;
+
+    @Schema(description = "产生积分的用户ID,例如:下订单的用户ID", example = "31502")
+    private Long generateUserId;
 }

+ 8 - 1
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/ptprofitlog/vo/PtProfitLogSaveReqVO.java

@@ -16,7 +16,14 @@ public class PtProfitLogSaveReqVO {
     @Schema(description = "收益类型 1:平台服务器费 2:平台收益 3用户下单返回毛利额度 4直推人额度 5合赢奖", example = "2")
     private Integer profitStatus;
 
-    @Schema(description = "用户ID , 只有收益类型为 3,4才有值", example = "6982")
+
+    /**
+     * 产生积分的用户ID,例如:下订单的用户ID
+     */
+    @Schema(description = "产生积分的用户ID", example = "6982")
+    private Long generateUserId;
+
+    @Schema(description = "积分变动的用户ID", example = "6982")
     private Long userId;
 
     @Schema(description = "订单Id", example = "26464")

+ 9 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/controller/app/sharepath/vo/SharePathRespVO.java

@@ -69,4 +69,13 @@ public class SharePathRespVO {
 
     @Schema(description = "后代人数")
     private Long descendantsCount;
+
+    @Schema(description = "最高可获取积分(峰值 / 最大值)")
+    private Long high_quota;
+
+    @Schema(description = "剩余的合赢奖额度 + 待确权直推奖")
+    private Long residueSocial;
+
+    @Schema(description = "用户名")
+    private String username;
 }

+ 24 - 1
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/dataobject/ptprofitlog/PtProfitLogDO.java

@@ -24,9 +24,15 @@ public class PtProfitLogDO extends BaseDO {
      */
     private Integer profitStatus;
     /**
-     * 用户ID , 只有收益类型为 3,4才有值
+     * 实际变动积分的用户ID , 只有收益类型为 3,4才有值
      */
     private Long userId;
+
+    /**
+     * 产生积分的用户ID,例如:下订单的用户ID
+     */
+    private Long generateUserId;
+
     /**
      * 订单Id
      */
@@ -61,5 +67,22 @@ public class PtProfitLogDO extends BaseDO {
      */
     private String percentTemplate;
 
+    /**
+     * 最大可用积分变化值
+     */
+    private Long maxAvailablePointsAmount;
+    /**
+     * 最大可用积分额度
+     */
+    private Long afterMaxAvailablePointsAmount;
+    /**
+     * 合赢奖超出额度
+     */
+    private Long accumulatedQuotaAmount;
+    /**
+     * 直推奖超出额度
+     */
+    private Long ancestorQuotaAmount;
+
 
 }

+ 69 - 11
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/mysql/ptprofitlog/PtProfitLogMapper.java

@@ -8,6 +8,13 @@ import cn.newfeifan.mall.module.distri.dal.dataobject.ptprofitlog.PtProfitLogDO;
 import org.apache.ibatis.annotations.Mapper;
 import cn.newfeifan.mall.module.distri.controller.app.ptprofitlog.vo.*;
 
+import java.util.Arrays;
+import java.util.List;
+
+import static cn.newfeifan.mall.module.distri.constant.DistriConstants.PT_ID;
+import static cn.newfeifan.mall.module.distri.enums.CaclEnum.*;
+import static cn.newfeifan.mall.module.distri.enums.CaclEnum.GROSS_PROFIT_ANCESTOR_QUOTA_PERC_EXCEED_MAXIMUM_LIMIT;
+
 /**
  * 平台利润记录 Mapper
  *
@@ -17,24 +24,75 @@ import cn.newfeifan.mall.module.distri.controller.app.ptprofitlog.vo.*;
 public interface PtProfitLogMapper extends BaseMapperX<PtProfitLogDO> {
 
     default PageResult<PtProfitLogDO> selectPage(PtProfitLogPageReqVO reqVO) {
+        //用户只能查看这些类型
+        List<Integer> profitStatus = null;
+
+        if (!reqVO.getIsFreeze()) {
+            //可用
+            profitStatus = Arrays.asList(
+                    RECOMMENDED_PERSON_QUOTA.getType(),
+                    DIRECT_REFERRAL_QUOTA.getType(),
+                    SMALL_QUOTA_CRASH.getType(),
+                    ORDER_PAY_INTEGRAL.getType(),
+                    ORDER_REFUND_INTEGRAL.getType(),
+                    ORDER_CANCEL_BY_USER_REFUND_INTEGRAL.getType(),
+                    ORDER_CANCEL_BY_SYSTEM_REFUND_INTEGRAL.getType()
+            );
+        } else {
+            //冻结
+            profitStatus = Arrays.asList(
+                    RECOMMENDED_PERSON_QUOTA.getType(),
+                    DIRECT_REFERRAL_QUOTA.getType(),
+                    ORDER_PAY_INTEGRAL_ANCESTER.getType(),
+                    ORDER_REFUND_INTEGRAL_CONSUMER.getType(),
+                    ORDER_REFUND_INTEGRAL_ANCESTER.getType(),
+                    ORDER_PAY_INTEGRAL_CONSUMER.getType());
+        }
+
+        if (!reqVO.getIsFreeze() && reqVO.getUserId().equals(PT_ID)) {
+            //平台账号可用
+            profitStatus = Arrays.asList(
+                    PLATFORM_TOTAL_ADD.getType(),
+                    PLATFORM_SERVICE_FEE.getType(),
+                    PLATFORM_REVENUE.getType(),
+                    AFTER_CRASH_CALC_PT_TOTAL_QUOTA.getType(),
+                    AFTER_CRASH_CALC_PT_TOTAL_GROSS_QUOTA.getType(),
+                    GROSS_PROFIT_BONUS_QUOTA_PERC_EXCEED_MAXIMUM_LIMIT.getType(),
+                    GROSS_PROFIT_ANCESTOR_QUOTA_PERC_EXCEED_MAXIMUM_LIMIT.getType()
+            );
+            reqVO.setUserId(null);
+        } else if (reqVO.getIsFreeze() && reqVO.getUserId().equals(PT_ID)) {
+            profitStatus = Arrays.asList(
+                    RECOMMENDED_PERSON_QUOTA.getType(),
+                    DIRECT_REFERRAL_QUOTA.getType(),
+                    SMALL_QUOTA_CRASH.getType(),
+                    ORDER_PAY_INTEGRAL.getType(),
+                    ORDER_REFUND_INTEGRAL.getType(),
+                    ORDER_CANCEL_BY_USER_REFUND_INTEGRAL.getType(),
+                    ORDER_CANCEL_BY_SYSTEM_REFUND_INTEGRAL.getType()
+            );
+            reqVO.setUserId(null);
+        }
+
         LambdaQueryWrapperX<PtProfitLogDO> queryWrapper = new LambdaQueryWrapperX<PtProfitLogDO>()
                 .eqIfPresent(PtProfitLogDO::getAmount, reqVO.getAmount())
                 .eqIfPresent(PtProfitLogDO::getAfterAmount, reqVO.getAfterAmount())
                 .eqIfPresent(PtProfitLogDO::getOrderId, reqVO.getOrderId())
                 .eqIfPresent(PtProfitLogDO::getPercentTemplate, reqVO.getPercentTemplate())
                 .eqIfPresent(PtProfitLogDO::getUserId, reqVO.getUserId())
+                .inIfPresent(PtProfitLogDO::getProfitStatus, profitStatus)
                 .orderByDesc(PtProfitLogDO::getCreateTime);
-        if(!reqVO.getIsFreeze()){
-            queryWrapper
-                    .isNotNull(PtProfitLogDO::getAmount)
-                    .ne(PtProfitLogDO::getAmount,0)
-            ;
-        }else{
-            queryWrapper
-                    .isNotNull(PtProfitLogDO::getFreezeAmount)
-                    .ne(PtProfitLogDO::getFreezeAmount,0)
-            ;
-        }
         return selectPage(reqVO, queryWrapper);
     }
+
+    default PageResult<PtProfitLogDO> getMaxAmountPage(PtProfitLogPageReqVO pageReqVO) {
+        List<Integer> profitStatus = Arrays.asList(
+                DIRECT_REFERRAL_QUOTA.getType(),
+                RECOMMENDED_PERSON_QUOTA.getType(),
+                SMALL_QUOTA_CRASH.getType());
+        return selectPage(pageReqVO, new LambdaQueryWrapperX<PtProfitLogDO>()
+                .eqIfPresent(PtProfitLogDO::getUserId, pageReqVO.getUserId())
+                .inIfPresent(PtProfitLogDO::getProfitStatus, profitStatus)
+                .orderByDesc(PtProfitLogDO::getCreateTime));
+    }
 }

+ 2 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/dal/mysql/sharepath/SharePathMapper.java

@@ -45,4 +45,6 @@ public interface SharePathMapper extends BaseMapperX<SharePathDO> {
 
     // 添加节点及其子节点的新祖先关系
     void addNewAncestors(@Param("nodeId") Long nodeId, @Param("newParentId") Long newParentId);
+
+    Long getAncestorIncreaseIntegralByUserId(@Param("userId") Long userId);
 }

+ 9 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/duser/DuserServiceImpl.java

@@ -10,6 +10,7 @@ import cn.newfeifan.mall.module.distri.dal.dataobject.socialstatus.SocialStatusD
 import cn.newfeifan.mall.module.distri.dal.mysql.orderpercentage.OrderPercentageMapper;
 import cn.newfeifan.mall.module.distri.enums.SocialStatusEnum;
 import cn.newfeifan.mall.module.distri.service.integral.IntegralService;
+import cn.newfeifan.mall.module.distri.service.orderpercentage.OrderPercentageService;
 import cn.newfeifan.mall.module.distri.service.ptprofitlog.PtProfitLogService;
 import cn.newfeifan.mall.module.distri.service.sharepath.SharePathService;
 import cn.newfeifan.mall.module.distri.service.socialstatus.SocialStatusService;
@@ -31,6 +32,7 @@ import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
 
 import cn.newfeifan.mall.module.distri.dal.mysql.duser.DuserMapper;
 
+import java.math.BigDecimal;
 import java.util.List;
 import java.util.Objects;
 
@@ -116,6 +118,9 @@ public class DuserServiceImpl implements DuserService {
     @Resource
     private SocialStatusService socialStatusService;
 
+    @Resource
+    private OrderPercentageService orderPercentageService;
+
     @Override
     public void hasUserAndCreat(SharePathSaveReqVO saveReqVO) {
         checkAndCreat(saveReqVO.getDescendant());
@@ -143,6 +148,10 @@ public class DuserServiceImpl implements DuserService {
         if (integral == null) {
             throw exception(INTEGRAL_NOT_EXISTS);
         }
+
+        OrderPercentageDO orderPercentageDO = orderPercentageService.queryStatus();
+        integral.setHighQuota(integral.getHighQuota() + new BigDecimal(orderPercentageDO.getBaseMaxQuota()).longValue());
+
         DuserInfoVO.DuserInfoVOBuilder duserInfoVOBuilder = DuserInfoVO.builder()
                 .integralDO(integral)
                 .descNo(sonsId.size());

+ 3 - 1
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/integral/IntegralService.java

@@ -65,13 +65,15 @@ public interface IntegralService {
     /**
      * 修改用户积分
      *
+     * @param generateUserId 导致产生积分变动的用户ID
      * @param userId 要修改积分的用户
      * @param caclEnum 导致积分变化的事件类型枚举
      * @param amount 用户积分变化金额,可为负数
      * @param freezeAmount 用户冻结积分变化金额,可为负数
      * @return 返回是否执行成功。执行失败,通常是就是用户积分不足,没积分抵扣
      */
-    Boolean updateUserIntegral(Long userId, CaclEnum caclEnum, Long amount, Long freezeAmount,
+    Boolean updateUserIntegral(Long generateUserId,//导致产生积分变动的用户ID
+            Long userId, CaclEnum caclEnum, Long amount, Long freezeAmount,
                                Long tradeOrderId,
                                String orderNum
                                );

+ 5 - 2
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/integral/IntegralServiceImpl.java

@@ -98,6 +98,7 @@ public class IntegralServiceImpl implements IntegralService {
      * add by Ben
      * 修改用户积分
      *
+     * @param generateUserId 要修改积分的用户
      * @param userId 要修改积分的用户
      * @param caclEnum 导致积分变化的事件类型枚举
      * @param amount 用户可用积分变化金额,可为负数
@@ -105,7 +106,8 @@ public class IntegralServiceImpl implements IntegralService {
      * @return 返回是否执行成功。执行失败,通常是就是用户积分不足,没积分抵扣
      */
     @Override
-    public Boolean updateUserIntegral(Long userId, CaclEnum caclEnum, Long amount, Long freezeAmount,
+    public Boolean updateUserIntegral(Long generateUserId,//导致产生积分变动的用户ID
+            Long userId, CaclEnum caclEnum, Long amount, Long freezeAmount,
                                       Long tradeOrderId,
                                       String OrderNum
                                       ) {
@@ -135,7 +137,8 @@ public class IntegralServiceImpl implements IntegralService {
             }
 
             //记录用户的积分变动日志
-            ptProfitLogService.addMessage(userId, caclEnum, amount, afterAmount,
+            ptProfitLogService.addMessage(generateUserId,//导致产生积分变动的用户ID
+                    userId, caclEnum, amount, afterAmount,
                     freezeAmount, afterFreezeAmount,null,tradeOrderId,OrderNum);
 
         }else if(effectRowNum<1){//如果钱包积分不足,不够抵扣

+ 6 - 2
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/partitioncrash/PartitionCrashService.java

@@ -1,11 +1,9 @@
 package cn.newfeifan.mall.module.distri.service.partitioncrash;
 
-import java.util.*;
 import javax.validation.*;
 import cn.newfeifan.mall.module.distri.controller.admin.partitioncrash.vo.*;
 import cn.newfeifan.mall.module.distri.dal.dataobject.partitioncrash.PartitionCrashDO;
 import cn.newfeifan.mall.framework.common.pojo.PageResult;
-import cn.newfeifan.mall.framework.common.pojo.PageParam;
 
 /**
  * 分区碰撞 Service 接口
@@ -52,4 +50,10 @@ public interface PartitionCrashService {
      */
     PageResult<PartitionCrashDO> getPartitionCrashPage(PartitionCrashPageReqVO pageReqVO);
 
+    /**
+     * 获取用户的剩余额度
+     * @param userId 用户编号
+     * @return 剩余额度
+     */
+    Long getResidueSocial(Long userId);
 }

+ 16 - 3
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/partitioncrash/PartitionCrashServiceImpl.java

@@ -1,19 +1,19 @@
 package cn.newfeifan.mall.module.distri.service.partitioncrash;
 
+import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
 import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.transaction.annotation.Transactional;
 
-import java.util.*;
 import cn.newfeifan.mall.module.distri.controller.admin.partitioncrash.vo.*;
 import cn.newfeifan.mall.module.distri.dal.dataobject.partitioncrash.PartitionCrashDO;
 import cn.newfeifan.mall.framework.common.pojo.PageResult;
-import cn.newfeifan.mall.framework.common.pojo.PageParam;
 import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
 
 import cn.newfeifan.mall.module.distri.dal.mysql.partitioncrash.PartitionCrashMapper;
 
+import java.util.List;
+
 import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.newfeifan.mall.module.distri.enums.ErrorCodeConstants.*;
 
@@ -71,4 +71,17 @@ public class PartitionCrashServiceImpl implements PartitionCrashService {
         return partitionCrashMapper.selectPage(pageReqVO);
     }
 
+    @Override
+    public Long getResidueSocial(Long userId) {
+        Long afterHitQuota = null;
+        List<PartitionCrashDO> partitionCrashDOS = partitionCrashMapper.selectList(new LambdaQueryWrapperX<PartitionCrashDO>()
+                .eq(PartitionCrashDO::getUserId, userId)
+                .orderByDesc(PartitionCrashDO::getCreateTime)
+        );
+        if(!partitionCrashDOS.isEmpty()){
+            afterHitQuota = partitionCrashDOS.get(0).getAfterHitQuota();
+        }
+        return afterHitQuota == null ? 0L : afterHitQuota;
+    }
+
 }

+ 4 - 1
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/ptprofitlog/PtProfitLogService.java

@@ -58,7 +58,9 @@ public interface PtProfitLogService {
     void saveBatch(List<PtProfitLogSaveReqVO> ptProfitLogSaveReqVOS);
 
     //记录用户的积分变动日志
-    void addMessage(Long userId, CaclEnum caclEnum, Long amount,
+    void addMessage(Long generateUserId,//导致产生积分变动的用户ID
+                    Long userId, //实际变动积分的用户ID
+                    CaclEnum caclEnum, Long amount,
                     Long afterAmount, Long freezeAmount,
                     Long afterFreezeAmount, String percentTemplate,
                     Long tradeOrderId,
@@ -68,4 +70,5 @@ public interface PtProfitLogService {
 
     String getTotalLog(List<Long> sonsId);
 
+    PageResult<PtProfitLogRespVO> getMaxAmountPage(PtProfitLogPageReqVO pageReqVO);
 }

+ 29 - 2
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/ptprofitlog/PtProfitLogServiceImpl.java

@@ -2,6 +2,7 @@ package cn.newfeifan.mall.module.distri.service.ptprofitlog;
 
 import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.newfeifan.mall.module.distri.enums.CaclEnum;
+import cn.newfeifan.mall.module.member.service.user.MemberUserService;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
@@ -20,6 +21,7 @@ import cn.newfeifan.mall.module.distri.dal.mysql.ptprofitlog.PtProfitLogMapper;
 
 import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.newfeifan.mall.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+import static cn.newfeifan.mall.module.distri.enums.CaclEnum.RECOMMENDED_PERSON_QUOTA;
 import static cn.newfeifan.mall.module.distri.enums.ErrorCodeConstants.*;
 
 /**
@@ -34,6 +36,9 @@ public class PtProfitLogServiceImpl implements PtProfitLogService {
     @Resource
     private PtProfitLogMapper ptProfitLogMapper;
 
+    @Resource
+    private MemberUserService memberUserService;
+
     @Override
     public Long createPtProfitLog(PtProfitLogSaveReqVO createReqVO) {
         // 插入
@@ -76,6 +81,24 @@ public class PtProfitLogServiceImpl implements PtProfitLogService {
         pageReqVO.setUserId(getLoginUserId());
         PageResult<PtProfitLogRespVO> result = BeanUtils.toBean(ptProfitLogMapper.selectPage(pageReqVO), PtProfitLogRespVO.class);
         for (PtProfitLogRespVO ptProfitLogRespVO : result.getList()) {
+            if (ptProfitLogRespVO.getProfitStatus().equals(RECOMMENDED_PERSON_QUOTA.getType()) ||
+                    ptProfitLogRespVO.getProfitStatus().equals(CaclEnum.ORDER_PAY_INTEGRAL_ANCESTER.getType()) ||
+                    ptProfitLogRespVO.getProfitStatus().equals(CaclEnum.ORDER_REFUND_INTEGRAL_ANCESTER.getType())) {
+                ptProfitLogRespVO.setUsername(memberUserService.getUser(ptProfitLogRespVO.getGenerateUserId()).getUsername());
+            }
+            ptProfitLogRespVO.setProfitStatusName(Objects.requireNonNull(CaclEnum.getCaclEnumByValue(ptProfitLogRespVO.getProfitStatus())).getName());
+        }
+        return result;
+    }
+
+    @Override
+    public PageResult<PtProfitLogRespVO> getMaxAmountPage(PtProfitLogPageReqVO pageReqVO) {
+        pageReqVO.setUserId(getLoginUserId());
+        PageResult<PtProfitLogRespVO> result = BeanUtils.toBean(ptProfitLogMapper.getMaxAmountPage(pageReqVO), PtProfitLogRespVO.class);
+        for (PtProfitLogRespVO ptProfitLogRespVO : result.getList()) {
+            if (ptProfitLogRespVO.getProfitStatus().equals(RECOMMENDED_PERSON_QUOTA.getType())) {
+                ptProfitLogRespVO.setUsername(memberUserService.getUser(ptProfitLogRespVO.getGenerateUserId()).getUsername());
+            }
             ptProfitLogRespVO.setProfitStatusName(Objects.requireNonNull(CaclEnum.getCaclEnumByValue(ptProfitLogRespVO.getProfitStatus())).getName());
         }
         return result;
@@ -89,6 +112,7 @@ public class PtProfitLogServiceImpl implements PtProfitLogService {
 
     /**
      * 添加一条用户积分日志消息
+     *
      * @param userId
      * @param caclEnum
      * @param amount
@@ -100,17 +124,20 @@ public class PtProfitLogServiceImpl implements PtProfitLogService {
      * @param OrderNum
      */
     @Override
-    public void addMessage(Long userId, CaclEnum caclEnum, Long amount, Long afterAmount,
+    public void addMessage(Long generateUserId,//导致产生积分变动的用户ID
+                           Long userId, //实际变动积分的用户ID
+                           CaclEnum caclEnum, Long amount, Long afterAmount,
                            Long freezeAmount, Long afterFreezeAmount,
                            String percentTemplate,
                            Long tradeOrderId,
                            String OrderNum
-                           ) {
+    ) {
         PtProfitLogSaveReqVO ptProfitLog = PtProfitLogSaveReqVO.builder()
                 .afterAmount(afterAmount)
                 .amount(amount)
                 .percentTemplate(percentTemplate)
                 .userId(userId)
+                .generateUserId(generateUserId)
                 .profitStatus(caclEnum.getType()).orderId(tradeOrderId).orderNo(OrderNum)
                 .freezeAmount(freezeAmount).afterFreezeAmount(afterFreezeAmount)
                 .build();

+ 50 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/sharepath/SharePathServiceImpl.java

@@ -4,11 +4,14 @@ import cn.newfeifan.mall.framework.common.pojo.PageParam;
 import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.newfeifan.mall.module.distri.controller.app.sharepath.vo.*;
 import cn.newfeifan.mall.module.distri.dal.dataobject.duser.DuserDO;
+import cn.newfeifan.mall.module.distri.dal.dataobject.integral.IntegralDO;
 import cn.newfeifan.mall.module.distri.dal.dataobject.orderpercentage.OrderPercentageDO;
 import cn.newfeifan.mall.module.distri.dal.dataobject.socialstatus.SocialStatusDO;
 import cn.newfeifan.mall.module.distri.dal.mysql.orderpercentage.OrderPercentageMapper;
 import cn.newfeifan.mall.module.distri.enums.SocialStatusEnum;
 import cn.newfeifan.mall.module.distri.service.duser.DuserService;
+import cn.newfeifan.mall.module.distri.service.integral.IntegralService;
+import cn.newfeifan.mall.module.distri.service.partitioncrash.PartitionCrashService;
 import cn.newfeifan.mall.module.distri.service.socialstatus.SocialStatusService;
 import cn.newfeifan.mall.module.member.dal.dataobject.user.MemberUserDO;
 import cn.newfeifan.mall.module.member.service.user.MemberUserService;
@@ -61,6 +64,12 @@ public class SharePathServiceImpl implements SharePathService {
     @Resource
     private OrderPercentageMapper orderPercentageMapper;
 
+    @Resource
+    private IntegralService integralService;
+
+    @Resource
+    private PartitionCrashService partitionCrashService;
+
 
     @Override
     public Long createSharePath(SharePathSaveReqVO createReqVO) {
@@ -148,6 +157,17 @@ public class SharePathServiceImpl implements SharePathService {
         if(ancestor != null) {
             ancestor.setAvatar(getAvatar(ancestor.getAncestor()));
             getSocialStatus(ancestor, ancestor.getAncestor());
+            //获取最大可用额度
+//            setHighQuota(ancestor, ancestor.getAncestor());
+
+            //获取团队数
+            Long descendantsCount = sharePathMapper.selectCount(new LambdaQueryWrapper<SharePathDO>()
+                    .eq(SharePathDO::getAncestor, ancestor.getAncestor())
+            );
+            ancestor.setDescendantsCount(descendantsCount);
+            ancestor.setResidueSocial(getResidueSocial(ancestor.getAncestor()));
+            //获取用户名
+            ancestor.setUsername(memberUserService.getUser(ancestor.getAncestor()).getUsername());
         }
 
         //获取团队成员
@@ -165,6 +185,14 @@ public class SharePathServiceImpl implements SharePathService {
                     .eq(SharePathDO::getAncestor, item.getDescendant())
             );
             item.setDescendantsCount(descendantsCount);
+
+            //获取最大可用额度
+//            setHighQuota(item, item.getDescendant());
+
+            //获取剩余碰撞额度 + 待确权直推奖
+            item.setResidueSocial(getResidueSocial(item.getDescendant()));
+            //获取用户名
+            item.setUsername(memberUserService.getUser(item.getDescendant()).getUsername());
         });
 
 
@@ -174,6 +202,28 @@ public class SharePathServiceImpl implements SharePathService {
                 .descendants(result).build();
     }
 
+    private Long getResidueSocial(Long userId){
+        if(!userId.equals(PT_ID)){
+            Long ancestorIncreaseIntegral = sharePathMapper.getAncestorIncreaseIntegralByUserId(userId);
+            if(ancestorIncreaseIntegral == null) ancestorIncreaseIntegral = 0L;
+            Long residueSocial = partitionCrashService.getResidueSocial(userId);
+            return ancestorIncreaseIntegral + residueSocial;
+        }
+        return 0L;
+    }
+
+    /**
+     * 获取最高可获取积分
+     * @param sharePath 对象
+     * @param userId 用户编号
+     */
+    private void setHighQuota(SharePathRespVO sharePath,Long userId){
+        IntegralDO integralDO = integralService.selectByUser(userId);
+        if(integralDO != null){
+            sharePath.setHigh_quota(integralDO.getHighQuota());
+        }
+    }
+
     private void getSocialStatus(SharePathRespVO sharePathRespVO,Long userId){
         if(Objects.equals(userId, PT_ID)) return;
         DuserDO duser = duserService.getDuserByUser(userId);

+ 9 - 3
feifan-module-distri/feifan-module-distri-biz/src/main/java/cn/newfeifan/mall/module/distri/service/socialstatus/SocialStatusServiceImpl.java

@@ -81,14 +81,20 @@ public class SocialStatusServiceImpl implements SocialStatusService {
         );
 
         SocialStatusBO socialStatusBO = SocialStatusBO.builder().build();
+
         for (int i = 0; i < socialStatusDOS.size(); i++) {
             if (point < socialStatusDOS.get(i).getPoint()) {
-                socialStatusBO.setId(socialStatusDOS.get(i - 1).getId());
-                socialStatusBO.setSocialUpNeed(socialStatusDOS.get(i).getPoint() - point);
+                if (point < socialStatusDOS.get(0).getPoint()) {
+                    socialStatusBO.setId(socialStatusDOS.get(i).getId());
+                    socialStatusBO.setSocialUpNeed(socialStatusDOS.get(i + 1).getPoint() - point);
+                } else {
+                    socialStatusBO.setId(socialStatusDOS.get(i - 1).getId());
+                    socialStatusBO.setSocialUpNeed(socialStatusDOS.get(i).getPoint() - point);
+                }
                 break;
             }
         }
-        if(socialStatusBO.getId() == null){
+        if (socialStatusBO.getId() == null) {
             socialStatusBO.setId(socialStatusDOS.get(socialStatusDOS.size() - 1).getId());
             socialStatusBO.setSocialUpNeed(0L);
         }

+ 4 - 0
feifan-module-distri/feifan-module-distri-biz/src/main/resources/mapper/sharepath/SharePathMapper.xml

@@ -48,6 +48,10 @@
     <select id="getMaxSortByParentId" resultType="int" parameterType="long">
         SELECT IFNULL(MAX(sort), 0) + 1 FROM distri_share_path WHERE ancestor = #{parentId} AND depth = 1
     </select>
+    <select id="getAncestorIncreaseIntegralByUserId" resultType="java.lang.Long">
+        SELECT sum(ancestor_increase_integral) AS ancestor_increase_integral FROM `trade_order_item`
+          where user_id = #{userId} and distribute_benefit = 0 and (after_sale_status = 0 or after_sale_status = 10) and deleted = 0
+    </select>
 
 
     <!-- 删除旧的祖先关系 -->

+ 12 - 0
feifan-module-infra/feifan-module-infra-api/src/main/java/cn/newfeifan/mall/module/infra/enums/AppFileConstants.java

@@ -0,0 +1,12 @@
+package cn.newfeifan.mall.module.infra.enums;
+
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 获取图片的地址域名前缀
+ */
+public interface AppFileConstants {
+    List<String> DOMAIN_LIST = Arrays.asList("https://thirdwx.qlogo.cn", "https://mall-ffkj.oss-cn-guangzhou.aliyuncs.com", "https://pt.letcgo.com");
+}

+ 1 - 0
feifan-module-infra/feifan-module-infra-api/src/main/java/cn/newfeifan/mall/module/infra/enums/ErrorCodeConstants.java

@@ -69,5 +69,6 @@ public interface ErrorCodeConstants {
     ErrorCode DEMO03_STUDENT_NOT_EXISTS = new ErrorCode(1_001_201_007, "学生不存在");
     ErrorCode DEMO03_GRADE_NOT_EXISTS = new ErrorCode(1_001_201_008, "学生班级不存在");
     ErrorCode DEMO03_GRADE_EXISTS = new ErrorCode(1_001_201_009, "学生班级已存在");
+    ErrorCode URL_DOMAIN_NOT_EXISTS = new ErrorCode(1_001_201_010, "url中的域名非指定域名");
 
 }

+ 19 - 4
feifan-module-infra/feifan-module-infra-biz/src/main/java/cn/newfeifan/mall/module/infra/controller/app/file/AppFileController.java

@@ -1,7 +1,6 @@
 package cn.newfeifan.mall.module.infra.controller.app.file;
 
 import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.io.resource.InputStreamResource;
 import cn.newfeifan.mall.framework.common.pojo.CommonResult;
 import cn.newfeifan.mall.module.infra.controller.app.file.vo.AppFileUploadReqVO;
 import cn.newfeifan.mall.module.infra.service.file.FileService;
@@ -10,7 +9,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.core.io.ByteArrayResource;
 import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.util.StreamUtils;
@@ -21,11 +19,12 @@ import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 
+import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.newfeifan.mall.framework.common.pojo.CommonResult.success;
+import static cn.newfeifan.mall.module.infra.enums.AppFileConstants.DOMAIN_LIST;
+import static cn.newfeifan.mall.module.infra.enums.ErrorCodeConstants.URL_DOMAIN_NOT_EXISTS;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.URL;
 import java.net.URLConnection;
 
@@ -54,6 +53,11 @@ public class AppFileController {
     @GetMapping("/downloadByUrl")
     @Operation(summary = "通过链接下载文件流")
     public ResponseEntity<ByteArrayResource> downloadByUrl(@RequestParam("fileUrl") String fileUrl) throws Exception {
+
+        if(!checkPrefix(fileUrl)){
+            throw exception(URL_DOMAIN_NOT_EXISTS);
+        }
+
         try {
             URL url = new URL(fileUrl);
             URLConnection connection = url.openConnection();
@@ -86,6 +90,17 @@ public class AppFileController {
         }
     }
 
+    private boolean checkPrefix(String fileUrl) {
+        // 遍历DOMAIN_LIST中的每个域名
+        for (String domain : DOMAIN_LIST) {
+            // 检查传入的字符串是否以当前域名为前缀
+            if (fileUrl.startsWith(domain)) {
+                return true; // 如果找到匹配的前缀,返回true
+            }
+        }
+        return false; // 如果没有找到匹配的前缀,返回false
+    }
+
 
 
 }

+ 6 - 0
feifan-module-mall/feifan-module-product-api/src/main/java/cn/newfeifan/mall/module/product/api/sku/dto/ProductSkuRespDTO.java

@@ -3,6 +3,7 @@ package cn.newfeifan.mall.module.product.api.sku.dto;
 import cn.newfeifan.mall.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
 import lombok.Data;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 /**
@@ -76,4 +77,9 @@ public class ProductSkuRespDTO {
      */
     private Integer secondBrokeragePrice;
 
+    /**
+     * 高精度价格
+     */
+    private BigDecimal highPrecisionPrice;
+
 }

+ 11 - 4
feifan-module-mall/feifan-module-product-api/src/main/java/cn/newfeifan/mall/module/product/api/spu/dto/ProductSpuRespDTO.java

@@ -3,6 +3,8 @@ package cn.newfeifan.mall.module.product.api.spu.dto;
 import cn.newfeifan.mall.module.product.enums.spu.ProductSpuStatusEnum;
 import lombok.Data;
 
+import java.math.BigDecimal;
+
 // TODO @LeeYan9: ProductSpuRespDTO
 /**
  * 商品 SPU 信息 Response DTO
@@ -26,7 +28,6 @@ public class ProductSpuRespDTO {
     private String name;
     /**
      * 单位
-     *
      * 对应 product_unit 数据字典
      */
     private Integer unit;
@@ -51,7 +52,6 @@ public class ProductSpuRespDTO {
 
     /**
      * 规格类型
-     *
      * false - 单规格
      * true - 多规格
      */
@@ -77,7 +77,6 @@ public class ProductSpuRespDTO {
 
     /**
      * 物流配置模板编号
-     *
      * 对应 TradeDeliveryExpressTemplateDO 的 id 编号
      */
     private Long deliveryTemplateId;
@@ -93,10 +92,18 @@ public class ProductSpuRespDTO {
 
     /**
      * 分销类型
-     *
      * false - 默认
      * true - 自行设置
      */
     private Boolean subCommissionType;
 
+    /**
+     * 高精度
+     */
+    private Boolean highPrecision;
+    /**
+     * 高精度价格
+     */
+    private BigDecimal highPrecisionPrice;
+
 }

+ 4 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spu/vo/ProductSkuRespVO.java

@@ -3,6 +3,7 @@ package cn.newfeifan.mall.module.product.controller.admin.spu.vo;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 @Schema(description = "管理后台 - 商品 SKU Response VO")
@@ -48,4 +49,7 @@ public class ProductSkuRespVO {
     @Schema(description = "属性数组")
     private List<ProductSkuSaveReqVO.Property> properties;
 
+    @Schema(description = "高精度价格", example = "9255")
+    private BigDecimal highPrecisionPrice;
+
 }

+ 3 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spu/vo/ProductSkuSaveReqVO.java

@@ -7,6 +7,7 @@ import lombok.NoArgsConstructor;
 
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
 import java.util.List;
 
 @Schema(description = "管理后台 - 商品 SKU 创建/更新 Request VO")
@@ -73,4 +74,6 @@ public class ProductSkuSaveReqVO {
 
     }
 
+    @Schema(description = "高精度价格", example = "9255")
+    private BigDecimal highPrecisionPrice;
 }

+ 6 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java

@@ -7,6 +7,7 @@ import lombok.EqualsAndHashCode;
 import lombok.ToString;
 import org.springframework.format.annotation.DateTimeFormat;
 
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 
 import static cn.newfeifan.mall.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@@ -55,4 +56,9 @@ public class ProductSpuPageReqVO extends PageParam {
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] createTime;
 
+    @Schema(description = "高精度价格", example = "9255")
+    private BigDecimal highPrecisionPrice;
+
+    @Schema(description = "高精度", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Boolean highPrecision;
 }

+ 8 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spu/vo/ProductSpuRespVO.java

@@ -9,6 +9,7 @@ import com.alibaba.excel.annotation.ExcelProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.List;
 
@@ -123,4 +124,11 @@ public class ProductSpuRespVO {
     @ExcelProperty("商品点击量")
     private Integer browseCount;
 
+    @Schema(description = "高精度", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("高精度")
+    private Boolean highPrecision;
+
+    @Schema(description = "高精度价格", example = "9255")
+    @ExcelProperty("高精度价格")
+    private BigDecimal highPrecisionPrice;
 }

+ 9 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spu/vo/ProductSpuSaveReqVO.java

@@ -6,6 +6,7 @@ import lombok.Data;
 import javax.validation.Valid;
 import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
 import java.util.List;
 
 @Schema(description = "管理后台 - 商品 SPU 新增/更新 Request VO")
@@ -93,4 +94,12 @@ public class ProductSpuSaveReqVO {
     @Valid
     private List<ProductSkuSaveReqVO> skus;
 
+
+    @Schema(description = "高精度价格", example = "9255")
+    private BigDecimal highPrecisionPrice;
+
+    @Schema(description = "高精度", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "高精度不能为空")
+    private Boolean highPrecision;
+
 }

+ 10 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java

@@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.ToString;
 
+import java.math.BigDecimal;
+
 @Schema(description = "管理后台 - 商品 SPU 精简 Response VO")
 @Data
 @ToString(callSuper = true)
@@ -37,5 +39,13 @@ public class ProductSpuSimpleRespVO {
 
     @Schema(description = "商品浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000")
     private Integer browseCount;
+    @Schema(description = "商品支付类别", example = "2")
+    private Integer spuPayType;
+
+    @Schema(description = "高精度")
+    private Boolean highPrecision;
+
+    @Schema(description = "高精度价格", example = "9255")
+    private BigDecimal highPrecisionPrice;
 
 }

+ 21 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java

@@ -4,6 +4,7 @@ import cn.newfeifan.mall.module.product.controller.app.property.vo.value.AppProd
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 @Schema(description = "用户 App - 商品 SPU 明细 Response VO")
@@ -13,6 +14,10 @@ public class AppProductSpuDetailRespVO {
     @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long id;
 
+    //add by Ben20240529
+    @Schema(description = "最大推广费,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "968") // 通过会员等级,计算出折扣后价格
+    private Integer promotionFee;
+
     // ========== 基本信息 =========
 
     @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "非繁")
@@ -83,6 +88,9 @@ public class AppProductSpuDetailRespVO {
         @Schema(description = "VIP 价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "968") // 通过会员等级,计算出折扣后价格
         private Integer vipPrice;
 
+        @Schema(description = "推广费, 单位: 分,值为sku中最大的推广费", requiredMode = Schema.RequiredMode.REQUIRED, example = "968")
+        private Integer promotionFee;
+
         @Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.zhongxing.cn/xx.png")
         private String picUrl;
 
@@ -95,6 +103,19 @@ public class AppProductSpuDetailRespVO {
         @Schema(description = "商品体积", example = "1024") // 单位:m^3 平米
         private Double volume;
 
+        @Schema(description = "高精度价格", example = "9255")
+        private BigDecimal highPrecisionPrice;
+
     }
 
+    @Schema(description = "商品类别")
+    private Integer spuType;
+    @Schema(description = "商品支付类别")
+    private Integer spuPayType;
+    @Schema(description = "高精度价格", example = "9255")
+    private BigDecimal highPrecisionPrice;
+
+    @Schema(description = "高精度", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Boolean highPrecision;
+
 }

+ 13 - 0
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/controller/app/spu/vo/AppProductSpuRespVO.java

@@ -3,6 +3,7 @@ package cn.newfeifan.mall.module.product.controller.app.spu.vo;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 @Schema(description = "用户 App - 商品 SPU Response VO")
@@ -12,6 +13,9 @@ public class AppProductSpuRespVO {
     @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Long id;
 
+    @Schema(description = "推广费,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    private Integer promotionFee;
+
     @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "非繁")
     private String name;
 
@@ -51,4 +55,13 @@ public class AppProductSpuRespVO {
     @Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Integer salesCount;
 
+    @Schema(description = "商品支付方式")
+    private Integer spuPayType;
+
+    @Schema(description = "高精度价格", example = "9255")
+    private BigDecimal highPrecisionPrice;
+
+    @Schema(description = "高精度", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Boolean highPrecision;
+
 }

+ 9 - 1
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/dataobject/sku/ProductSkuDO.java

@@ -12,6 +12,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler;
 import lombok.*;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 /**
@@ -35,6 +36,10 @@ public class ProductSkuDO extends BaseDO {
     @TableId
     private Long id;
 
+    /**
+     * 推广费, 单位: 分,值为sku中最大的推广费 add by Ben 20240529
+     */
+    private Integer promotionFee;
 
     /**
      * 店铺ID,关联`sale_shop`表
@@ -50,7 +55,6 @@ public class ProductSkuDO extends BaseDO {
 
     /**
      * SPU 编号
-     *
      * 关联 {@link ProductSpuDO#getId()}
      */
     private Long spuId;
@@ -109,6 +113,10 @@ public class ProductSkuDO extends BaseDO {
      */
     private Integer salesCount;
 
+    /**
+     * 高精度价格
+     */
+    private BigDecimal highPrecisionPrice;
     /**
      * 商品属性
      */

+ 22 - 11
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/dataobject/spu/ProductSpuDO.java

@@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import lombok.*;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 /**
@@ -38,6 +39,11 @@ public class ProductSpuDO extends BaseDO {
 
     // ========== 基本信息 =========
 
+    /**
+     * 推广费, 单位: 分,值为sku中最大的推广费
+     */
+    private Integer promotionFee;
+
     /**
      * 商品名称
      */
@@ -57,13 +63,11 @@ public class ProductSpuDO extends BaseDO {
 
     /**
      * 商品分类编号
-     *
      * 关联 {@link ProductCategoryDO#getId()}
      */
     private Long categoryId;
     /**
      * 商品品牌编号
-     *
      * 关联 {@link ProductBrandDO#getId()}
      */
     private Long brandId;
@@ -83,7 +87,6 @@ public class ProductSpuDO extends BaseDO {
     private Integer sort;
     /**
      * 商品状态
-     *
      * 枚举 {@link ProductSpuStatusEnum}
      */
     private Integer status;
@@ -92,32 +95,27 @@ public class ProductSpuDO extends BaseDO {
 
     /**
      * 规格类型
-     *
      * false - 单规格
      * true - 多规格
      */
     private Boolean specType;
     /**
      * 商品价格,单位使用:分
-     *
      * 基于其对应的 {@link ProductSkuDO#getPrice()} sku单价最低的商品的
      */
     private Integer price;
     /**
      * 市场价,单位使用:分
-     *
      * 基于其对应的 {@link ProductSkuDO#getMarketPrice()} sku单价最低的商品的
      */
     private Integer marketPrice;
     /**
      * 成本价,单位使用:分
-     *
      * 基于其对应的 {@link ProductSkuDO#getCostPrice()} sku单价最低的商品的
      */
     private Integer costPrice;
     /**
      * 库存
-     *
      * 基于其对应的 {@link ProductSkuDO#getStock()} 求和
      */
     private Integer stock;
@@ -126,14 +124,12 @@ public class ProductSpuDO extends BaseDO {
 
     /**
      * 配送方式数组
-     *
      * 对应 DeliveryTypeEnum 枚举
      */
     @TableField(typeHandler = IntegerListTypeHandler.class)
     private List<Integer> deliveryTypes;
     /**
      * 物流配置模板编号
-     *
      * 对应 TradeDeliveryExpressTemplateDO 的 id 编号
      */
     private Long deliveryTemplateId;
@@ -148,7 +144,6 @@ public class ProductSpuDO extends BaseDO {
     // TODO @puhui999:字段估计要改成 brokerageType
     /**
      * 分销类型
-     *
      * false - 默认
      * true - 自行设置
      */
@@ -168,4 +163,20 @@ public class ProductSpuDO extends BaseDO {
      * 浏览量
      */
     private Integer browseCount;
+    /**
+     * 商品类别
+     */
+    private Integer spuType;
+    /**
+     * 商品支付类别
+     */
+    private Integer spuPayType;
+    /**
+     * 高精度
+     */
+    private Boolean highPrecision;
+    /**
+     * 高精度价格
+     */
+    private BigDecimal highPrecisionPrice;
 }

+ 12 - 6
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/service/spu/ProductSpuServiceImpl.java

@@ -102,12 +102,18 @@ public class ProductSpuServiceImpl implements ProductSpuService {
      * @param skus 商品 SKU 数组
      */
     private void initSpuFromSkus(ProductSpuDO spu, List<ProductSkuSaveReqVO> skus) {
-        // sku 单价最低的商品的价格
-        spu.setPrice(getMinValue(skus, ProductSkuSaveReqVO::getPrice));
-        // sku 单价最低的商品的市场价格
-        spu.setMarketPrice(getMinValue(skus, ProductSkuSaveReqVO::getMarketPrice));
-        // sku 单价最低的商品的成本价格
-        spu.setCostPrice(getMinValue(skus, ProductSkuSaveReqVO::getCostPrice));
+        //是否是高精度商品
+        if(!spu.getHighPrecision()){
+            // sku 单价最低的商品的价格
+            spu.setPrice(getMinValue(skus, ProductSkuSaveReqVO::getPrice));
+            // sku 单价最低的商品的市场价格
+            spu.setMarketPrice(getMinValue(skus, ProductSkuSaveReqVO::getMarketPrice));
+            // sku 单价最低的商品的成本价格
+            spu.setCostPrice(getMinValue(skus, ProductSkuSaveReqVO::getCostPrice));
+        }else{
+            // sku 单价最低的商品的价格
+            spu.setHighPrecisionPrice(getMinValue(skus, ProductSkuSaveReqVO::getHighPrecisionPrice));
+        }
         // skus 库存总数
         spu.setStock(getSumValue(skus, ProductSkuSaveReqVO::getStock, Integer::sum));
         // 若是 spu 已有状态则不处理

+ 1 - 0
feifan-module-mall/feifan-module-sale-api/src/main/java/cn/newfeifan/mall/module/sale/enums/ErrorCodeConstants.java

@@ -15,4 +15,5 @@ public interface ErrorCodeConstants {
     //店铺表相关错误,表编号是1
     ErrorCode SHOP_NOT_EXISTS = new ErrorCode(1_101_001_001, "店铺不存在");
 
+    ErrorCode MERCHANT_APPLY_NOT_EXISTS = new ErrorCode(1_002_029_003, "商户申请不存在");
 }

+ 70 - 0
feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/controller/admin/merchantapply/MerchantApplyController.java

@@ -0,0 +1,70 @@
+package cn.newfeifan.mall.module.sale.controller.admin.merchantapply;
+
+import cn.newfeifan.mall.framework.security.core.annotations.PreAuthenticated;
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import javax.validation.*;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.common.pojo.CommonResult;
+import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
+import static cn.newfeifan.mall.framework.common.pojo.CommonResult.success;
+
+import cn.newfeifan.mall.module.sale.controller.admin.merchantapply.vo.*;
+import cn.newfeifan.mall.module.sale.dal.dataobject.merchantapply.MerchantApplyDO;
+import cn.newfeifan.mall.module.sale.service.merchantapply.MerchantApplyService;
+
+@Tag(name = "管理后台 - 商户申请")
+@RestController
+@RequestMapping("/sale/merchant-apply")
+@Validated
+public class MerchantApplyController {
+
+    @Resource
+    private MerchantApplyService merchantApplyService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建商户申请")
+    @PreAuthenticated
+    public CommonResult<Long> createMerchantApply(@Valid @RequestBody MerchantApplySaveReqVO createReqVO) {
+        return success(merchantApplyService.createMerchantApply(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新商户申请")
+    @PreAuthenticated
+    public CommonResult<Boolean> updateMerchantApply(@Valid @RequestBody MerchantApplySaveReqVO updateReqVO) {
+        merchantApplyService.updateMerchantApply(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除商户申请")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthenticated
+    public CommonResult<Boolean> deleteMerchantApply(@RequestParam("id") Long id) {
+        merchantApplyService.deleteMerchantApply(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得商户申请")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthenticated
+    public CommonResult<MerchantApplyRespVO> getMerchantApply(@RequestParam("id") Long id) {
+        MerchantApplyDO merchantApply = merchantApplyService.getMerchantApply(id);
+        return success(BeanUtils.toBean(merchantApply, MerchantApplyRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得商户申请分页")
+    @PreAuthenticated
+    public CommonResult<PageResult<MerchantApplyRespVO>> getMerchantApplyPage(@Valid MerchantApplyPageReqVO pageReqVO) {
+        PageResult<MerchantApplyDO> pageResult = merchantApplyService.getMerchantApplyPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, MerchantApplyRespVO.class));
+    }
+}

+ 92 - 0
feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/controller/admin/merchantapply/vo/MerchantApplyPageReqVO.java

@@ -0,0 +1,92 @@
+package cn.newfeifan.mall.module.sale.controller.admin.merchantapply.vo;
+
+import lombok.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.newfeifan.mall.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static cn.newfeifan.mall.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 商户申请分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MerchantApplyPageReqVO extends PageParam {
+
+    @Schema(description = "logo地址", example = "https://www.zhongxing.cn")
+    private String logoUrl;
+
+    @Schema(description = "商户名称", example = "非繁人")
+    private String name;
+
+    @Schema(description = "商户状态,关联商户状态表", example = "1")
+    private Integer status;
+
+    @Schema(description = "简介", example = "随便")
+    private String description;
+
+    @Schema(description = "商户负责人")
+    private String contact;
+
+    @Schema(description = "所在地")
+    private String address;
+
+    @Schema(description = "负责人电话")
+    private String contactNumber;
+
+    @Schema(description = "域名")
+    private String website;
+
+    @Schema(description = "商户官网", example = "https://www.zhongxing.cn")
+    private String businessUrl;
+
+    @Schema(description = "维权电话")
+    private String complaintsHotline;
+
+    @Schema(description = "客服电话")
+    private String customerServiceHotline;
+
+    @Schema(description = "邮箱")
+    private String email;
+
+    @Schema(description = "营业执照图片路径")
+    private String businessLicensePicture;
+
+    @Schema(description = "服务套餐", example = "18036")
+    private Integer packageId;
+
+    @Schema(description = "店铺数量", example = "31320")
+    private Integer shopCount;
+
+    @Schema(description = "服务到期时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] expireTime;
+
+    @Schema(description = "申请时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+    @Schema(description = "区域id,对应文件系统 src/main/resources/area.csv 中的id一列", example = "28982")
+    private Long areaId;
+
+    @Schema(description = "申请用户id", example = "7189")
+    private Long applyMemberUserId;
+
+    @Schema(description = "审核系统用户id", example = "29612")
+    private Long checkSystemUserId;
+
+    @Schema(description = "审核时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] checkTime;
+
+    @Schema(description = "审核意见")
+    private String checkComment;
+
+    @Schema(description = "申请备注")
+    private String applyComment;
+
+    @Schema(description = "审核状态:默认0表示未审核,1审核通过,2审核不通过", example = "1")
+    private Integer checkStatus;
+
+}

+ 113 - 0
feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/controller/admin/merchantapply/vo/MerchantApplyRespVO.java

@@ -0,0 +1,113 @@
+package cn.newfeifan.mall.module.sale.controller.admin.merchantapply.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+
+@Schema(description = "管理后台 - 商户申请 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MerchantApplyRespVO {
+
+    @Schema(description = "商户id", requiredMode = Schema.RequiredMode.REQUIRED, example = "32267")
+    @ExcelProperty("商户id")
+    private Long id;
+
+    @Schema(description = "logo地址", example = "https://www.zhongxing.cn")
+    @ExcelProperty("logo地址")
+    private String logoUrl;
+
+    @Schema(description = "商户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "非繁人")
+    @ExcelProperty("商户名称")
+    private String name;
+
+    @Schema(description = "商户状态,关联商户状态表", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @ExcelProperty("商户状态,关联商户状态表")
+    private Integer status;
+
+    @Schema(description = "简介", example = "随便")
+    @ExcelProperty("简介")
+    private String description;
+
+    @Schema(description = "商户负责人")
+    @ExcelProperty("商户负责人")
+    private String contact;
+
+    @Schema(description = "所在地")
+    @ExcelProperty("所在地")
+    private String address;
+
+    @Schema(description = "负责人电话")
+    @ExcelProperty("负责人电话")
+    private String contactNumber;
+
+    @Schema(description = "域名")
+    @ExcelProperty("域名")
+    private String website;
+
+    @Schema(description = "商户官网", example = "https://www.zhongxing.cn")
+    @ExcelProperty("商户官网")
+    private String businessUrl;
+
+    @Schema(description = "维权电话")
+    @ExcelProperty("维权电话")
+    private String complaintsHotline;
+
+    @Schema(description = "客服电话")
+    @ExcelProperty("客服电话")
+    private String customerServiceHotline;
+
+    @Schema(description = "邮箱")
+    @ExcelProperty("邮箱")
+    private String email;
+
+    @Schema(description = "营业执照图片路径")
+    @ExcelProperty("营业执照图片路径")
+    private String businessLicensePicture;
+
+    @Schema(description = "服务套餐", example = "18036")
+    @ExcelProperty("服务套餐")
+    private Integer packageId;
+
+    @Schema(description = "店铺数量", example = "31320")
+    @ExcelProperty("店铺数量")
+    private Integer shopCount;
+
+    @Schema(description = "服务到期时间")
+    @ExcelProperty("服务到期时间")
+    private LocalDateTime expireTime;
+
+    @Schema(description = "申请时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("申请时间")
+    private LocalDateTime createTime;
+
+    @Schema(description = "区域id,对应文件系统 src/main/resources/area.csv 中的id一列", example = "28982")
+    @ExcelProperty("区域id,对应文件系统 src/main/resources/area.csv 中的id一列")
+    private Long areaId;
+
+    @Schema(description = "申请用户id", requiredMode = Schema.RequiredMode.REQUIRED, example = "7189")
+    @ExcelProperty("申请用户id")
+    private Long applyMemberUserId;
+
+    @Schema(description = "审核系统用户id", example = "29612")
+    @ExcelProperty("审核系统用户id")
+    private Long checkSystemUserId;
+
+    @Schema(description = "审核时间")
+    @ExcelProperty("审核时间")
+    private LocalDateTime checkTime;
+
+    @Schema(description = "审核意见")
+    @ExcelProperty("审核意见")
+    private String checkComment;
+
+    @Schema(description = "申请备注")
+    @ExcelProperty("申请备注")
+    private String applyComment;
+
+    @Schema(description = "审核状态:默认0表示未审核,1审核通过,2审核不通过", example = "1")
+    @ExcelProperty("审核状态:默认0表示未审核,1审核通过,2审核不通过")
+    private Integer checkStatus;
+
+}

+ 87 - 0
feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/controller/admin/merchantapply/vo/MerchantApplySaveReqVO.java

@@ -0,0 +1,87 @@
+package cn.newfeifan.mall.module.sale.controller.admin.merchantapply.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import javax.validation.constraints.*;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 商户申请新增/修改 Request VO")
+@Data
+public class MerchantApplySaveReqVO {
+
+    @Schema(description = "商户id", requiredMode = Schema.RequiredMode.REQUIRED, example = "32267")
+    private Long id;
+
+    @Schema(description = "logo地址", example = "https://www.zhongxing.cn")
+    private String logoUrl;
+
+    @Schema(description = "商户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "非繁人")
+    @NotEmpty(message = "商户名称不能为空")
+    private String name;
+
+    @Schema(description = "商户状态,关联商户状态表", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "商户状态,关联商户状态表不能为空")
+    private Integer status;
+
+    @Schema(description = "简介", example = "随便")
+    private String description;
+
+    @Schema(description = "商户负责人")
+    private String contact;
+
+    @Schema(description = "所在地")
+    private String address;
+
+    @Schema(description = "负责人电话")
+    private String contactNumber;
+
+    @Schema(description = "域名")
+    private String website;
+
+    @Schema(description = "商户官网", example = "https://www.zhongxing.cn")
+    private String businessUrl;
+
+    @Schema(description = "维权电话")
+    private String complaintsHotline;
+
+    @Schema(description = "客服电话")
+    private String customerServiceHotline;
+
+    @Schema(description = "邮箱")
+    private String email;
+
+    @Schema(description = "营业执照图片路径")
+    private String businessLicensePicture;
+
+    @Schema(description = "服务套餐", example = "18036")
+    private Integer packageId;
+
+    @Schema(description = "店铺数量", example = "31320")
+    private Integer shopCount;
+
+    @Schema(description = "服务到期时间")
+    private LocalDateTime expireTime;
+
+    @Schema(description = "区域id,对应文件系统 src/main/resources/area.csv 中的id一列", example = "28982")
+    private Long areaId;
+
+    @Schema(description = "申请用户id", requiredMode = Schema.RequiredMode.REQUIRED, example = "7189")
+    @NotNull(message = "申请用户id不能为空")
+    private Long applyMemberUserId;
+
+    @Schema(description = "审核系统用户id", example = "29612")
+    private Long checkSystemUserId;
+
+    @Schema(description = "审核时间")
+    private LocalDateTime checkTime;
+
+    @Schema(description = "审核意见")
+    private String checkComment;
+
+    @Schema(description = "申请备注")
+    private String applyComment;
+
+    @Schema(description = "审核状态:默认0表示未审核,1审核通过,2审核不通过", example = "1")
+    private Integer checkStatus;
+
+}

+ 121 - 0
feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/dal/dataobject/merchantapply/MerchantApplyDO.java

@@ -0,0 +1,121 @@
+package cn.newfeifan.mall.module.sale.dal.dataobject.merchantapply;
+
+import lombok.*;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.newfeifan.mall.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 商户申请 DO
+ *
+ * @author 非繁人
+ */
+@TableName("sale_merchant_apply")
+@KeySequence("sale_merchant_apply_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class MerchantApplyDO extends BaseDO {
+
+    /**
+     * 商户id
+     */
+    @TableId
+    private Long id;
+    /**
+     * logo地址
+     */
+    private String logoUrl;
+    /**
+     * 商户名称
+     */
+    private String name;
+    /**
+     * 商户状态,关联商户状态表
+     */
+    private Integer status;
+    /**
+     * 简介
+     */
+    private String description;
+    /**
+     * 商户负责人
+     */
+    private String contact;
+    /**
+     * 所在地
+     */
+    private String address;
+    /**
+     * 负责人电话
+     */
+    private String contactNumber;
+    /**
+     * 域名
+     */
+    private String website;
+    /**
+     * 商户官网
+     */
+    private String businessUrl;
+    /**
+     * 维权电话
+     */
+    private String complaintsHotline;
+    /**
+     * 客服电话
+     */
+    private String customerServiceHotline;
+    /**
+     * 邮箱
+     */
+    private String email;
+    /**
+     * 营业执照图片路径
+     */
+    private String businessLicensePicture;
+    /**
+     * 服务套餐
+     */
+    private Integer packageId;
+    /**
+     * 店铺数量
+     */
+    private Integer shopCount;
+    /**
+     * 服务到期时间
+     */
+    private LocalDateTime expireTime;
+    /**
+     * 区域id,对应文件系统 src/main/resources/area.csv 中的id一列
+     */
+    private Long areaId;
+    /**
+     * 申请用户id
+     */
+    private Long applyMemberUserId;
+    /**
+     * 审核系统用户id
+     */
+    private Long checkSystemUserId;
+    /**
+     * 审核时间
+     */
+    private LocalDateTime checkTime;
+    /**
+     * 审核意见
+     */
+    private String checkComment;
+    /**
+     * 申请备注
+     */
+    private String applyComment;
+    /**
+     * 审核状态:默认0表示未审核,1审核通过,2审核不通过
+     */
+    private Integer checkStatus;
+
+}

+ 48 - 0
feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/dal/mysql/merchantapply/MerchantApplyMapper.java

@@ -0,0 +1,48 @@
+package cn.newfeifan.mall.module.sale.dal.mysql.merchantapply;
+
+
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.newfeifan.mall.framework.mybatis.core.mapper.BaseMapperX;
+import cn.newfeifan.mall.module.sale.dal.dataobject.merchantapply.MerchantApplyDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.newfeifan.mall.module.sale.controller.admin.merchantapply.vo.*;
+
+/**
+ * 商户申请 Mapper
+ *
+ * @author 非繁人
+ */
+@Mapper
+public interface MerchantApplyMapper extends BaseMapperX<MerchantApplyDO> {
+
+    default PageResult<MerchantApplyDO> selectPage(MerchantApplyPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<MerchantApplyDO>()
+                .eqIfPresent(MerchantApplyDO::getLogoUrl, reqVO.getLogoUrl())
+                .likeIfPresent(MerchantApplyDO::getName, reqVO.getName())
+                .eqIfPresent(MerchantApplyDO::getStatus, reqVO.getStatus())
+                .eqIfPresent(MerchantApplyDO::getDescription, reqVO.getDescription())
+                .eqIfPresent(MerchantApplyDO::getContact, reqVO.getContact())
+                .eqIfPresent(MerchantApplyDO::getAddress, reqVO.getAddress())
+                .eqIfPresent(MerchantApplyDO::getContactNumber, reqVO.getContactNumber())
+                .eqIfPresent(MerchantApplyDO::getWebsite, reqVO.getWebsite())
+                .eqIfPresent(MerchantApplyDO::getBusinessUrl, reqVO.getBusinessUrl())
+                .eqIfPresent(MerchantApplyDO::getComplaintsHotline, reqVO.getComplaintsHotline())
+                .eqIfPresent(MerchantApplyDO::getCustomerServiceHotline, reqVO.getCustomerServiceHotline())
+                .eqIfPresent(MerchantApplyDO::getEmail, reqVO.getEmail())
+                .eqIfPresent(MerchantApplyDO::getBusinessLicensePicture, reqVO.getBusinessLicensePicture())
+                .eqIfPresent(MerchantApplyDO::getPackageId, reqVO.getPackageId())
+                .eqIfPresent(MerchantApplyDO::getShopCount, reqVO.getShopCount())
+                .betweenIfPresent(MerchantApplyDO::getExpireTime, reqVO.getExpireTime())
+                .betweenIfPresent(MerchantApplyDO::getCreateTime, reqVO.getCreateTime())
+                .eqIfPresent(MerchantApplyDO::getAreaId, reqVO.getAreaId())
+                .eqIfPresent(MerchantApplyDO::getApplyMemberUserId, reqVO.getApplyMemberUserId())
+                .eqIfPresent(MerchantApplyDO::getCheckSystemUserId, reqVO.getCheckSystemUserId())
+                .betweenIfPresent(MerchantApplyDO::getCheckTime, reqVO.getCheckTime())
+                .eqIfPresent(MerchantApplyDO::getCheckComment, reqVO.getCheckComment())
+                .eqIfPresent(MerchantApplyDO::getApplyComment, reqVO.getApplyComment())
+                .eqIfPresent(MerchantApplyDO::getCheckStatus, reqVO.getCheckStatus())
+                .orderByDesc(MerchantApplyDO::getId));
+    }
+
+}

+ 53 - 0
feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/service/merchantapply/MerchantApplyService.java

@@ -0,0 +1,53 @@
+package cn.newfeifan.mall.module.sale.service.merchantapply;
+
+import javax.validation.*;
+import cn.newfeifan.mall.module.sale.controller.admin.merchantapply.vo.*;
+import cn.newfeifan.mall.module.sale.dal.dataobject.merchantapply.MerchantApplyDO;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+
+/**
+ * 商户申请 Service 接口
+ *
+ * @author 非繁人
+ */
+public interface MerchantApplyService {
+
+    /**
+     * 创建商户申请
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createMerchantApply(@Valid MerchantApplySaveReqVO createReqVO);
+
+    /**
+     * 更新商户申请
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateMerchantApply(@Valid MerchantApplySaveReqVO updateReqVO);
+
+    /**
+     * 删除商户申请
+     *
+     * @param id 编号
+     */
+    void deleteMerchantApply(Long id);
+
+    /**
+     * 获得商户申请
+     *
+     * @param id 编号
+     * @return 商户申请
+     */
+    MerchantApplyDO getMerchantApply(Long id);
+
+    /**
+     * 获得商户申请分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 商户申请分页
+     */
+    PageResult<MerchantApplyDO> getMerchantApplyPage(MerchantApplyPageReqVO pageReqVO);
+
+}

+ 71 - 0
feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/service/merchantapply/MerchantApplyServiceImpl.java

@@ -0,0 +1,71 @@
+package cn.newfeifan.mall.module.sale.service.merchantapply;
+
+import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+
+import cn.newfeifan.mall.module.sale.controller.admin.merchantapply.vo.*;
+import cn.newfeifan.mall.module.sale.dal.dataobject.merchantapply.MerchantApplyDO;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
+
+import cn.newfeifan.mall.module.sale.dal.mysql.merchantapply.MerchantApplyMapper;
+
+import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.newfeifan.mall.module.sale.enums.ErrorCodeConstants.*;
+
+/**
+ * 商户申请 Service 实现类
+ *
+ * @author 非繁人
+ */
+@Service
+@Validated
+public class MerchantApplyServiceImpl implements MerchantApplyService {
+
+    @Resource
+    private MerchantApplyMapper merchantApplyMapper;
+
+    @Override
+    public Long createMerchantApply(MerchantApplySaveReqVO createReqVO) {
+        // 插入
+        MerchantApplyDO merchantApply = BeanUtils.toBean(createReqVO, MerchantApplyDO.class);
+        merchantApplyMapper.insert(merchantApply);
+        // 返回
+        return merchantApply.getId();
+    }
+
+    @Override
+    public void updateMerchantApply(MerchantApplySaveReqVO updateReqVO) {
+        // 校验存在
+        validateMerchantApplyExists(updateReqVO.getId());
+        // 更新
+        MerchantApplyDO updateObj = BeanUtils.toBean(updateReqVO, MerchantApplyDO.class);
+        merchantApplyMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteMerchantApply(Long id) {
+        // 校验存在
+        validateMerchantApplyExists(id);
+        // 删除
+        merchantApplyMapper.deleteById(id);
+    }
+
+    private void validateMerchantApplyExists(Long id) {
+        if (merchantApplyMapper.selectById(id) == null) {
+            throw exception(MERCHANT_APPLY_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public MerchantApplyDO getMerchantApply(Long id) {
+        return merchantApplyMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<MerchantApplyDO> getMerchantApplyPage(MerchantApplyPageReqVO pageReqVO) {
+        return merchantApplyMapper.selectPage(pageReqVO);
+    }
+
+}

+ 3 - 1
feifan-module-mall/feifan-module-trade-api/src/main/java/cn/newfeifan/mall/module/trade/enums/delivery/DeliveryTypeEnum.java

@@ -16,7 +16,9 @@ import java.util.Arrays;
 public enum DeliveryTypeEnum implements IntArrayValuable {
 
     EXPRESS(1, "快递发货"),
-    PICK_UP(2, "用户自提"),;
+    PICK_UP(2, "用户自提"),
+    VIRTUAL_PRODUCT(3,"虚拟商品收货")
+    ;
 
     public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DeliveryTypeEnum::getType).toArray();
 

+ 46 - 0
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/controller/app/order/AppTradeOrderController.java

@@ -7,6 +7,9 @@ import cn.newfeifan.mall.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
 import cn.newfeifan.mall.module.pay.controller.admin.order.vo.PayOrderRespVO;
 import cn.newfeifan.mall.module.pay.convert.order.PayOrderConvert;
 import cn.newfeifan.mall.module.pay.dal.dataobject.order.PayOrderDO;
+import cn.newfeifan.mall.module.pay.dal.mysql.order.PayOrderMapper;
+import cn.newfeifan.mall.module.pay.enums.order.PayOrderStatusEnum;
+import cn.newfeifan.mall.module.pay.service.order.PayOrderService;
 import cn.newfeifan.mall.module.trade.controller.app.order.vo.*;
 import cn.newfeifan.mall.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
 import cn.newfeifan.mall.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO;
@@ -57,6 +60,48 @@ public class AppTradeOrderController {
     @Resource
     private TradeOrderProperties tradeOrderProperties;
 
+    //add by Ben
+    @Resource
+    private PayOrderMapper payOrderMapper;
+    //add by Ben
+    @Resource
+    private PayOrderService payOrderService;
+
+
+    @GetMapping("/getPayOrderByStatus")
+    @Operation(summary = "获得支付订单")
+    @Parameter(name = "id", description = "支付订单编号", required = true, example = "1024")
+    public CommonResult<PayOrderRespVO> getPayOrderByStatus(@RequestParam("id") Long id) {
+
+        PayOrderDO oldPayOrderDO = payOrderMapper.selectById(id);
+        PayOrderDO newPayOrderDO = payOrderService.getOrderByStatus(oldPayOrderDO);
+
+        CommonResult<PayOrderRespVO> success = success(PayOrderConvert.INSTANCE.convert(newPayOrderDO));
+
+//        boolean test = true;
+//        if(true)
+        //如果在上一行代码,把支付订单状态从“待支付”,改为“已支付”,则证明订单支付成功,则改trade_order表状态为待发货,并且分配积分
+        if(oldPayOrderDO.getStatus().equals(PayOrderStatusEnum.WAITING.getStatus())
+                &&
+                newPayOrderDO.getStatus().equals(PayOrderStatusEnum.SUCCESS.getStatus())
+        )
+        {
+            //只有支付订单id参数payOrderId是有用的。
+            List list = tradeOrderUpdateService.updateOrderPaid(id);
+            Object jfObj = list.get(0);
+            Object sjObj = list.get(1);
+
+            Long jf = (Long)jfObj;//待确权积分
+            Double sj = (Double)sjObj;//待确权身价
+
+            success.getData().setJf(jf);
+            success.getData().setSj(sj);
+        }
+
+        return success;
+    }
+
+
 
     /**
      * add by Ben
@@ -94,6 +139,7 @@ public class AppTradeOrderController {
     @PostMapping("/update-paid")
     @Operation(summary = "更新订单为已支付") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
     public CommonResult<Boolean> updateOrderPaid(@RequestBody PayOrderNotifyReqDTO notifyReqDTO) {
+        log.error("============进入支付回调===================");
         tradeOrderUpdateService.updateOrderPaid(Long.valueOf(notifyReqDTO.getMerchantOrderId()),
                 notifyReqDTO.getPayOrderId());
         return success(true);

+ 1 - 1
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/controller/app/order/vo/AppTradeOrderCreateReqVO.java

@@ -17,7 +17,7 @@ public class AppTradeOrderCreateReqVO extends AppTradeOrderSettlementReqVO {
 
     //add by Ben
     @Schema(description = "本订单使用积分,为一整数", example = "36")
-    private Long payIntegral;
+    private Double payIntegral;
 
     @Schema(description = "【本属性已不作页面与后台传值使用,被shopRemarks替代。本属性只作java内部使用】备注", example = "这个是我的订单哟")
     private String remark;

+ 1 - 3
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java

@@ -1,12 +1,10 @@
 package cn.newfeifan.mall.module.trade.controller.app.order.vo;
 
 import cn.newfeifan.mall.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO;
-import cn.newfeifan.mall.module.trade.enums.order.TradeOrderRefundStatusEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.time.LocalDateTime;
-import java.util.Date;
 import java.util.List;
 
 @Schema(description = "用户 App - 订单交易的明细 Response VO")
@@ -15,7 +13,7 @@ public class AppTradeOrderDetailRespVO {
 
     //========使用积分=================
     @Schema(description = "订单使用积分", example = "8900000")
-    private Long payIntegral;
+    private Double payIntegral;
 
     // ========== 订单基本信息 ==========
 

+ 2 - 1
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java

@@ -1,6 +1,5 @@
 package cn.newfeifan.mall.module.trade.controller.app.order.vo;
 
-import cn.hutool.core.util.ObjUtil;
 import cn.newfeifan.mall.framework.common.validation.InEnum;
 import cn.newfeifan.mall.framework.common.validation.Mobile;
 import cn.newfeifan.mall.module.trade.enums.delivery.DeliveryTypeEnum;
@@ -41,6 +40,8 @@ public class AppTradeOrderSettlementReqVO {
 
     @Schema(description = "收件地址编号", example = "1")
     private Long addressId;
+    @Schema(description = "地址类别",example = "1 实体;2虚拟")
+    private Integer addressType = 1;
 
     @Schema(description = "自提门店编号", example = "1088")
     private Long pickUpStoreId;

+ 10 - 1
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/controller/app/order/vo/AppTradeOrderSettlementRespVO.java

@@ -7,6 +7,7 @@ import lombok.Data;
 import lombok.NoArgsConstructor;
 
 import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
 import java.util.List;
 import java.util.Map;
 
@@ -64,6 +65,8 @@ public class AppTradeOrderSettlementRespVO {
         private Integer skuId;
         @Schema(description = "价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
         private Integer price;
+        @Schema(description = "高精度金额")
+        private BigDecimal highPrecisionPrice;
         @Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.zhongxing.cn/1.png")
         private String picUrl;
 
@@ -86,9 +89,12 @@ public class AppTradeOrderSettlementRespVO {
     @AllArgsConstructor
     public static class Price {
 
-        @Schema(description = "商品原价(总),单位:", requiredMode = Schema.RequiredMode.REQUIRED, example = "500")
+        @Schema(description = "商品原价(总),单位:小数点后六位", requiredMode = Schema.RequiredMode.REQUIRED, example = "500")
         private Integer totalPrice;
 
+        @Schema(description = "虚拟商品原价(总)", requiredMode = Schema.RequiredMode.REQUIRED, example = "500")
+        private Double virtualTotalPrice;
+
         @Schema(description = "订单优惠(总),单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "66")
         private Integer discountPrice;
 
@@ -107,6 +113,9 @@ public class AppTradeOrderSettlementRespVO {
         @Schema(description = "实际支付金额(总),单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "450")
         private Integer payPrice;
 
+        @Schema(description = "虚拟商品实际支付金额(总),单位:小数点后六位", requiredMode = Schema.RequiredMode.REQUIRED, example = "450")
+        private Double virtualPayPrice;
+
     }
 
     @Schema(description = "地址信息")

+ 1 - 1
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/dal/dataobject/order/TradeOrderDO.java

@@ -34,7 +34,7 @@ public class TradeOrderDO extends BaseDO {
 
     //本商品使用积分 add by Ben payIntegral
 //    private Integer payPoints;
-    private Long payIntegral;
+    private Double payIntegral;
 
     //退还的使用的积分 add by Ben
     private Long refundIntegral;

+ 7 - 0
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/dal/dataobject/order/TradeOrderItemDO.java

@@ -13,6 +13,7 @@ import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 
 import java.io.Serializable;
+import java.math.BigDecimal;
 import java.util.List;
 
 /**
@@ -38,6 +39,9 @@ public class TradeOrderItemDO extends BaseDO {
     //用户获得积分 add by Ben
     private Long increaseIntegral;
 
+    //推荐用户获得积分 add by Ben 20240604
+    private Long ancestorIncreaseIntegral;
+
     // ========== 订单项基本信息 ==========
     /**
      * 编号
@@ -188,6 +192,9 @@ public class TradeOrderItemDO extends BaseDO {
      */
     private Integer afterSaleStatus;
 
+    @TableField(exist = false)
+    private BigDecimal highPrecisionPrice;
+
     /**
      * 商品属性
      */

+ 6 - 0
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/dal/mysql/order/TradeOrderMapper.java

@@ -9,6 +9,8 @@ import cn.newfeifan.mall.module.trade.controller.app.order.vo.AppTradeOrderPageR
 import cn.newfeifan.mall.module.trade.dal.dataobject.order.TradeOrderDO;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
 
 import java.time.LocalDateTime;
 import java.util.List;
@@ -18,6 +20,10 @@ import java.util.Set;
 @Mapper
 public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> {
 
+    //add by Ben 20240604
+    @Select("SELECT ancestor FROM `distri_share_path` where descendant = #{userId} and depth=1")
+    Long selectAncesterByMemberUserId(@Param("userId") Long userId);
+
     default int updateByIdAndStatus(Long id, Integer status, TradeOrderDO update) {
         return update(update, new LambdaUpdateWrapper<TradeOrderDO>()
                 .eq(TradeOrderDO::getId, id).eq(TradeOrderDO::getStatus, status));

+ 2 - 2
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/aftersale/AfterSaleServiceImpl.java

@@ -312,8 +312,8 @@ public class AfterSaleServiceImpl implements AfterSaleService {
         List<Long> adminUsers = adminUserService.getUserIdsByShop(afterSale.getShopId());
         for (Long aUserId : adminUsers) {
             //发送信息
-            wcChatMessageUtils.sendWcChatMessage(afterSale.getUserId(), WcChatMessageTemplateIdEnum.AFTER_SALE_NO_CHECK2.getTemplateId(),
-                    params, aUserId, null, afterSale.getId());
+            wcChatMessageUtils.sendWcChatMessage(WcChatMessageTemplateIdEnum.AFTER_SALE_NO_CHECK2.getTemplateId(),
+                    params, aUserId, afterSale.getId());
         }
     }
 

+ 10 - 0
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/order/TradeOrderUpdateService.java

@@ -11,8 +11,12 @@ import cn.newfeifan.mall.module.trade.controller.app.order.vo.AppTradeOrderSettl
 import cn.newfeifan.mall.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO;
 import cn.newfeifan.mall.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
 import cn.newfeifan.mall.module.trade.dal.dataobject.order.TradeOrderDO;
+import cn.newfeifan.mall.module.trade.enums.order.TradeOrderOperateTypeEnum;
+import cn.newfeifan.mall.module.trade.framework.order.core.annotations.TradeOrderLog;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.validation.constraints.NotNull;
+import java.util.List;
 
 /**
  * 交易订单【写】Service 接口
@@ -42,6 +46,12 @@ public interface TradeOrderUpdateService {
      */
     TradeOrderDO createOrder(Long userId, AppTradeOrderCreateReqVO createReqVO);
 
+    @Transactional(rollbackFor = Exception.class)
+    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_PAY)
+    //下面的参数中的id1为交易订单TradeOrder表的id,已经没用了,因为一个支付订单对应多个订单。
+    //只有支付订单id参数payOrderId是有用的。
+    List updateOrderPaid(Long payOrderId);
+
     /**
      * 更新交易订单已支付
      *

+ 351 - 144
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/order/TradeOrderUpdateServiceImpl.java

@@ -30,7 +30,9 @@ import cn.newfeifan.mall.module.pay.enums.order.PayOrderStatusEnum;
 import cn.newfeifan.mall.module.product.api.comment.ProductCommentApi;
 import cn.newfeifan.mall.module.product.api.comment.dto.ProductCommentCreateReqDTO;
 import cn.newfeifan.mall.module.product.dal.dataobject.sku.ProductSkuDO;
+import cn.newfeifan.mall.module.product.dal.dataobject.spu.ProductSpuDO;
 import cn.newfeifan.mall.module.product.dal.mysql.sku.ProductSkuMapper;
+import cn.newfeifan.mall.module.product.dal.mysql.spu.ProductSpuMapper;
 import cn.newfeifan.mall.module.sale.dal.dataobject.shop.ShopDO;
 import cn.newfeifan.mall.module.sale.dal.mysql.shop.ShopMapper;
 import cn.newfeifan.mall.module.system.service.user.AdminUserService;
@@ -38,6 +40,7 @@ import cn.newfeifan.mall.module.trade.controller.admin.order.vo.TradeOrderDelive
 import cn.newfeifan.mall.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO;
 import cn.newfeifan.mall.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO;
 import cn.newfeifan.mall.module.trade.controller.admin.order.vo.TradeOrderUpdatePriceReqVO;
+import cn.newfeifan.mall.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO;
 import cn.newfeifan.mall.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
 import cn.newfeifan.mall.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO;
 import cn.newfeifan.mall.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO;
@@ -87,9 +90,10 @@ import static cn.newfeifan.mall.framework.common.exception.util.ServiceException
 import static cn.newfeifan.mall.framework.common.util.collection.CollectionUtils.*;
 import static cn.newfeifan.mall.framework.common.util.date.LocalDateTimeUtils.minusTime;
 import static cn.newfeifan.mall.framework.common.util.servlet.ServletUtils.getClientIP;
+import static cn.newfeifan.mall.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 import static cn.newfeifan.mall.framework.web.core.util.WebFrameworkUtils.getTerminal;
 import static cn.newfeifan.mall.module.trade.enums.ErrorCodeConstants.*;
-
+import static cn.newfeifan.mall.module.trade.enums.delivery.DeliveryTypeEnum.VIRTUAL_PRODUCT;
 
 
 /**
@@ -102,11 +106,14 @@ import static cn.newfeifan.mall.module.trade.enums.ErrorCodeConstants.*;
 @Slf4j
 public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
 
+
     @Resource
     private IntegralMapper integralMapper;//add by ben 20240411
 
     @Resource
     private ProductSkuMapper productSkuMapper;//add by ben 20240314
+    @Resource
+    private ProductSpuMapper productSpuMapper;
 
     @Resource
     private ShopMapper shopMapper;//add by ben 20240314
@@ -163,12 +170,12 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
 
     // =================== Order ===================
 
-
     /**
      * add by Ben
      * 待支付订单,点支付时的新增方法
-     * @param tradeOrderId
-     * @return
+     *
+     * @param tradeOrderId 订单id
+     * @return 支付订单
      */
     public PayOrderDO getPayOrder(Long tradeOrderId) {
 
@@ -177,29 +184,28 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
 
         //页面传入的订单
         TradeOrderDO orderDO = tradeOrderMapper.selectOne("id", tradeOrderId);
-       Long parentPayOrderId = orderDO.getPayOrderId();
+        Long parentPayOrderId = orderDO.getPayOrderId();
 
         //本订单对应的支付订单id,是否是多个订单支付的合并支付订单
         List<TradeOrderDO> tradeOrderList = tradeOrderMapper.selectList("pay_order_id", parentPayOrderId);
-        if(tradeOrderList.size()==1){//如果一个支付单只对应一个订单,证明不是合并支付订单
+        if (tradeOrderList.size() == 1) {//如果一个支付单只对应一个订单,证明不是合并支付订单
 
             thisPayOrderDO = payOrderMapper.selectById(parentPayOrderId);
 //            rs = thisPayOrderDO;
-        }else if(tradeOrderList.size()>1){//如果一个支付单对应多个订单,证明是合并支付订单,则生成其下级拆分支付的支付单
+        } else if (tradeOrderList.size() > 1) {//如果一个支付单对应多个订单,证明是合并支付订单,则生成其下级拆分支付的支付单
 
             PayOrderDO parentPayOrderDO = payOrderMapper.selectById(parentPayOrderId);
             LocalDateTime expireTime = parentPayOrderDO.getExpireTime();//原合并支付订单的过期时间
 
-            for (int i = 0; i < tradeOrderList.size(); i++) {
-                TradeOrderDO tradeOrderDO = tradeOrderList.get(i);
+            for (TradeOrderDO tradeOrderDO : tradeOrderList) {
                 Long tId = tradeOrderDO.getId();
                 List<TradeOrderItemDO> tradeOrderItemDOS = tradeOrderItemMapper.selectList("order_id", tId);
 
                 //创建子支付订单,并且让trade_order记录关联子支付订单
                 Long childPayOrderId = createChildPayOrder(tradeOrderDO, tradeOrderItemDOS,
-                        parentPayOrderId,expireTime);
+                        parentPayOrderId, expireTime);
 
-                if(tId==tradeOrderId){//如果当前为页面传入的订单
+                if (Objects.equals(tId, tradeOrderId)) {//如果当前为页面传入的订单
                     thisPayOrderDO = payOrderMapper.selectById(childPayOrderId);
                 }
             }
@@ -220,68 +226,73 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
     @Override
     public AppTradeOrderSettlementRespVO settlementOrder(Long userId, AppTradeOrderSettlementReqVO settlementReqVO) {
         // 1. 获得收货地址
-        MemberAddressRespDTO address = getAddress(userId, settlementReqVO.getAddressId());
+        MemberAddressRespDTO address = getAddress(userId, settlementReqVO.getAddressId(), settlementReqVO.getAddressType());
         if (address != null) {
             settlementReqVO.setAddressId(address.getId());
         }
 
+        //如果是虚拟商品,则用自己的编写的程序返回
+        if (Objects.equals(settlementReqVO.getDeliveryType(), VIRTUAL_PRODUCT.getType())) {
+            return getSettlement(address, settlementReqVO.getItems());
+        }
+
         // add by Ben 20240314
         // 4. 查询每个sku对应的店铺ID,并传回页面
         List<AppTradeOrderSettlementReqVO.Item> productSkuList = settlementReqVO.getItems();
-        List<Long> productSkuIdList = new ArrayList<Long>();
-        Map<Long,AppTradeOrderSettlementReqVO.Item> itemMap = new HashMap<Long,AppTradeOrderSettlementReqVO.Item>();
-        for(AppTradeOrderSettlementReqVO.Item skuItem : productSkuList){
+        List<Long> productSkuIdList = new ArrayList<>();
+        Map<Long, AppTradeOrderSettlementReqVO.Item> itemMap = new HashMap<>();
+        for (AppTradeOrderSettlementReqVO.Item skuItem : productSkuList) {
             productSkuIdList.add(skuItem.getSkuId());
-            itemMap.put(skuItem.getSkuId(),skuItem);
+            itemMap.put(skuItem.getSkuId(), skuItem);
         }
         // 查询每个skuid对应的sku对象
         List<ProductSkuDO> productSkuDOList = productSkuMapper.selectListBySKuId(productSkuIdList);
 
         //key为店铺ID,value为skuid的List
-        Map<Long,List<Long>> shopSkuIds = new HashMap<Long, List<Long>>();
+        Map<Long, List<Long>> shopSkuIds = new HashMap<>();
         //key为店铺ID,value为item的Map
-        Map<Long,List<AppTradeOrderSettlementReqVO.Item>> shopSkuItemMap = new HashMap<Long,List<AppTradeOrderSettlementReqVO.Item>>();
+        Map<Long, List<AppTradeOrderSettlementReqVO.Item>> shopSkuItemMap = new HashMap<>();
 
-        for(ProductSkuDO sku:productSkuDOList){//把sku根据店聚合放到map中
+        for (ProductSkuDO sku : productSkuDOList) {//把sku根据店聚合放到map中
             Long skuId = sku.getId();
             Long shopId = sku.getShopId();
 
             List<AppTradeOrderSettlementReqVO.Item> itemList = shopSkuItemMap.get(shopId);
-            if(itemList==null){
-                itemList=new ArrayList<AppTradeOrderSettlementReqVO.Item>();
-                shopSkuItemMap.put(shopId,itemList);
+            if (itemList == null) {
+                itemList = new ArrayList<>();
+                shopSkuItemMap.put(shopId, itemList);
             }
 //            AppTradeOrderSettlementReqVO.Item item = new AppTradeOrderSettlementReqVO.Item();
             itemList.add(itemMap.get(skuId));
 
             List<Long> shopSkuList = shopSkuIds.get(shopId);
-            if(shopSkuList==null) {
-                shopSkuList = new ArrayList<Long>();
-                shopSkuIds.put(shopId,shopSkuList);
+            if (shopSkuList == null) {
+                shopSkuList = new ArrayList<>();
+                shopSkuIds.put(shopId, shopSkuList);
             }
             shopSkuList.add(skuId);//把sku根据店聚合放到map中
         }
 
 
         //把店铺id和店铺名称查出来放到map中
-        List<Long> shopIds = new ArrayList<Long>();
+        List<Long> shopIds = new ArrayList<>();
         for (Long shopid : shopSkuIds.keySet()) {
             shopIds.add(shopid);
         }
         List<ShopDO> shopDOList = shopMapper.selectListById(shopIds);
-        Map<Long,String> shopNameMap = new HashMap<Long,String>();//key为店铺id,value为店铺名
+        Map<Long, String> shopNameMap = new HashMap<>();//key为店铺id,value为店铺名
         for (ShopDO shopDO : shopDOList) {
-            shopNameMap.put(shopDO.getId(),shopDO.getName());
+            shopNameMap.put(shopDO.getId(), shopDO.getName());
         }
 
         // 2. 计算价格
-        /**
-         * add by Ben 20240402
-         * 原来下面的代码中是取settlementReqVO.getItems()的所有项计算的,其中Items含不同店铺的商品,现在要把不同店铺的商品分开计算
-         *
+        /*
+          add by Ben 20240402
+          原来下面的代码中是取settlementReqVO.getItems()的所有项计算的,其中Items含不同店铺的商品,现在要把不同店铺的商品分开计算
+
          */
         //保存每个店铺返回页面的 订单信息汇总
-        Map<Long,AppTradeOrderSettlementRespVO> shopRespVOMap = new HashMap<Long,AppTradeOrderSettlementRespVO>();
+        Map<Long, AppTradeOrderSettlementRespVO> shopRespVOMap = new HashMap<>();
         //所有店铺支付总价
         Integer allShopPayPrice = 0;
         //所有店商品不算运费的商品总价
@@ -290,7 +301,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         Integer allShopDeliveryPrice = 0;
 
         //循环计算各个店铺的价格
-        for(Long shopId:shopSkuItemMap.keySet()){
+        for (Long shopId : shopSkuItemMap.keySet()) {
             List<AppTradeOrderSettlementReqVO.Item> items = shopSkuItemMap.get(shopId);
             AppTradeOrderSettlementReqVO shopSettlementReqVO = new AppTradeOrderSettlementReqVO();
             BeanUtils.copyProperties(settlementReqVO, shopSettlementReqVO);
@@ -301,7 +312,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
             TradePriceCalculateRespBO shopCalculateRespBO = calculatePrice(userId, shopSettlementReqVO);
             // 3. 拼接返回
             AppTradeOrderSettlementRespVO respVO = TradeOrderConvert.INSTANCE.convert(shopCalculateRespBO, address);
-            shopRespVOMap.put(shopId,respVO);
+            shopRespVOMap.put(shopId, respVO);
 
             //所有店铺支付总价
             allShopPayPrice += shopCalculateRespBO.getPrice().getPayPrice();
@@ -330,7 +341,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         AppTradeOrderSettlementRespVO respVO = TradeOrderConvert.INSTANCE.convert(calculateRespBO, address);
 
         //把重复的收货地址置为空
-        for(Long shopId:shopRespVOMap.keySet()){
+        for (Long shopId : shopRespVOMap.keySet()) {
             AppTradeOrderSettlementRespVO a = shopRespVOMap.get(shopId);
             a.setAddress(null);
         }
@@ -347,18 +358,129 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         return respVO;
     }
 
+    /**
+     * 虚拟商品自走程序
+     *
+     * @param address
+     * @param items   商品项数组
+     * @return AppTradeOrderSettlementRespVO
+     */
+    private AppTradeOrderSettlementRespVO getSettlement(MemberAddressRespDTO address, List<AppTradeOrderSettlementReqVO.Item> items) {
+
+        // 4. 查询每个sku对应的店铺ID,并传回页面
+        List<AppTradeOrderSettlementReqVO.Item> productSkuList = items;
+        List<Long> productSkuIdList = new ArrayList<>();
+        Map<Long, AppTradeOrderSettlementReqVO.Item> itemMap = new HashMap<>();
+        for (AppTradeOrderSettlementReqVO.Item skuItem : productSkuList) {
+            productSkuIdList.add(skuItem.getSkuId());
+            itemMap.put(skuItem.getSkuId(), skuItem);
+        }
+        // 查询每个skuid对应的sku对象
+        List<ProductSkuDO> productSkuDOList = productSkuMapper.selectListBySKuId(productSkuIdList);
+
+        //key为店铺ID,value为skuid的List
+        Map<Long, List<Long>> shopSkuIds = new HashMap<>();
+        //key为店铺ID,value为item的Map
+        Map<Long, List<AppTradeOrderSettlementReqVO.Item>> shopSkuItemMap = new HashMap<>();
+
+        for (ProductSkuDO sku : productSkuDOList) {//把sku根据店聚合放到map中
+            Long skuId = sku.getId();
+            Long shopId = sku.getShopId();
+
+            List<AppTradeOrderSettlementReqVO.Item> itemList = shopSkuItemMap.get(shopId);
+            if (itemList == null) {
+                itemList = new ArrayList<>();
+                shopSkuItemMap.put(shopId, itemList);
+            }
+//            AppTradeOrderSettlementReqVO.Item item = new AppTradeOrderSettlementReqVO.Item();
+            itemList.add(itemMap.get(skuId));
+
+            List<Long> shopSkuList = shopSkuIds.get(shopId);
+            if (shopSkuList == null) {
+                shopSkuList = new ArrayList<>();
+                shopSkuIds.put(shopId, shopSkuList);
+            }
+            shopSkuList.add(skuId);//把sku根据店聚合放到map中
+        }
+
+
+        //把店铺id和店铺名称查出来放到map中
+        List<Long> shopIds = new ArrayList<>();
+        for (Long shopid : shopSkuIds.keySet()) {
+            shopIds.add(shopid);
+        }
+        List<ShopDO> shopDOList = shopMapper.selectListById(shopIds);
+        Map<Long, String> shopNameMap = new HashMap<>();//key为店铺id,value为店铺名
+        for (ShopDO shopDO : shopDOList) {
+            shopNameMap.put(shopDO.getId(), shopDO.getName());
+        }
+
+        AppTradeOrderSettlementRespVO respVO = new AppTradeOrderSettlementRespVO();
+        respVO.setShopNameMap(shopNameMap);
+        respVO.setShopSkuIds(shopSkuIds);
+        IntegralDO integralDO = integralMapper.selectOne("user_id", getLoginUserId());//查询出用户积分相关信息
+        Long currentQuota = integralDO.getCurrentQuota();//获取用户当前积分
+        respVO.setCurrentQuota(currentQuota);
+
+        //保存每个店铺返回页面的 订单信息汇总
+        Map<Long, AppTradeOrderSettlementRespVO> shopRespVOMap = new HashMap<>();
+        //所有店铺支付总价
+        AppTradeOrderSettlementRespVO.Price shopCalculateRespBO = new AppTradeOrderSettlementRespVO.Price();
+
+        //循环计算各个店铺的价格
+        for (Long shopId : shopSkuItemMap.keySet()) {
+            List<AppTradeOrderSettlementReqVO.Item> orderItems = shopSkuItemMap.get(shopId);
+
+            AppTradeOrderSettlementRespVO respVO2 = new AppTradeOrderSettlementRespVO();
+            respVO2.setPrice(shopCalculateRespBO);
+            AppTradeOrderSettlementRespVO.Item item = new AppTradeOrderSettlementRespVO.Item();
+            ProductSkuDO sku = productSkuMapper.selectById(orderItems.get(0).getSkuId());
+            ProductSpuDO spu = productSpuMapper.selectById(sku.getSpuId());
+            item.setPrice(sku.getPrice());
+            item.setHighPrecisionPrice(sku.getHighPrecisionPrice());
+            item.setCount(orderItems.get(0).getCount());
+            item.setPicUrl(sku.getPicUrl());
+            item.setSpuId(sku.getSpuId());
+            item.setSkuId(sku.getId().intValue());
+            item.setSpuName(spu.getName());
+            item.setCategoryId(spu.getCategoryId());
+            List<ProductSkuDO.Property> properties = sku.getProperties();
+            item.setProperties(cn.newfeifan.mall.framework.common.util.object.BeanUtils.toBean(properties, AppProductPropertyValueDetailRespVO.class));
+
+            respVO2.setItems(Arrays.asList(item));
+            //计算价格
+            shopRespVOMap.put(shopId, respVO2);
+            shopCalculateRespBO.setVirtualPayPrice(sku.getHighPrecisionPrice().doubleValue() * orderItems.get(0).getCount());
+            shopCalculateRespBO.setVirtualTotalPrice(sku.getHighPrecisionPrice().doubleValue() * orderItems.get(0).getCount());
+            shopCalculateRespBO.setPayPrice((int) sku.getHighPrecisionPrice().doubleValue() * orderItems.get(0).getCount());
+            shopCalculateRespBO.setTotalPrice((int) sku.getHighPrecisionPrice().doubleValue() * orderItems.get(0).getCount());
+        }
+
+        //把重复的收货地址置为空
+        for (Long shopId : shopRespVOMap.keySet()) {
+            AppTradeOrderSettlementRespVO a = shopRespVOMap.get(shopId);
+            a.setAddress(null);
+        }
+
+        respVO.setShopRespVOMap(shopRespVOMap);
+        respVO.setPrice(shopCalculateRespBO);
+        respVO.setAddress(cn.newfeifan.mall.framework.common.util.object.BeanUtils.toBean(address, AppTradeOrderSettlementRespVO.Address.class));
+        return respVO;
+    }
+
     /**
      * 获得用户地址
      *
-     * @param userId    用户编号
-     * @param addressId 地址编号
+     * @param userId      用户编号
+     * @param addressId   地址编号
+     * @param addressType 地址类别
      * @return 地址
      */
-    private MemberAddressRespDTO getAddress(Long userId, Long addressId) {
+    private MemberAddressRespDTO getAddress(Long userId, Long addressId, Integer addressType) {
         if (addressId != null) {
-            return addressApi.getAddress(addressId, userId);
+            return addressApi.getAddress(addressId, userId, addressType);
         }
-        return addressApi.getDefaultAddress(userId);
+        return addressApi.getDefaultAddress(userId, addressType);
     }
 
     /**
@@ -383,7 +505,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
     }
 
 
-
     /**
      * add by Ben
      * 计算订单含积分的各项商品价格
@@ -407,18 +528,18 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
     }
 
     //把数据库的钱转换为数据库的积分
-    public static BigDecimal money2Integral(BigDecimal money){
+    public static BigDecimal money2Integral(BigDecimal money) {
         return money.multiply(DistriConstants.MONEY2INTEGRAL_BIG_DECIMAL);
     }
 
     //把数据库的钱转换为数据库的积分
-    public static Long money2Integral(Integer money){
-        return Long.valueOf(money*DistriConstants.MONEY2INTEGRAL);
+    public static Long money2Integral(Integer money) {
+        return Long.valueOf(money * DistriConstants.MONEY2INTEGRAL);
     }
 
     //把数据库的积分转换为数据库的钱
-    public static Integer integral2Money(Long integral){
-        Long l = (integral/DistriConstants.MONEY2INTEGRAL);
+    public static Integer integral2Money(Long integral) {
+        Long l = (integral / DistriConstants.MONEY2INTEGRAL);
         return l.intValue();
     }
 
@@ -431,23 +552,23 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         //查询订单提成比例
         QueryWrapper<OrderPercentageDO> queryWrapper = new QueryWrapper<>();
         OrderPercentageDO orderPercentageDO = orderPercentageMapper.selectOne(queryWrapper);//表中只有一条记录
-        /**
+        /*
          * 毛利 = 成本 * 0.38... (推广费用)
          */
         String grossProfitPerc = orderPercentageDO.getGrossProfitPerc();
         float grossProfitPercFloat = Float.parseFloat(grossProfitPerc);
-        if(grossProfitPercFloat>1){
-            throw new RuntimeException("商品毛利值,占利润比例异常,达到"+grossProfitPerc+"!!");
+        if (grossProfitPercFloat > 1) {
+            throw new RuntimeException("商品毛利值,占利润比例异常,达到" + grossProfitPerc + "!!");
         }
 
 
-        /**
+        /*
          * 购物本人自得 百分比
          */
         String grossProfitUserQuotaPerc = orderPercentageDO.getGrossProfitUserQuotaPerc();
         float grossProfitUserQuotaPercFloat = Float.parseFloat(grossProfitUserQuotaPerc);
-        if(grossProfitUserQuotaPercFloat>0.5){
-            throw new RuntimeException("消费本人获得积分,占毛利比例异常,达到"+grossProfitUserQuotaPerc+"!!");
+        if (grossProfitUserQuotaPercFloat > 0.5) {
+            throw new RuntimeException("消费本人获得积分,占毛利比例异常,达到" + grossProfitUserQuotaPerc + "!!");
         }
 
         //校验最大值 end
@@ -457,43 +578,42 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         // 4. 查询每个sku对应的店铺ID,并传回页面
         List<AppTradeOrderSettlementReqVO.Item> productSkuList = createReqVO.getItems();
         // 把所有商品的id都取出来,为查询所有商品的店铺做准备
-        List<Long> productSkuIdList = new ArrayList<Long>();
-        Map<Long,AppTradeOrderSettlementReqVO.Item> itemMap = new HashMap<Long,AppTradeOrderSettlementReqVO.Item>();
-        for(AppTradeOrderSettlementReqVO.Item skuItem : productSkuList){
+        List<Long> productSkuIdList = new ArrayList<>();
+        Map<Long, AppTradeOrderSettlementReqVO.Item> itemMap = new HashMap<>();
+        for (AppTradeOrderSettlementReqVO.Item skuItem : productSkuList) {
             productSkuIdList.add(skuItem.getSkuId());
-            itemMap.put(skuItem.getSkuId(),skuItem);
+            itemMap.put(skuItem.getSkuId(), skuItem);
         }
         // 查询每个skuid对应的sku对象
         List<ProductSkuDO> productSkuDOList = productSkuMapper.selectListBySKuId(productSkuIdList);
 
-        Map<Long,Long> shopMerchantMap = new HashMap<Long,Long>();//key是店铺ID,value是商户ID
-        for(ProductSkuDO productSkuDO:productSkuDOList){
-            shopMerchantMap.put(productSkuDO.getShopId(),productSkuDO.getMerchantId());
+        Map<Long, Long> shopMerchantMap = new HashMap<>();//key是店铺ID,value是商户ID
+        for (ProductSkuDO productSkuDO : productSkuDOList) {
+            shopMerchantMap.put(productSkuDO.getShopId(), productSkuDO.getMerchantId());
         }
 
         //key为店铺ID,value为skuid的List
-        Map<Long,List<Long>> shopSkuIds = new HashMap<Long, List<Long>>();
+        Map<Long, List<Long>> shopSkuIds = new HashMap<>();
         //key为店铺ID,value为item的Map
-        Map<Long,List<AppTradeOrderSettlementReqVO.Item>> shopSkuItemMap = new HashMap<Long,List<AppTradeOrderSettlementReqVO.Item>>();
-
+        Map<Long, List<AppTradeOrderSettlementReqVO.Item>> shopSkuItemMap = new HashMap<>();
 
 
-        for(ProductSkuDO sku:productSkuDOList){//把sku根据店聚合放到map中
+        for (ProductSkuDO sku : productSkuDOList) {//把sku根据店聚合放到map中
             Long skuId = sku.getId();
             Long shopId = sku.getShopId();
 
             List<AppTradeOrderSettlementReqVO.Item> itemList = shopSkuItemMap.get(shopId);
-            if(itemList==null){
-                itemList=new ArrayList<AppTradeOrderSettlementReqVO.Item>();
-                shopSkuItemMap.put(shopId,itemList);
+            if (itemList == null) {
+                itemList = new ArrayList<>();
+                shopSkuItemMap.put(shopId, itemList);
             }
 //            AppTradeOrderSettlementReqVO.Item item = new AppTradeOrderSettlementReqVO.Item();
             itemList.add(itemMap.get(skuId));
 
             List<Long> shopSkuList = shopSkuIds.get(shopId);
-            if(shopSkuList==null) {
-                shopSkuList = new ArrayList<Long>();
-                shopSkuIds.put(shopId,shopSkuList);
+            if (shopSkuList == null) {
+                shopSkuList = new ArrayList<>();
+                shopSkuIds.put(shopId, shopSkuList);
             }
             shopSkuList.add(skuId);//把sku根据店聚合放到map中
         }
@@ -501,18 +621,18 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
 
         //add by Ben
         //为键值对,键为店铺ID,值为备注文本
-        Map<Long,String> shopRemarks = createReqVO.getShopRemarks();
-        if(shopRemarks==null){
-            shopRemarks = new HashMap<Long,String>();
+        Map<Long, String> shopRemarks = createReqVO.getShopRemarks();
+        if (shopRemarks == null) {
+            shopRemarks = new HashMap<>();
         }
 
         //消费者在页面录入的,要使用的积分
-        Long payPoints = createReqVO.getPayIntegral();
+        Double payPoints = createReqVO.getPayIntegral();
 
-        if(payPoints == null){
-            payPoints = 0l;
-        }else{//把页面传入的,1积分=1元钱的积分,转换为后台保存到数据库的积分值
-            payPoints = payPoints* DistriConstants.INTEGRAL_PAGE2DB;
+        if (payPoints == null) {
+            payPoints = (double) 0;
+        } else {//把页面传入的,1积分=1元钱的积分,转换为后台保存到数据库的积分值
+            payPoints = payPoints * DistriConstants.INTEGRAL_PAGE2DB;
         }
 
 
@@ -521,9 +641,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         //计算订单含积分的各项商品价格
         TradePriceCalculateRespBO tradePriceCalculateRespBO = calculatePriceWithPoints(userId, createReqVO);
         //计算分摊的积分金额
-        List<Integer> dividePoints = TradePriceCalculatorHelper.dividePrice(tradePriceCalculateRespBO.getItems(), integral2Money(payPoints));
+        List<Integer> dividePoints = TradePriceCalculatorHelper.dividePrice(tradePriceCalculateRespBO.getItems(), integral2Money(payPoints.longValue()));
         //键为skuId,value为单个商品项信息
-        Map<Long, TradePriceCalculateRespBO.OrderItem> itemPayPointsMap = new HashMap<Long, TradePriceCalculateRespBO.OrderItem>();
+        Map<Long, TradePriceCalculateRespBO.OrderItem> itemPayPointsMap = new HashMap<>();
 
         //订单项数组
         List<TradePriceCalculateRespBO.OrderItem> priceOrderItems = tradePriceCalculateRespBO.getItems();
@@ -531,16 +651,16 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
             TradePriceCalculateRespBO.OrderItem orderItem = priceOrderItems.get(i);
             Long itemPoint = money2Integral(dividePoints.get(i));//每项商品使用的积分
             orderItem.setPayPoints(itemPoint);
-            itemPayPointsMap.put(orderItem.getSkuId(),orderItem);
+            itemPayPointsMap.put(orderItem.getSkuId(), orderItem);
         }
 
         Integer allShopPayRMB = 0;//所有店铺订单实际支付的金额
 
-        List<Map<String,Object>> orderMapList = new ArrayList<Map<String,Object>>();
+        List<Map<String, Object>> orderMapList = new ArrayList<>();
 
         //循环调用原来的计算订单价格方法,计算价格
         //循环一次生成一间店的订单
-        for(Long shopId:shopSkuItemMap.keySet()){
+        for (Long shopId : shopSkuItemMap.keySet()) {
 
             AppTradeOrderCreateReqVO shopCreateReqVO = new AppTradeOrderCreateReqVO();
 
@@ -558,6 +678,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
             TradeOrderDO order = buildTradeOrder(userId, shopCreateReqVO, calculateRespBO);
             List<TradeOrderItemDO> orderItems = buildTradeOrderItems(order, calculateRespBO);
 
+            for (TradeOrderItemDO orderItem : orderItems) {
+                ProductSkuDO productSkuDO = productSkuMapper.selectById(orderItem.getSkuId());
+                orderItem.setHighPrecisionPrice(productSkuDO.getHighPrecisionPrice());
+            }
+
             // 2. 订单创建前的逻辑
             //修改sku库存
             tradeProductSkuOrderHandler.beforeOrderCreate(order, orderItems);
@@ -565,10 +690,10 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
 //            tradeOrderHandlers.forEach(handler -> handler.beforeOrderCreate(order, orderItems));
 
             // 3. 保存一间店铺的订单
-            Long shopPayPoints = 0l;//一间店铺订单总支付积分
+            Long shopPayPoints = 0L;//一间店铺订单总支付积分
             Integer shopPayPrice = 0;//一间店铺订单总支付价格
 
-            for(TradeOrderItemDO orderItem:orderItems){//一间店铺订单的所有商品项
+            for (TradeOrderItemDO orderItem : orderItems) {//一间店铺订单的所有商品项
 //                orderItem.setOrderId(order.getId());
 
                 //3.5 add by Ben
@@ -576,7 +701,20 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
                 Long skuId = orderItem.getSkuId();
                 TradePriceCalculateRespBO.OrderItem orderItemTmp = itemPayPointsMap.get(skuId);
                 orderItem.setPayIntegral(orderItemTmp.getPayPoints()); //本商品使用积分
-                Integer payRmb = orderItem.getPrice()*orderItem.getCount()-integral2Money(orderItemTmp.getPayPoints());//本商品实付人民币
+                Integer payRmb;
+                if (orderItem.getHighPrecisionPrice() == null) {
+                    payRmb = orderItem.getPrice() * orderItem.getCount() - integral2Money(orderItemTmp.getPayPoints());//本商品实付人民币
+                } else {
+                    double rmb = (orderItem.getHighPrecisionPrice().doubleValue() * orderItem.getCount()) - integral2Money(orderItemTmp.getPayPoints());
+                    if (rmb > 0 && rmb < 1) {
+                        payRmb = 1;
+                    }else{
+                        double multiplied = rmb * 10;
+                        // 对乘以10后的数使用 Math.ceil() 向上取整
+                        double roundedUp = Math.ceil(multiplied);
+                        payRmb = (int)(roundedUp/10.0);
+                    }
+                }
                 orderItem.setPayRmb(payRmb);//本商品实付人民币
                 orderItem.setPayPrice(payRmb);//本商品实付人民币
 
@@ -584,9 +722,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
                 shopPayPrice += payRmb;//一间店铺订单总支付价格
             }
 
-            shopPayPrice+=order.getDeliveryPrice();//店铺支付总金额,加上运费
+            shopPayPrice += order.getDeliveryPrice();//店铺支付总金额,加上运费
 
-            allShopPayRMB +=shopPayPrice;
+            allShopPayRMB += shopPayPrice;
 
             Long merchantId = shopMerchantMap.get(shopId);//商户ID
 
@@ -594,7 +732,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
             order.setShopId(shopId);
             order.setPayPrice(shopPayPrice);
             order.setPayRmb(shopPayPrice);
-            order.setPayIntegral(shopPayPoints);
+            order.setPayIntegral(shopPayPoints.doubleValue());
 
             tradeOrderMapper.insert(order);
 
@@ -605,46 +743,46 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
             afterCreateTradeOrder(order, orderItems, shopCreateReqVO);
 
 //            Map<>
-            Map<String,Object> orderMap = new HashMap<String,Object>();
-            orderMap.put("order",order);
-            orderMap.put("orderItems",orderItems);
+            Map<String, Object> orderMap = new HashMap<>();
+            orderMap.put("order", order);
+            orderMap.put("orderItems", orderItems);
             orderMapList.add(orderMap);//把订单保存起来,为支付订单做准备
         }
 
         TradeOrderDO virtualOrder = new TradeOrderDO();//为了生成支付订单,创建的虚拟订单,本订单不会保存到数据库
-        TradeOrderDO firstOrder = (TradeOrderDO)(orderMapList.get(0).get("order"));
-        List<TradeOrderItemDO> firstOrderItems = (List<TradeOrderItemDO>)(orderMapList.get(0).get("orderItems"));
+        TradeOrderDO firstOrder = (TradeOrderDO) (orderMapList.get(0).get("order"));
+        List<TradeOrderItemDO> firstOrderItems = (List<TradeOrderItemDO>) (orderMapList.get(0).get("orderItems"));
 
         BeanUtils.copyProperties(firstOrder, virtualOrder);
         virtualOrder.setPayPrice(allShopPayRMB);
         virtualOrder.setPayRmb(allShopPayRMB);
 
         Integer shopCount = shopSkuIds.keySet().size();//订单对应的店铺数目
-        if(shopCount>1) {//如果多店铺拆分订单,则支付订单的商户订单id为0
-            virtualOrder.setId(0l);//为了让payOrder中的tradeOrderId为0;
-        } else if (shopCount==1) {
+        if (shopCount > 1) {//如果多店铺拆分订单,则支付订单的商户订单id为0
+            virtualOrder.setId(0L);//为了让payOrder中的tradeOrderId为0;
+        } else if (shopCount == 1) {
             virtualOrder.setId(firstOrder.getId());//为了指定payOrder中的tradeOrderId;
-        }else{
-            throw new RuntimeException("订单id"+firstOrder.getId()+",对应一间店铺都没");
+        } else {
+            throw new RuntimeException("订单id" + firstOrder.getId() + ",对应一间店铺都没");
         }
 
         // 3. 生成预支付:生成支付订单记录
         Long payOrderId = createPayOrder(virtualOrder, firstOrderItems);
 
-        for(Map<String,Object> m:orderMapList){
-            TradeOrderDO order = (TradeOrderDO)(m.get("order"));
+        for (Map<String, Object> m : orderMapList) {
+            TradeOrderDO order = (TradeOrderDO) (m.get("order"));
             // 更新到交易单上
             tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setPayOrderId(payOrderId));
         }
 
         //如果订单有使用积分,则抵扣用户的积分。add by Ben
-        if(payPoints>0){
-            for(Map<String,Object> m:orderMapList) {
+        if (payPoints > 0) {
+            for (Map<String, Object> m : orderMapList) {
                 TradeOrderDO order = (TradeOrderDO) (m.get("order"));
                 Long tradeOrderId = order.getId();
-                String OrderNum =order.getNo();
-                Long payIntegral = order.getPayIntegral();//每个订单使用的积分
-                integralService.updateUserIntegral(userId, CaclEnum.ORDER_PAY_INTEGRAL, payIntegral * (-1), 0l, tradeOrderId, OrderNum);
+                String OrderNum = order.getNo();
+                Long payIntegral = order.getPayIntegral().longValue();//每个订单使用的积分
+                integralService.updateUserIntegral(userId, userId, CaclEnum.ORDER_PAY_INTEGRAL, payIntegral * (-1), 0L, tradeOrderId, OrderNum);
             }
         }
 
@@ -716,22 +854,28 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         return virtualOrder;
     }
 
+
     /**
-     * 把商品的推广费总额,转换为直推人获得的冻结积分
+     * 把商品的推广费总额,转换为消费者本人(直推人)、或消费者的推荐人 获得的冻结积分
+     *
      * @param promotionExpenses 商品的推广费总额
+     * @param grossProfitPerc   推荐人/消费者本人额度 百分比
      * @return 输入推广费,对应的直推人获得的冻结积分
      */
     public static Long promotionExpenses2GrossProfitAncestorQuota(
+            /*
+            商品的推广费总额
+             */
             Integer promotionExpenses,
-            /**
+            /*
              * 毛利 = 成本 * 0.38... (推广费用)
              */
             String grossProfitPerc,
-            /**
-             * 推广-推荐人额度 百分比
+            /*
+             * 推广-推荐人/消费者本人额度 百分比
              */
             String grossProfitAncestorQuotaPerc
-            ){
+    ) {
 
         //转为BigDecimal
         BigDecimal profit = new BigDecimal(String.valueOf(promotionExpenses));
@@ -766,13 +910,17 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         // 物流信息
         order.setDeliveryType(createReqVO.getDeliveryType());
         if (Objects.equals(createReqVO.getDeliveryType(), DeliveryTypeEnum.EXPRESS.getType())) {
-            MemberAddressRespDTO address = addressApi.getAddress(createReqVO.getAddressId(), userId);
+            MemberAddressRespDTO address = addressApi.getAddress(createReqVO.getAddressId(), userId, 1);
             Assert.notNull(address, "地址({}) 不能为空", createReqVO.getAddressId()); // 价格计算时,已经计算
             order.setReceiverName(address.getName()).setReceiverMobile(address.getMobile())
                     .setReceiverAreaId(address.getAreaId()).setReceiverDetailAddress(address.getDetailAddress());
         } else if (Objects.equals(createReqVO.getDeliveryType(), DeliveryTypeEnum.PICK_UP.getType())) {
             order.setReceiverName(createReqVO.getReceiverName()).setReceiverMobile(createReqVO.getReceiverMobile());
             order.setPickUpVerifyCode(RandomUtil.randomNumbers(8)); // 随机一个核销码,长度为 8 位
+        } else if (Objects.equals(createReqVO.getDeliveryType(), VIRTUAL_PRODUCT.getType())) {
+            MemberAddressRespDTO address = addressApi.getAddress(createReqVO.getAddressId(), userId, 2);
+            order.setReceiverName(address.getName()).setReceiverMobile(address.getMobile())
+                    .setReceiverDetailAddress(address.getDetailAddress());
         }
         return order;
     }
@@ -816,14 +964,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
 
     /**
      * 创建子支付订单
-     * @param order
-     * @param orderItems
-     * @param parentPayOrderId  父级支付订单id
-     * @param expireTime  支付过期时间
-     * @return
+     *
+     * @param order            订单
+     * @param orderItems       订单详情
+     * @param parentPayOrderId 父级支付订单id
+     * @param expireTime       支付过期时间
+     * @return 支付订单ID
      */
     private Long createChildPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems,
-                                     Long parentPayOrderId,LocalDateTime expireTime) {
+                                     Long parentPayOrderId, LocalDateTime expireTime) {
         // 创建支付单,用于后续的支付
         PayOrderCreateReqDTO payOrderCreateReqDTO = TradeOrderConvert.INSTANCE.convert(
                 order, orderItems, tradeOrderProperties);
@@ -861,37 +1010,50 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         return payOrderId;//返回支付订单ID
     }
 
+
     @Override
-    @Transactional(rollbackFor = Exception.class)
     @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_PAY)
-    //下面的参数中的id1为交易订单TradeOrder表的id,已经没用了,因为一个支付订单对应多个订单。
     //只有支付订单id参数payOrderId是有用的。
-    public void updateOrderPaid(Long id1, Long payOrderId) {
-
+    public List updateOrderPaid(Long payOrderId) {
 
 //        System.out.println("#########updateOrderPaid####payOrderId:"+payOrderId);
 
+        List rs = new ArrayList();
+
         //查询订单提成比例
         QueryWrapper<OrderPercentageDO> queryWrapper = new QueryWrapper<>();
         OrderPercentageDO orderPercentageDO = orderPercentageMapper.selectOne(queryWrapper);//表中只有一条记录
-        /**
+
+        /*
          * 毛利 = 成本 * 0.38... (推广费用)
          */
         String grossProfitPerc = orderPercentageDO.getGrossProfitPerc();
 
+        Integer allTradeOrderTotalPrice = 0;//所有订单的总金额
+        Long allTradeOrderTotalFreezeAmount = 0L;//所有订单用户总的冻结积分
 
-
-        /**
+        /*
          * 购物本人自得 百分比
          */
         String grossProfitUserQuotaPerc = orderPercentageDO.getGrossProfitUserQuotaPerc();
 
+        /*
+         * 推荐人(上一级) 百分比
+         */
+        String grossProfitAncestorQuotaPerc = orderPercentageDO.getGrossProfitAncestorQuotaPerc();
+
         //add by Ben 根据支付订单id,查询所有 支付订单 对应的 订单
         List<TradeOrderDO> TradeOrderDOList = tradeOrderMapper.selectList("pay_order_id", payOrderId);
 
-        for(TradeOrderDO tradeOrderDO:TradeOrderDOList) {
+        //购物者ID
+        Long memberUserIdOfTradeOrder = TradeOrderDOList.get(0).getUserId();
+        //20240604 推荐人(上级用户ID)
+        Long ancesterUserId = tradeOrderMapper.selectAncesterByMemberUserId(memberUserIdOfTradeOrder);
+
+        for (TradeOrderDO tradeOrderDO : TradeOrderDOList) {
 
             Long tradeOrderId = tradeOrderDO.getId();
+            allTradeOrderTotalPrice += tradeOrderDO.getTotalPrice();
 
 //            System.out.println("#########updateOrderPaid####tradeOrderId:"+tradeOrderId);
 
@@ -936,17 +1098,20 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
             }
 
             List<ProductSkuDO> productSkuDOS = productSkuMapper.selectBatchIds(skuList);
-            Map<Long,ProductSkuDO> skuDOMap = new HashMap<Long,ProductSkuDO>();
+            Map<Long, ProductSkuDO> skuDOMap = new HashMap<>();
             for (ProductSkuDO productSkuDO : productSkuDOS) {
-                skuDOMap.put(productSkuDO.getId(),productSkuDO);
+                skuDOMap.put(productSkuDO.getId(), productSkuDO);
             }
 
-            Long totalFreezeAmount = 0l;//用户总的冻结积分
+            Long totalFreezeAmount = 0L;//用户总的冻结积分
+
+            Long totalAncestorFreezeAmount = 0L;//推荐人总的冻结积分
+
             for (TradeOrderItemDO tradeOrderItemDO : TradeOrderItemList) {
                 ProductSkuDO productSkuDO = skuDOMap.get(tradeOrderItemDO.getSkuId());
                 //这类商品的总推广费
-                Integer promotionExpenses = (productSkuDO.getPrice()-productSkuDO.getCostPrice())
-                        *tradeOrderItemDO.getCount();
+                Integer promotionExpenses = (productSkuDO.getPrice() - productSkuDO.getCostPrice())
+                        * tradeOrderItemDO.getCount();
 
                 //把商品项的推广费,转换为这项商品直推人获得的冻结积分
                 Long itemFreezeAmount =
@@ -955,30 +1120,70 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
                                 grossProfitUserQuotaPerc//消费者自得额度 百分比
                         );
 
-                totalFreezeAmount+=itemFreezeAmount;
+
+                //把商品项的推广费,转换为这项商品推荐人(上级)获得的冻结积分
+                Long ancestorItemFreezeAmount =
+                        promotionExpenses2GrossProfitAncestorQuota(promotionExpenses,
+                                grossProfitPerc,//毛利 = 成本 * 0.38... (推广费用)
+                                grossProfitAncestorQuotaPerc//消费者自得额度 百分比
+                        );
+
+                totalFreezeAmount += itemFreezeAmount;
+                totalAncestorFreezeAmount += ancestorItemFreezeAmount;
 
                 //记录用户在此订单项获得的冻结积分
                 TradeOrderItemDO toid = new TradeOrderItemDO();
                 toid.setId(tradeOrderItemDO.getId());
                 toid.setIncreaseIntegral(itemFreezeAmount);
+                toid.setAncestorIncreaseIntegral(ancestorItemFreezeAmount);//20240504 add by Ben
                 tradeOrderItemMapper.updateById(toid);
             }
 
             //把商品的推广费总额,转换为直推人获得的冻结积分
 //            Integer freezeAmount = promotionExpenses2GrossProfitAncestorQuota(orderPercentageMapper,totalPromotionExpenses);
 
-            String OrderNum =order.getNo();
-            integralService.updateUserIntegral(tradeOrderDO.getUserId(), CaclEnum.ORDER_GET_FREEZE_INTEGRAL, 0l,totalFreezeAmount,tradeOrderId,OrderNum);
+            String OrderNum = order.getNo();
+            //修改购物者本人获得的冻结积分
+            integralService.updateUserIntegral(tradeOrderDO.getUserId(), tradeOrderDO.getUserId(), CaclEnum.ORDER_PAY_INTEGRAL_CONSUMER, 0L, totalFreezeAmount, tradeOrderId, OrderNum);
+
+            //修改推荐人(上级)获得的冻结积分
+            integralService.updateUserIntegral(tradeOrderDO.getUserId(), ancesterUserId, CaclEnum.ORDER_PAY_INTEGRAL_ANCESTER, 0L, totalAncestorFreezeAmount, tradeOrderId, OrderNum);
+            log.warn("[TradeOrderUpdateServiceImpl.updateOrderPaid]$$$:[tradeOrderId({}),ancesterUserId({}),totalAncestorFreezeAmount({})]" + new Date(),
+                    tradeOrderId, ancesterUserId, totalAncestorFreezeAmount);
 
+            allTradeOrderTotalFreezeAmount += totalFreezeAmount;//用户获得总的待确权冻结积分
 
             // 发送给微信消息给系统用户待发货消息
             sentWcChatMessage(order);
         }
 
 
+        //自得身价计算
+        double orderUserSocialStatus = Double.parseDouble(orderPercentageDO.getOrderUserSocialStatus());//获得身价百分比
+        Double newSocialStatus = allTradeOrderTotalPrice * orderUserSocialStatus / 100;//用户获取的待确权身价值
+
+
+        rs.add(allTradeOrderTotalFreezeAmount);
+        rs.add(newSocialStatus);
+
+        return rs;
     }
 
-    private void sentWcChatMessage(TradeOrderDO order){
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_PAY)
+    //下面的参数中的id1为交易订单TradeOrder表的id,已经没用了,因为一个支付订单对应多个订单。
+    //只有支付订单id参数payOrderId是有用的。
+    public void updateOrderPaid(Long id1, Long payOrderId) {
+
+        log.error("[TradeOrderUpdateServiceImpl.updateOrderPaid]###微信回调(现在程序什么也没干):[payOrderId({}) ,TradeOrderId({})]" + new Date(),
+                payOrderId, id1);
+
+        //updateOrderPaid( payOrderId);
+    }
+
+    private void sentWcChatMessage(TradeOrderDO order) {
         List<String> params = new ArrayList<>();
         DecimalFormat df = new DecimalFormat("0.00");
         String formattedPrice = df.format((double) order.getPayPrice() / 100);
@@ -1001,8 +1206,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         List<Long> adminUsers = adminUserService.getUserIdsByShop(order.getShopId());
         for (Long aUserId : adminUsers) {
             //发送信息
-            wcChatMessageUtils.sendWcChatMessage(order.getUserId(), WcChatMessageTemplateIdEnum.ORDER_NO_DELIVERY2.getTemplateId(),
-                    params, aUserId, order.getUserId(), order.getId());
+            wcChatMessageUtils.sendWcChatMessage(WcChatMessageTemplateIdEnum.ORDER_NO_DELIVERY2.getTemplateId(),
+                    params, aUserId, order.getId());
         }
     }
 
@@ -1216,6 +1421,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
 
     /**
      * 用户手动取消订单
+     *
      * @param userId 用户编号
      * @param id     订单编号
      */
@@ -1237,18 +1443,19 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL);
 
         //3.退回订单已支付的积分 add by Ben
-        Long payIntegral = order.getPayIntegral();//每个订单使用的积分
+        Long payIntegral = order.getPayIntegral().longValue();//每个订单使用的积分
         Long tradeOrderId = order.getId();
         String orderNum = order.getNo();
         //如果订单有使用积分,则退回积分
-        if(payIntegral>0) {
-            integralService.updateUserIntegral(userId, CaclEnum.ORDER_CANCEL_BY_USER_REFUND_INTEGRAL, payIntegral, 0l, tradeOrderId, orderNum);
+        if (payIntegral > 0) {
+            integralService.updateUserIntegral(userId, userId, CaclEnum.ORDER_CANCEL_BY_USER_REFUND_INTEGRAL, payIntegral, 0L, tradeOrderId, orderNum);
         }
     }
 
     /**
      * 订单超时未支付,自动取消
-     * @return
+     *
+     * @return 数量
      */
     @Override
     public int cancelOrderBySystem() {
@@ -1267,13 +1474,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
                 getSelf().cancelOrderBySystem(order);
 
                 //退回订单已支付的积分 add by Ben
-                Long payIntegral = order.getPayIntegral();//每个订单使用的积分
+                Long payIntegral = order.getPayIntegral().longValue();//每个订单使用的积分
                 Long tradeOrderId = order.getId();
                 String orderNum = order.getNo();
                 Long userId = order.getUserId();
                 //如果订单有使用积分,则退回积分
-                if(payIntegral>0) {
-                    integralService.updateUserIntegral(userId, CaclEnum.ORDER_CANCEL_BY_SYSTEM_REFUND_INTEGRAL, payIntegral, 0l, tradeOrderId, orderNum);
+                if (payIntegral > 0) {
+                    integralService.updateUserIntegral(userId, userId, CaclEnum.ORDER_CANCEL_BY_SYSTEM_REFUND_INTEGRAL, payIntegral, 0L, tradeOrderId, orderNum);
                 }
 
                 count++;

+ 19 - 6
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/price/TradePriceServiceImpl.java

@@ -4,6 +4,10 @@ import cn.newfeifan.mall.module.product.api.sku.ProductSkuApi;
 import cn.newfeifan.mall.module.product.api.sku.dto.ProductSkuRespDTO;
 import cn.newfeifan.mall.module.product.api.spu.ProductSpuApi;
 import cn.newfeifan.mall.module.product.api.spu.dto.ProductSpuRespDTO;
+import cn.newfeifan.mall.module.product.dal.dataobject.sku.ProductSkuDO;
+import cn.newfeifan.mall.module.product.dal.dataobject.spu.ProductSpuDO;
+import cn.newfeifan.mall.module.product.dal.mysql.sku.ProductSkuMapper;
+import cn.newfeifan.mall.module.product.dal.mysql.spu.ProductSpuMapper;
 import cn.newfeifan.mall.module.trade.service.price.bo.TradePriceCalculateReqBO;
 import cn.newfeifan.mall.module.trade.service.price.bo.TradePriceCalculateRespBO;
 import cn.newfeifan.mall.module.trade.service.price.calculator.TradeDeliveryPriceCalculator;
@@ -42,6 +46,11 @@ public class TradePriceServiceImpl implements TradePriceService {
     @Resource
     private List<TradePriceCalculator> priceCalculators;
 
+    @Resource
+    private ProductSkuMapper productSkuMapper;
+    @Resource
+    private ProductSpuMapper productSpuMapper;
+
     /**
      * add by Ben
      * 计算订单含积分的各项商品价格
@@ -77,9 +86,9 @@ public class TradePriceServiceImpl implements TradePriceService {
 //        priceCalculators.forEach(calculator -> calculator.calculate(calculateReqBO, calculateRespBO));
         //计算运费
         TradeDeliveryPriceCalculator tradeDeliveryPriceCalculator = null;
-        for(TradePriceCalculator tpc:priceCalculators){
+        for (TradePriceCalculator tpc : priceCalculators) {
             //把计算运费对象取出来,这个对象不能new,因为自己new会缺少地址信息
-            if(tpc.getClass().getName().equals("cn.newfeifan.mall.module.trade.service.price.calculator.TradeDeliveryPriceCalculator")){
+            if (tpc.getClass().getName().equals("cn.newfeifan.mall.module.trade.service.price.calculator.TradeDeliveryPriceCalculator")) {
                 tradeDeliveryPriceCalculator = (TradeDeliveryPriceCalculator) tpc;
                 break;
             }
@@ -88,10 +97,14 @@ public class TradePriceServiceImpl implements TradePriceService {
         tradeDeliveryPriceCalculator.calculate(calculateReqBO, calculateRespBO);
 
         // 2.2  如果最终支付金额小于等于 0,则抛出业务异常
-        if (calculateRespBO.getPrice().getPayPrice() <= 0) {
-            log.error("[calculatePrice][价格计算不正确,请求 calculateReqDTO({}),结果 priceCalculate({})]",
-                    calculateReqBO, calculateRespBO);
-            throw exception(PRICE_CALCULATE_PAY_PRICE_ILLEGAL);
+        ProductSkuDO sku = productSkuMapper.selectById(calculateReqBO.getItems().get(0).getSkuId());
+        ProductSpuDO spu = productSpuMapper.selectById(sku.getSpuId());
+        if (!spu.getHighPrecision()) {
+            if (calculateRespBO.getPrice().getPayPrice() <= 0) {
+                log.error("[calculatePrice][价格计算不正确,请求 calculateReqDTO({}),结果 priceCalculate({})]",
+                        calculateReqBO, calculateRespBO);
+                throw exception(PRICE_CALCULATE_PAY_PRICE_ILLEGAL);
+            }
         }
         return calculateRespBO;
     }

+ 4 - 4
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/price/calculator/TradeDeliveryPriceCalculator.java

@@ -8,7 +8,6 @@ import cn.newfeifan.mall.module.member.api.address.MemberAddressApi;
 import cn.newfeifan.mall.module.member.api.address.dto.MemberAddressRespDTO;
 import cn.newfeifan.mall.module.sale.dal.dataobject.shop.ShopDO;
 import cn.newfeifan.mall.module.sale.dal.mysql.shop.ShopMapper;
-import cn.newfeifan.mall.module.trade.dal.dataobject.config.TradeConfigDO;
 import cn.newfeifan.mall.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO;
 import cn.newfeifan.mall.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
 import cn.newfeifan.mall.module.trade.enums.delivery.DeliveryTypeEnum;
@@ -52,8 +51,6 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
     private DeliveryPickUpStoreService deliveryPickUpStoreService;
     @Resource
     private DeliveryExpressTemplateService deliveryExpressTemplateService;
-    @Resource
-    private TradeConfigService tradeConfigService;
 
     @Override
     public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
@@ -64,6 +61,9 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
             calculateByPickUp(param);
         } else if (DeliveryTypeEnum.EXPRESS.getType().equals(param.getDeliveryType())) {
             calculateExpress(param, result);
+        } else if (DeliveryTypeEnum.VIRTUAL_PRODUCT.getType().equals(param.getDeliveryType())) {
+            // 虚拟商品不需要计算运费
+            calculateByPickUp(param);
         }
     }
 
@@ -86,7 +86,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
             // 价格计算时,如果为空就不算~最终下单,会校验该字段不允许空
             return;
         }
-        MemberAddressRespDTO address = addressApi.getAddress(param.getAddressId(), param.getUserId());
+        MemberAddressRespDTO address = addressApi.getAddress(param.getAddressId(), param.getUserId(),1);
         Assert.notNull(address, "收件人({})的地址,不能为空", param.getUserId());
 
         // 情况一:全局包邮

+ 10 - 7
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/price/calculator/TradePriceCalculatorHelper.java

@@ -4,7 +4,6 @@ import cn.hutool.core.lang.Assert;
 import cn.newfeifan.mall.framework.common.util.collection.CollectionUtils;
 import cn.newfeifan.mall.module.product.api.sku.dto.ProductSkuRespDTO;
 import cn.newfeifan.mall.module.product.api.spu.dto.ProductSpuRespDTO;
-import cn.newfeifan.mall.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO;
 import cn.newfeifan.mall.module.trade.dal.dataobject.order.TradeOrderItemDO;
 import cn.newfeifan.mall.module.trade.enums.order.TradeOrderTypeEnum;
 import cn.newfeifan.mall.module.trade.service.price.bo.TradePriceCalculateReqBO;
@@ -20,7 +19,6 @@ import static java.util.Collections.singletonList;
 
 /**
  * {@link TradePriceCalculator} 的工具类
- *
  * 主要实现对 {@link TradePriceCalculateRespBO} 计算结果的操作
  *
  * @author 非繁源码
@@ -50,11 +48,18 @@ public class TradePriceCalculatorHelper {
             // 商品项
             TradePriceCalculateRespBO.OrderItem orderItem = new TradePriceCalculateRespBO.OrderItem();
             result.getItems().add(orderItem);
+
+            // sku 价格
+            if(!spu.getHighPrecision()){
+                orderItem.setPrice(sku.getPrice()).setPayPrice(sku.getPrice() * item.getCount())
+                        .setDiscountPrice(0).setDeliveryPrice(0).setCouponPrice(0).setPointPrice(0).setVipPrice(0);
+            }else{
+                orderItem.setPrice(sku.getHighPrecisionPrice().intValue()).setPayPrice((int)(sku.getHighPrecisionPrice().doubleValue() * item.getCount()))
+                        .setDiscountPrice(0).setDeliveryPrice(0).setCouponPrice(0).setPointPrice(0).setVipPrice(0);
+            }
+
             orderItem.setSpuId(sku.getSpuId()).setSkuId(sku.getId())
                     .setCount(item.getCount()).setCartId(item.getCartId()).setSelected(item.getSelected());
-            // sku 价格
-            orderItem.setPrice(sku.getPrice()).setPayPrice(sku.getPrice() * item.getCount())
-                    .setDiscountPrice(0).setDeliveryPrice(0).setCouponPrice(0).setPointPrice(0).setVipPrice(0);
             // sku 信息
             orderItem.setPicUrl(sku.getPicUrl()).setProperties(sku.getProperties())
                     .setWeight(sku.getWeight()).setVolume(sku.getVolume());
@@ -145,7 +150,6 @@ public class TradePriceCalculatorHelper {
 
     /**
      * 重新计算每个订单项的支付金额
-     *
      * 【目前主要是单测使用】
      *
      * @param orderItems 订单项数组
@@ -249,7 +253,6 @@ public class TradePriceCalculatorHelper {
 
     /**
      * 计算订单调价价格分摊
-     *
      * 和 {@link #dividePrice(List, Integer)} 逻辑一致,只是传入的是 TradeOrderItemDO 对象
      *
      * @param items         订单项

+ 42 - 39
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/utils/wechat/WcChatMessageUtils.java

@@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONUtil;
+import cn.newfeifan.mall.module.member.dal.dataobject.user.MemberUserDO;
 import cn.newfeifan.mall.module.member.service.user.MemberUserService;
 import cn.newfeifan.mall.module.system.dal.dataobject.config.SystemConfigDO;
 import cn.newfeifan.mall.module.system.dal.dataobject.wechatmsgtemplate.WechatMsgTemplateDO;
@@ -23,9 +24,7 @@ import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
 import java.time.LocalDateTime;
-import java.util.Arrays;
-import java.util.List;
-import java.util.UUID;
+import java.util.*;
 
 import static cn.newfeifan.mall.module.system.constant.SystemConstants.WX_TICK_KEY_APPID;
 import static cn.newfeifan.mall.module.trade.enums.MessageTemplateConstants.AFTER_SALE_NO_CHECK_List;
@@ -85,6 +84,7 @@ public class WcChatMessageUtils {
             stringRedisTemplate.opsForValue().set(WX_TICK_KEY_APPID, accessToken, expireTime, java.util.concurrent.TimeUnit.SECONDS);
         }
 
+        log.info("===========Access_token:{}", accessToken);
 
         return accessToken;
     }
@@ -92,31 +92,10 @@ public class WcChatMessageUtils {
     /**
      * 发送微信消息
      *
-     * @param userId              接口消息的用户id
-     * @param data                模板参数
-     * @param wechatMsgTemplateId 自定义的消息模板id
+     * @param userId 接口消息的用户id
+     * @param data   模板参数
      */
-    private void sendWxgMessage(Long userId, JsonObject data, String wechatMsgTemplateId, Long systemUserId, Long memberUserId, Long objectId) {
-
-        // 组装消息内容
-        String userOpenId = null;
-        if (wechatMsgTemplateId.equals(WcChatMessageTemplateIdEnum.AFTER_SALE_NO_CHECK2.getTemplateId()) ||
-                wechatMsgTemplateId.equals(WcChatMessageTemplateIdEnum.ORDER_NO_DELIVERY2.getTemplateId())) {
-            //如果该用户没有该消息的权限,则不发送消息
-            if (!isHavePermission(systemUserId, wechatMsgTemplateId)) {
-                return;
-            }
-            userOpenId = getOpenIdBySysTemUserId(systemUserId);
-            memberUserId = memberUserService.getUserIdBySystemUserId(systemUserId);
-        } else {
-            userOpenId = getOpenId(userId);
-        }
-
-        //如果用户没有绑定微信,则不发送消息
-        if (userOpenId == null) {
-            return;
-        }
-
+    private void sendWxgMessage(Long userId, JsonObject data, String wechatMsgTemplateId, Long systemUserId, Long objectId, String userOpenId) {
         String templateId = getTemplateId(wechatMsgTemplateId).getWechatMsgTemplateId(); // 模板id
         String url = getDoMain(wechatMsgTemplateId, objectId);       // 跳转路径(小程序之外)
         String client_msg_id = UUID.randomUUID().toString();  // 防重入id
@@ -129,6 +108,10 @@ public class WcChatMessageUtils {
         message.setClient_msg_id(client_msg_id);
         message.setData(data);
 
+        sendWecChatMessage(userId, wechatMsgTemplateId, systemUserId, objectId, userOpenId, message,1);
+    }
+
+    private void sendWecChatMessage(Long userId, String wechatMsgTemplateId, Long systemUserId, Long objectId, String userOpenId, WeChatTemplateMessage message, int maxRetries) {
         // 发送消息
         String returnMsg = HttpUtil.post(StrUtil.format("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={}", getAccessToken()), message.toString());
         cn.hutool.json.JSONObject jsonObject2 = JSONUtil.parseObj(returnMsg);
@@ -139,7 +122,6 @@ public class WcChatMessageUtils {
                 .openid(userOpenId)
                 .memberUserId(userId)
                 .systemUserId(systemUserId)
-                .memberUserId(memberUserId)
                 .wechatMsgTemplateId(Long.valueOf(wechatMsgTemplateId))
                 .wechatMsgTemplateParams(message.toString())
                 .objectId(objectId)
@@ -153,6 +135,13 @@ public class WcChatMessageUtils {
         }
 
         messageLogService.createMessageLog(messageLogSaveReqVO);
+
+        // 如果微信的accessToken失效,则重新获取,最多重试3次
+        if (jsonObject2.getStr("errcode").equals("40001") && maxRetries <= 3) {
+            maxRetries++;
+            stringRedisTemplate.delete(WX_TICK_KEY_APPID);
+            sendWecChatMessage(userId, wechatMsgTemplateId, systemUserId, objectId, userOpenId, message, maxRetries);
+        }
     }
 
     /**
@@ -180,14 +169,12 @@ public class WcChatMessageUtils {
     /**
      * 发送微信信息
      *
-     * @param userId       用户id
      * @param templateId   自定义消息模板id
      * @param params       消息参数
      * @param systemUserId 系统用户id
-     * @param memberUserId 会员用户id
      * @param objectId     对象id
      */
-    public void sendWcChatMessage(Long userId, String templateId, List<String> params, Long systemUserId, Long memberUserId, Long objectId) {
+    public void sendWcChatMessage(String templateId, List<String> params, Long systemUserId, Long objectId) {
         WechatMsgTemplateDO template = getTemplateId(templateId);
         String messageTemplateParameters = template.getMessageTemplateParameters();
 
@@ -201,8 +188,28 @@ public class WcChatMessageUtils {
         List<String> dataParams = Arrays.asList(parts);
         JsonObject templateData = getTemplateData(dataParams, params);
 
-        // 发送微信消息
-        sendWxgMessage(userId, templateData, templateId, systemUserId, memberUserId, objectId);
+        // 组装消息内容
+        String userOpenId;
+        // 判断系统用户是否有接收消息的权限
+        if (!isHavePermission(systemUserId, templateId)) {
+            return;
+        }
+
+        // 获取系统用户绑定的会员用户集
+        Map<String, Long> openMap = new HashMap<>();
+        List<MemberUserDO> memberUserDOS = getMemberUserBySystemUserId(systemUserId);
+        for (MemberUserDO memberUserDO : memberUserDOS) {
+            userOpenId = getOpenId(memberUserDO.getId());
+
+            //如果用户没有绑定微信,则不发送消息
+            if (userOpenId == null) {
+                continue;
+            }
+
+            openMap.put(userOpenId, memberUserDO.getId());
+        }
+
+        openMap.forEach((k, v) -> sendWxgMessage(v, templateData, templateId, systemUserId, objectId, k));
     }
 
     /**
@@ -261,11 +268,7 @@ public class WcChatMessageUtils {
         return socialUserService.getOpenIdByUserId(userId);
     }
 
-    private String getOpenIdBySysTemUserId(Long systemUserId) {
-        Long memberUserId = memberUserService.getUserIdBySystemUserId(systemUserId);
-        if (memberUserId == null) {
-            return null;
-        }
-        return getOpenId(memberUserId);
+    private List<MemberUserDO> getMemberUserBySystemUserId(Long systemUserId) {
+        return memberUserService.getUserListBySystemUserId(systemUserId);
     }
 }

+ 4 - 2
feifan-module-member/feifan-module-member-api/src/main/java/cn/newfeifan/mall/module/member/api/address/MemberAddressApi.java

@@ -14,16 +14,18 @@ public interface MemberAddressApi {
      *
      * @param id 收件地址编号
      * @param userId 用户编号
+     * @param addressType 地址类别
      * @return 用户收件地址
      */
-    MemberAddressRespDTO getAddress(Long id, Long userId);
+    MemberAddressRespDTO getAddress(Long id, Long userId,Integer addressType);
 
     /**
      * 获得用户默认收件地址
      *
      * @param userId 用户编号
+     * @param addressType 地址类别
      * @return 用户收件地址
      */
-    MemberAddressRespDTO getDefaultAddress(Long userId);
+    MemberAddressRespDTO getDefaultAddress(Long userId,Integer addressType);
 
 }

+ 5 - 0
feifan-module-member/feifan-module-member-api/src/main/java/cn/newfeifan/mall/module/member/enums/DictTypeConstants.java

@@ -15,4 +15,9 @@ public interface DictTypeConstants {
     //将身价参数存在redis中的前缀
     String DISTRI_ORDER_PERCENTAGE  = "distri:orderPercentage";
 
+    //默认头像
+    String DEFAULT_AVATAR = "https://pt.letcgo.com/admin-api/infra/file/23/get/f9deb6a0e38c17d3d416da8b5285412dee1360e53e5b094f9397094be4252e66.png";
+
+    Long MOBILE_REGISTER_MAX = 10L;
+
 }

+ 5 - 1
feifan-module-member/feifan-module-member-api/src/main/java/cn/newfeifan/mall/module/member/enums/ErrorCodeConstants.java

@@ -16,9 +16,10 @@ public interface ErrorCodeConstants {
     ErrorCode USER_POINT_NOT_ENOUGH = new ErrorCode(1_004_001_003, "用户积分余额不足");
 
     // ========== AUTH 模块 1-004-003-000 ==========
-    ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1_004_003_000, "登录失败,账号密码不正确");
+    ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1_004_003_000, "登录失败,用户名或密码不正确");
     ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1_004_003_001, "登录失败,账号被禁用");
     ErrorCode AUTH_SOCIAL_USER_NOT_FOUND = new ErrorCode(1_004_003_005, "登录失败,解析不到三方登录信息");
+    ErrorCode AUTH_SOCIAL_USER_BIND_USER_NOT_FOUND = new ErrorCode(1_004_003_006, "登录失败,查询不到此用户");
     ErrorCode AUTH_MOBILE_USED = new ErrorCode(1_004_003_007, "手机号已经被使用");
 
     // ========== 用户收件地址 1-004-004-000 ==========
@@ -56,5 +57,8 @@ public interface ErrorCodeConstants {
     ErrorCode GROUP_HAS_USER = new ErrorCode(1_004_012_001, "用户分组下存在用户,无法删除");
 
     ErrorCode REDIS_ORDER_PERCENTAGE_NOT_EXISTS = new ErrorCode(1_004_012_002, "缓存中没有找到存储的签到获取的身价值");
+    ErrorCode AUTH_USERNAME_EXISTS = new ErrorCode(1_004_012_003, "此用户名已经存在,请换一个!");
+    ErrorCode MOBILE_IS_MAXIMIZE = new ErrorCode(1_004_012_004, "此手机号已经达到注册的上限了");
+    ErrorCode AUTH_SOCIAL_USER_BIND_MAX = new ErrorCode(1_004_012_004, "此微信号已经到达绑定的上限了");
 
 }

+ 4 - 4
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/api/address/MemberAddressApiImpl.java

@@ -21,13 +21,13 @@ public class MemberAddressApiImpl implements MemberAddressApi {
     private AddressService addressService;
 
     @Override
-    public MemberAddressRespDTO getAddress(Long id, Long userId) {
-        return AddressConvert.INSTANCE.convert02(addressService.getAddress(userId, id));
+    public MemberAddressRespDTO getAddress(Long id, Long userId,Integer addressType) {
+        return AddressConvert.INSTANCE.convert02(addressService.getAddress(userId, id,addressType));
     }
 
     @Override
-    public MemberAddressRespDTO getDefaultAddress(Long userId) {
-        return AddressConvert.INSTANCE.convert02(addressService.getDefaultUserAddress(userId));
+    public MemberAddressRespDTO getDefaultAddress(Long userId,Integer addressType) {
+        return AddressConvert.INSTANCE.convert02(addressService.getDefaultUserAddress(userId,addressType));
     }
 
 }

+ 8 - 8
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/address/AppAddressController.java

@@ -49,8 +49,8 @@ public class AppAddressController {
     @Operation(summary = "删除用户收件地址")
     @Parameter(name = "id", description = "编号", required = true)
     @PreAuthenticated
-    public CommonResult<Boolean> deleteAddress(@RequestParam("id") Long id) {
-        addressService.deleteAddress(getLoginUserId(), id);
+    public CommonResult<Boolean> deleteAddress(@RequestParam("id") Long id, @RequestParam(defaultValue = "1") Integer addressType) {
+        addressService.deleteAddress(getLoginUserId(), id,addressType);
         return success(true);
     }
 
@@ -58,24 +58,24 @@ public class AppAddressController {
     @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);
+    public CommonResult<AppAddressRespVO> getAddress(@RequestParam("id") Long id, @RequestParam(defaultValue = "1") Integer addressType) {
+        MemberAddressDO address = addressService.getAddress(getLoginUserId(), id,addressType);
         return success(AddressConvert.INSTANCE.convert(address));
     }
 
     @GetMapping("/get-default")
     @Operation(summary = "获得默认的用户收件地址")
     @PreAuthenticated
-    public CommonResult<AppAddressRespVO> getDefaultUserAddress() {
-        MemberAddressDO address = addressService.getDefaultUserAddress(getLoginUserId());
+    public CommonResult<AppAddressRespVO> getDefaultUserAddress(@RequestParam(defaultValue = "1") Integer addressType) {
+        MemberAddressDO address = addressService.getDefaultUserAddress(getLoginUserId(),addressType);
         return success(AddressConvert.INSTANCE.convert(address));
     }
 
     @GetMapping("/list")
     @Operation(summary = "获得用户收件地址列表")
     @PreAuthenticated
-    public CommonResult<List<AppAddressRespVO>> getAddressList() {
-        List<MemberAddressDO> list = addressService.getAddressList(getLoginUserId());
+    public CommonResult<List<AppAddressRespVO>> getAddressList(@RequestParam(defaultValue = "1") Integer addressType) {
+        List<MemberAddressDO> list = addressService.getAddressList(getLoginUserId(), addressType);
         return success(AddressConvert.INSTANCE.convertList(list));
     }
 

+ 3 - 1
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/address/vo/AppAddressBaseVO.java

@@ -21,7 +21,6 @@ public class AppAddressBaseVO {
     private String mobile;
 
     @Schema(description = "地区编号", requiredMode = Schema.RequiredMode.REQUIRED)
-    @NotNull(message = "地区编号不能为空")
     private Long areaId;
 
     @Schema(description = "收件详细地址", requiredMode = Schema.RequiredMode.REQUIRED)
@@ -32,4 +31,7 @@ public class AppAddressBaseVO {
     @NotNull(message = "是否默认地址不能为空")
     private Boolean defaultStatus;
 
+    @Schema(description = "地址类别", example = "1")
+    private Integer addressType;
+
 }

+ 24 - 6
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/AppAuthController.java

@@ -45,7 +45,7 @@ public class AppAuthController {
 
 
     @PostMapping("/login")
-    @Operation(summary = "使用手机 + 密码登录")
+    @Operation(summary = "使用用户名 + 密码登录")
     public CommonResult<AppAuthLoginRespVO> login(@RequestBody @Valid AppAuthLoginReqVO reqVO) {
         return success(authService.login(reqVO));
     }
@@ -73,11 +73,17 @@ public class AppAuthController {
     // ========== 短信登录相关 ==========
 
     @PostMapping("/sms-login")
-    @Operation(summary = "使用手机 + 验证码登录")
+    @Operation(summary = "使用用户名 + 手机 + 验证码登录")
     public CommonResult<AppAuthLoginRespVO> smsLogin(@RequestBody @Valid AppAuthSmsLoginReqVO reqVO) {
         return success(authService.smsLogin(reqVO));
     }
 
+    @PostMapping("/sms-register")
+    @Operation(summary = "使用用户名 + 手机 + 验证码 + 密码注册")
+    public CommonResult<AppAuthLoginRespVO> smsRegister(@RequestBody @Valid AppAuthSmsRegisterReqVO reqVO) {
+        return success(authService.smsRegister(reqVO));
+    }
+
     @PostMapping("/send-sms-code")
     @Operation(summary = "发送手机验证码")
     public CommonResult<Boolean> sendSmsCode(@RequestBody @Valid AppAuthSmsSendReqVO reqVO) {
@@ -93,11 +99,10 @@ public class AppAuthController {
     }
 
     @PostMapping("/social-login-validate-sms-code")
-    @Operation(summary = "社交快捷登录-校验手机验证码")
+    @Operation(summary = "社交快捷注册-校验手机验证码")
     public CommonResult<AppAuthLoginRespVO> socialLoginValidateSmsCode(@RequestBody @Validated SocialLoginValidateSmsCodeReqVO requestVO) {
         authService.validateSmsCode(getLoginUserId(), requestVO.getReqVO());
-        AppAuthSocialLoginReqVO loginReqVO = requestVO.getLoginReqVO();
-        return success(authService.socialLogin(loginReqVO, requestVO.getReqVO().getMobile(), false, true));
+        return success(authService.socialRegister(requestVO.getRegisterReqVO(), requestVO.getReqVO().getMobile(), false, true));
     }
 
     // ========== 社交登录相关 ==========
@@ -116,7 +121,20 @@ public class AppAuthController {
     @PostMapping("/social-login")
     @Operation(summary = "社交快捷登录,使用 code 授权码", description = "适合未登录的用户,但是社交账号已绑定用户")
     public CommonResult<AppAuthLoginRespVO> socialLogin(@RequestBody @Valid AppAuthSocialLoginReqVO reqVO) {
-        return success(authService.socialLogin(reqVO, null, true, false));
+        return success(authService.socialLogin(reqVO));
+    }
+
+    @PostMapping("/social-register")
+    @Operation(summary = "社交快捷注册,使用code授权码",description = "同一个微信账号注册多个消费者账号")
+    public CommonResult<AppAuthLoginRespVO> socialRegister(@RequestBody @Valid AppAuthSocialRegisterReqVO requestVO){
+
+        return success(authService.socialRegister(requestVO, null, false, false));
+    }
+
+    @PostMapping("/select-username-login")
+    @Operation(summary = "选择用户名登录")
+    public CommonResult<AppAuthLoginRespVO> selectUsernameLogin(@RequestBody @Valid AppAuthSelectUsernameLoginReqVO reqVO) {
+        return success(authService.selectUsernameLogin(reqVO));
     }
 
     @PostMapping("/weixin-mini-app-login")

+ 4 - 6
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java

@@ -2,7 +2,6 @@ package cn.newfeifan.mall.module.member.controller.app.auth.vo;
 
 import cn.hutool.core.util.StrUtil;
 import cn.newfeifan.mall.framework.common.validation.InEnum;
-import cn.newfeifan.mall.framework.common.validation.Mobile;
 import cn.newfeifan.mall.module.system.enums.social.SocialTypeEnum;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.AllArgsConstructor;
@@ -13,6 +12,7 @@ import org.hibernate.validator.constraints.Length;
 
 import javax.validation.constraints.AssertTrue;
 import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
 
 @Schema(description = "用户 APP - 手机 + 密码登录 Request VO,如果登录并绑定社交用户,需要传递 social 开头的参数")
 @Data
@@ -20,11 +20,9 @@ import javax.validation.constraints.NotEmpty;
 @AllArgsConstructor
 @Builder
 public class AppAuthLoginReqVO {
-
-    @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
-    @NotEmpty(message = "手机号不能为空")
-    @Mobile
-    private String mobile;
+    @Schema(description = "登录用的用户名", example = "张三")
+    @NotNull(message = "用户名不能为空")
+    private String username;
 
     @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "buzhidao")
     @NotEmpty(message = "密码不能为空")

+ 4 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java

@@ -7,6 +7,7 @@ import lombok.Data;
 import lombok.NoArgsConstructor;
 
 import java.time.LocalDateTime;
+import java.util.List;
 
 @Schema(description = "用户 APP - 登录 Response VO")
 @Data
@@ -27,6 +28,9 @@ public class AppAuthLoginRespVO {
     @Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime expiresTime;
 
+    @Schema(description = "当前微信绑定的账号集合")
+    private List<AppAuthMemberUserRespVO> socialUsers;
+
     /**
      * 仅社交登录、社交绑定时会返回
      *

+ 16 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/AppAuthMemberUserRespVO.java

@@ -0,0 +1,16 @@
+package cn.newfeifan.mall.module.member.controller.app.auth.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+
+@Schema(description = "用户 APP - 微信下的用户 Response VO")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class AppAuthMemberUserRespVO {
+    @Schema(description = "用户名", example = "张三")
+    private String username;
+    @Schema(description = "头像", example = "https://www.iocoder.cn/xxx.jpg")
+    private String avatar;
+}

+ 18 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/AppAuthSelectUsernameLoginReqVO.java

@@ -0,0 +1,18 @@
+package cn.newfeifan.mall.module.member.controller.app.auth.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+@Data
+@Schema(description = "用户 APP - 用户微信登录后可以选择微信绑定的账号登录")
+public class AppAuthSelectUsernameLoginReqVO {
+    @Schema(description = "openId", requiredMode = Schema.RequiredMode.REQUIRED, example = "nice")
+    @NotNull(message = "openId不能为空")
+    private String openId;
+
+    @Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "nice")
+    @NotNull(message = "用户名不能为空")
+    private String username;
+}

+ 4 - 9
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/AppAuthSmsLoginReqVO.java

@@ -13,6 +13,7 @@ import org.hibernate.validator.constraints.Length;
 
 import javax.validation.constraints.AssertTrue;
 import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Pattern;
 
 @Schema(description = "用户 APP - 手机 + 验证码登录 Request VO,如果登录并绑定社交用户,需要传递 social 开头的参数")
@@ -45,15 +46,9 @@ public class AppAuthSmsLoginReqVO {
     @Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
     private String socialState;
 
-    @Schema(description = "分享链接ID 没有可以不传")
-    private String linkId;
-
-    public Long getLinkId() {
-        if (linkId == null) {
-            return null;
-        }
-        return Long.parseLong(linkId,16);
-    }
+    @Schema(description = "用户名")
+    @NotNull(message = "用户名不能为空")
+    private String username;
 
     @AssertTrue(message = "授权码不能为空")
     public boolean isSocialCodeValid() {

+ 28 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/AppAuthSmsRegisterReqVO.java

@@ -0,0 +1,28 @@
+package cn.newfeifan.mall.module.member.controller.app.auth.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotNull;
+
+@Schema(description = "用户 APP - 手机 + 验证码登录 Request VO,如果登录并绑定社交用户,需要传递 social 开头的参数")
+@Data
+public class AppAuthSmsRegisterReqVO extends AppAuthSmsLoginReqVO {
+
+    @Schema(description = "分享链接ID")
+    @NotNull(message = "只能通过分享注册")
+    private String linkId;
+
+    @Schema(description = "密码")
+    @NotNull(message = "密码不能为空")
+    @Length(min = 4, max = 16, message = "密码长度为 4-16 位")
+    private String password;
+
+    public Long getLinkId() {
+        if (linkId == null) {
+            return null;
+        }
+        return Long.parseLong(linkId,16);
+    }
+}

+ 0 - 10
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/AppAuthSocialLoginReqVO.java

@@ -30,14 +30,4 @@ public class AppAuthSocialLoginReqVO {
     @Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
     @NotEmpty(message = "state 不能为空")
     private String state;
-
-    @Schema(description = "分享链接ID 没有可以不传")
-    private String linkId;
-
-    public Long getLinkId() {
-        if (linkId == null) {
-            return null;
-        }
-        return Long.parseLong(linkId,16);
-    }
 }

+ 26 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/AppAuthSocialRegisterReqVO.java

@@ -0,0 +1,26 @@
+package cn.newfeifan.mall.module.member.controller.app.auth.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@Data
+public class AppAuthSocialRegisterReqVO  extends AppAuthSocialLoginReqVO{
+    @Schema(description = "分享链接ID")
+    @NotNull(message = "只能通过分享注册")
+    @NotEmpty(message = "只能通过分享注册")
+    private String linkId;
+
+    @Schema(description = "用户名")
+    private String username;
+
+    public Long getLinkId() {
+        if (linkId == null) {
+            return null;
+        }
+        return Long.parseLong(linkId,16);
+    }
+
+}

+ 1 - 1
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/auth/vo/SocialLoginValidateSmsCodeReqVO.java

@@ -20,6 +20,6 @@ public class SocialLoginValidateSmsCodeReqVO {
      * 该字段包含了社交登录所需的请求参数。
      */
     @Valid
-    private AppAuthSocialLoginReqVO loginReqVO;
+    private AppAuthSocialRegisterReqVO registerReqVO;
 
 }

+ 8 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/user/AppMemberUserController.java

@@ -16,6 +16,7 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
+import javax.validation.constraints.NotEmpty;
 
 import static cn.newfeifan.mall.framework.common.pojo.CommonResult.success;
 import static cn.newfeifan.mall.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@@ -32,6 +33,13 @@ public class AppMemberUserController {
     @Resource
     private MemberLevelService levelService;
 
+    @GetMapping("/verifyUsername")
+    @Operation(summary = "校验用户名是否重复")
+    public CommonResult<Boolean> verifyUsername(@NotEmpty(message = "用户名不能为空") @RequestParam(value = "username") String username) {
+        return success(userService.selectCountByUsername(username) == 0);
+    }
+
+
     @GetMapping("/get")
     @Operation(summary = "获得基本信息")
     @PreAuthenticated

+ 3 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java

@@ -53,4 +53,7 @@ public class AppMemberUserInfoRespVO {
 
     }
 
+    @Schema(description = "登录用的用户名", example = "张三")
+    private String username;
+
 }

+ 5 - 1
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/dal/dataobject/address/MemberAddressDO.java

@@ -46,9 +46,13 @@ public class MemberAddressDO extends BaseDO {
     private String detailAddress;
     /**
      * 是否默认
-     *
      * true - 默认收件地址
      */
     private Boolean defaultStatus;
 
+    /**
+     * 地址类别
+     */
+    private Integer addressType;
+
 }

+ 5 - 7
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/dal/dataobject/user/MemberUserDO.java

@@ -20,7 +20,6 @@ import java.util.List;
 
 /**
  * 会员用户 DO
- *
  * uk_mobile 索引:基于 {@link #mobile} 字段
  *
  * @author 非繁源码
@@ -52,13 +51,11 @@ public class MemberUserDO extends TenantBaseDO {
     private String mobile;
     /**
      * 加密后的密码
-     *
      * 因为目前使用 {@link BCryptPasswordEncoder} 加密器,所以无需自己处理 salt 盐
      */
     private String password;
     /**
      * 帐号状态
-     *
      * 枚举 {@link CommonStatusEnum}
      */
     private Integer status;
@@ -97,7 +94,6 @@ public class MemberUserDO extends TenantBaseDO {
     private String name;
     /**
      * 性别
-     *
      * 枚举 {@link SexEnum}
      */
     private Integer sex;
@@ -107,7 +103,6 @@ public class MemberUserDO extends TenantBaseDO {
     private LocalDateTime birthday;
     /**
      * 所在地
-     *
      * 关联 {@link Area#getId()} 字段
      */
     private Integer areaId;
@@ -132,7 +127,6 @@ public class MemberUserDO extends TenantBaseDO {
 
     /**
      * 会员级别编号
-     *
      * 关联 {@link MemberLevelDO#getId()} 字段
      */
     private Long levelId;
@@ -142,7 +136,6 @@ public class MemberUserDO extends TenantBaseDO {
     private Integer experience;
     /**
      * 用户分组编号
-     *
      * 关联 {@link MemberGroupDO#getId()} 字段
      */
     private Long groupId;
@@ -152,4 +145,9 @@ public class MemberUserDO extends TenantBaseDO {
      */
     private Long systemUsersId;
 
+    /**
+     * 登录用的用户名
+     */
+    private String username;
+
 }

+ 8 - 2
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/dal/mysql/address/MemberAddressMapper.java

@@ -10,13 +10,19 @@ import java.util.List;
 @Mapper
 public interface MemberAddressMapper extends BaseMapperX<MemberAddressDO> {
 
-    default MemberAddressDO selectByIdAndUserId(Long id, Long userId) {
-        return selectOne(MemberAddressDO::getId, id, MemberAddressDO::getUserId, userId);
+    default MemberAddressDO selectByIdAndUserId(Long id, Long userId,Integer addressType) {
+        return selectOne(MemberAddressDO::getId, id, MemberAddressDO::getUserId, userId, MemberAddressDO::getAddressType, addressType);
     }
 
     default List<MemberAddressDO> selectListByUserIdAndDefaulted(Long userId, Boolean defaulted) {
         return selectList(new LambdaQueryWrapperX<MemberAddressDO>().eq(MemberAddressDO::getUserId, userId)
                 .eqIfPresent(MemberAddressDO::getDefaultStatus, defaulted));
     }
+    default List<MemberAddressDO> selectListByUserIdAndDefaulted(Long userId, Boolean defaulted, Integer addressType) {
+        return selectList(new LambdaQueryWrapperX<MemberAddressDO>().eq(MemberAddressDO::getUserId, userId)
+                .eqIfPresent(MemberAddressDO::getDefaultStatus, defaulted)
+                .eqIfPresent(MemberAddressDO::getAddressType,addressType)
+        );
+    }
 
 }

+ 9 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/dal/mysql/user/MemberUserMapper.java

@@ -10,6 +10,7 @@ import cn.newfeifan.mall.module.member.controller.admin.user.vo.MemberUserPageRe
 import cn.newfeifan.mall.module.member.dal.dataobject.user.MemberUserDO;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
 import java.util.stream.Collectors;
@@ -25,6 +26,9 @@ public interface MemberUserMapper extends BaseMapperX<MemberUserDO> {
     default MemberUserDO selectByMobile(String mobile) {
         return selectOne(MemberUserDO::getMobile, mobile);
     }
+    default MemberUserDO selectByMobileAndUsername(String mobile,String username) {
+        return selectOne(MemberUserDO::getMobile, mobile,MemberUserDO::getUsername, username);
+    }
 
     default List<MemberUserDO> selectListByNicknameLike(String nickname) {
         return selectList(new LambdaQueryWrapperX<MemberUserDO>()
@@ -93,4 +97,9 @@ public interface MemberUserMapper extends BaseMapperX<MemberUserDO> {
         return update(null, lambdaUpdateWrapper);
     }
 
+    void synchronizationUserNicknameForDUser(@Param(value = "nickname")String nickname, @Param(value = "userId")Long userId);
+
+    void synchronizationUserNicknameForIntegral(@Param("nickname") String nickname, @Param("userId") Long userId);
+    void synchronizationUserNicknameForSharePathDesc(@Param("nickname") String nickname, @Param("userId") Long userId);
+    void synchronizationUserNicknameForSharePathAnc(@Param("nickname") String nickname, @Param("userId") Long userId);
 }

+ 8 - 4
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/address/AddressService.java

@@ -36,32 +36,36 @@ public interface AddressService {
      * 删除用户收件地址
      *
      * @param userId 用户编号
+     * @param addressType 地址类型
      * @param id 编号
      */
-    void deleteAddress(Long userId, Long id);
+    void deleteAddress(Long userId, Long id,Integer addressType);
 
     /**
      * 获得用户收件地址
      *
      * @param id 编号
+     * @param addressType 地址类型
      * @return 用户收件地址
      */
-    MemberAddressDO getAddress(Long userId, Long id);
+    MemberAddressDO getAddress(Long userId, Long id,Integer addressType);
 
     /**
      * 获得用户收件地址列表
      *
      * @param userId 用户编号
+     * @param addressType 地址类型
      * @return 用户收件地址列表
      */
-    List<MemberAddressDO> getAddressList(Long userId);
+    List<MemberAddressDO> getAddressList(Long userId,Integer addressType);
 
     /**
      * 获得用户默认的收件地址
      *
      * @param userId 用户编号
+     * @param addressType 地址类别
      * @return 用户收件地址
      */
-    MemberAddressDO getDefaultUserAddress(Long userId);
+    MemberAddressDO getDefaultUserAddress(Long userId,Integer addressType);
 
 }

+ 15 - 11
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/address/AddressServiceImpl.java

@@ -6,6 +6,7 @@ import cn.newfeifan.mall.module.member.controller.app.address.vo.AppAddressUpdat
 import cn.newfeifan.mall.module.member.convert.address.AddressConvert;
 import cn.newfeifan.mall.module.member.dal.dataobject.address.MemberAddressDO;
 import cn.newfeifan.mall.module.member.dal.mysql.address.MemberAddressMapper;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
@@ -23,6 +24,7 @@ import static cn.newfeifan.mall.module.member.enums.ErrorCodeConstants.ADDRESS_N
  */
 @Service
 @Validated
+@Slf4j
 public class AddressServiceImpl implements AddressService {
 
     @Resource
@@ -49,7 +51,7 @@ public class AddressServiceImpl implements AddressService {
     @Transactional(rollbackFor = Exception.class)
     public void updateAddress(Long userId, AppAddressUpdateReqVO updateReqVO) {
         // 校验存在,校验是否能够操作
-        validAddressExists(userId, updateReqVO.getId());
+        validAddressExists(userId, updateReqVO.getId(),updateReqVO.getAddressType());
 
         // 如果修改的是默认收件地址,则将原默认地址修改为非默认
         if (Boolean.TRUE.equals(updateReqVO.getDefaultStatus())) {
@@ -64,33 +66,35 @@ public class AddressServiceImpl implements AddressService {
     }
 
     @Override
-    public void deleteAddress(Long userId, Long id) {
+    public void deleteAddress(Long userId, Long id,Integer addressType) {
         // 校验存在,校验是否能够操作
-        validAddressExists(userId, id);
+        validAddressExists(userId, id,addressType);
         // 删除
         memberAddressMapper.deleteById(id);
     }
 
-    private void validAddressExists(Long userId, Long id) {
-        MemberAddressDO addressDO = getAddress(userId, id);
+    private void validAddressExists(Long userId, Long id,Integer addressType) {
+        MemberAddressDO addressDO = getAddress(userId, id,addressType);
         if (addressDO == null) {
             throw exception(ADDRESS_NOT_EXISTS);
         }
     }
 
     @Override
-    public MemberAddressDO getAddress(Long userId, Long id) {
-        return memberAddressMapper.selectByIdAndUserId(id, userId);
+    public MemberAddressDO getAddress(Long userId, Long id,Integer addressType) {
+        return memberAddressMapper.selectByIdAndUserId(id, userId,addressType);
     }
 
     @Override
-    public List<MemberAddressDO> getAddressList(Long userId) {
-        return memberAddressMapper.selectListByUserIdAndDefaulted(userId, null);
+    public List<MemberAddressDO> getAddressList(Long userId,Integer addressType) {
+        return memberAddressMapper.selectList(MemberAddressDO::getUserId,userId,MemberAddressDO::getAddressType,addressType);
     }
 
     @Override
-    public MemberAddressDO getDefaultUserAddress(Long userId) {
-        List<MemberAddressDO> addresses = memberAddressMapper.selectListByUserIdAndDefaulted(userId, true);
+    public MemberAddressDO getDefaultUserAddress(Long userId,Integer addressType) {
+        List<MemberAddressDO> addresses;
+        log.info("addressType:{}",addressType);
+        addresses = memberAddressMapper.selectListByUserIdAndDefaulted(userId, true,addressType);
         return CollUtil.getFirst(addresses);
     }
 

+ 12 - 1
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/auth/MemberAuthService.java

@@ -43,7 +43,7 @@ public interface MemberAuthService {
      * @param phone 用户手机号
      * @return 登录结果
      */
-    AppAuthLoginRespVO socialLogin(@Valid AppAuthSocialLoginReqVO reqVO, String phone, Boolean isFirst, Boolean isRegister);
+    AppAuthLoginRespVO socialRegister(@Valid AppAuthSocialRegisterReqVO reqVO, String phone, Boolean isFirst, Boolean isRegister);
 
     /**
      * 微信小程序的一键登录
@@ -86,4 +86,15 @@ public interface MemberAuthService {
      */
     AppAuthLoginRespVO refreshToken(String refreshToken);
 
+    /**
+     * 使用手机号 + 验证码注册
+     *
+     * @param reqVO 注册信息
+     * @return 登录结果
+     */
+    AppAuthLoginRespVO smsRegister(AppAuthSmsRegisterReqVO reqVO);
+
+    AppAuthLoginRespVO socialLogin(AppAuthSocialLoginReqVO reqVO);
+
+    AppAuthLoginRespVO selectUsernameLogin(AppAuthSelectUsernameLoginReqVO reqVO);
 }

+ 119 - 37
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/auth/MemberAuthServiceImpl.java

@@ -27,17 +27,19 @@ import cn.newfeifan.mall.module.system.enums.logger.LoginResultEnum;
 import cn.newfeifan.mall.module.system.enums.oauth2.OAuth2ClientConstants;
 import cn.newfeifan.mall.module.system.enums.sms.SmsSceneEnum;
 import cn.newfeifan.mall.module.system.enums.social.SocialTypeEnum;
-import jodd.util.StringUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
+import java.util.List;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.newfeifan.mall.framework.common.util.servlet.ServletUtils.getClientIP;
 import static cn.newfeifan.mall.framework.web.core.util.WebFrameworkUtils.getTerminal;
+import static cn.newfeifan.mall.module.member.enums.DictTypeConstants.*;
 import static cn.newfeifan.mall.module.member.enums.ErrorCodeConstants.*;
 
 /**
@@ -64,8 +66,8 @@ public class MemberAuthServiceImpl implements MemberAuthService {
 
     @Override
     public AppAuthLoginRespVO login(AppAuthLoginReqVO reqVO) {
-        // 使用手机 + 密码,进行登录。
-        MemberUserDO user = login0(reqVO.getMobile(), reqVO.getPassword());
+        // 使用用户名 + 密码,进行登录。
+        MemberUserDO user = login0(reqVO.getUsername(), reqVO.getPassword());
 
         // 如果 socialType 非空,说明需要绑定社交用户
         String openid = null;
@@ -75,7 +77,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
         }
 
         // 创建 Token 令牌,记录登录日志
-        return createTokenAfterLoginSuccess(user, reqVO.getMobile(), LoginLogTypeEnum.LOGIN_MOBILE, openid);
+        return createTokenAfterLoginSuccess(user, reqVO.getUsername(), LoginLogTypeEnum.LOGIN_MOBILE, openid);
     }
 
     @Override
@@ -86,8 +88,10 @@ public class MemberAuthServiceImpl implements MemberAuthService {
         smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_LOGIN.getScene(), userIp));
 
         // 获得获得注册用户
-        MemberUserDO user = userService.createUserIfAbsent(reqVO.getMobile(), userIp, getTerminal(), reqVO.getLinkId());
-        Assert.notNull(user, "获取用户失败,结果为空");
+        MemberUserDO user = userService.createUserIfAbsent(reqVO.getMobile(), reqVO.getUsername(), userIp, getTerminal());
+        if(user == null){
+            throw exception(USER_MOBILE_NOT_EXISTS);
+        }
 
         // 如果 socialType 非空,说明需要绑定社交用户
         String openid = null;
@@ -102,7 +106,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
 
     @Override
     @Transactional
-    public AppAuthLoginRespVO socialLogin(AppAuthSocialLoginReqVO reqVO, String phone, Boolean isFirst, Boolean isRegister) {
+    public AppAuthLoginRespVO socialRegister(AppAuthSocialRegisterReqVO reqVO, String phone, Boolean isFirst, Boolean isRegister) {
 
 
         // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号
@@ -112,28 +116,53 @@ public class MemberAuthServiceImpl implements MemberAuthService {
             throw exception(AUTH_SOCIAL_USER_NOT_FOUND);
         }
 
-        // 情况一:已绑定,直接读取用户信息
-        MemberUserDO user;
-        if (socialUser.getUserId() != null) {
-            user = userService.getUser(socialUser.getUserId());
-            // 情况二:未绑定,注册用户 + 绑定用户
-        } else {
+        //重名校验
+        if (reqVO.getUsername().isEmpty() || userService.selectCountByUsername(reqVO.getUsername()) > 0) {
+            throw exception(AUTH_USERNAME_EXISTS);
+        }
 
-            //通过微信 + 手机号首次登录
-            if (!StringUtil.isEmpty(phone)) {
-                //如果会员表中有记录
-                user = userService.getUserByMobile(phone);
-                if (user == null) {
-                    //加入手机号
-                    user = userService.createUser(phone, socialUser.getNickname(), socialUser.getAvatar(), getClientIP(), getTerminal(), reqVO.getLinkId());
-                }
-            } else {
-                user = userService.createUser(null, socialUser.getNickname(), socialUser.getAvatar(), getClientIP(), getTerminal(), reqVO.getLinkId());
-            }
+        //校验手机号注册是否达到上限
+        verifyMobileIsMaximize(phone);
+
+        //微信能绑定的账号上限校验
+        if(socialUserApi.wxBindIsMax(socialUser.getId())){
+            throw exception(AUTH_SOCIAL_USER_BIND_MAX);
+        }
+
+        MemberUserDO user = userService.createUser(phone, socialUser.getNickname(), socialUser.getAvatar(), getClientIP(), getTerminal(), reqVO.getLinkId(), reqVO.getUsername(), null);
+
+        socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
+                reqVO.getType(), reqVO.getCode(), reqVO.getState()));
+
+        // 创建 Token 令牌,记录登录日志
+        return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, socialUser.getOpenid());
+    }
 
-            socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
-                    reqVO.getType(), reqVO.getCode(), reqVO.getState()));
+    @Override
+    public AppAuthLoginRespVO socialLogin(AppAuthSocialLoginReqVO reqVO) {
+        // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号
+        SocialUserRespDTO socialUser = socialUserApi.getSocialUserByCode(UserTypeEnum.MEMBER.getValue(), reqVO.getType(),
+                reqVO.getCode(), reqVO.getState(), true, false);
+        if (socialUser == null) {
+            throw exception(AUTH_SOCIAL_USER_NOT_FOUND);
         }
+
+        //如果同一个微信绑定了多个用户就返回用户集 供用户选择登录
+        if (socialUser.getUserIds().size() != 1) {
+            List<MemberUserDO> users = userService.getUserList(socialUser.getUserIds());
+            List<AppAuthMemberUserRespVO> memberUserRespVOS = users.stream().map(user -> AppAuthMemberUserRespVO
+                            .builder()
+                            .username(user.getUsername())
+                            .avatar(user.getAvatar())
+                            .build())
+                    .collect(Collectors.toList());
+            return AppAuthLoginRespVO.builder().openid(socialUser.getOpenid()).socialUsers(memberUserRespVOS).build();
+        } else {
+            //如果只有一个账号那就直接登录
+            socialUser.setUserId(socialUser.getUserIds().get(0));
+        }
+
+        MemberUserDO user = userService.getUser(socialUser.getUserId());
         if (user == null) {
             throw exception(USER_NOT_EXISTS);
         }
@@ -142,6 +171,19 @@ public class MemberAuthServiceImpl implements MemberAuthService {
         return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, socialUser.getOpenid());
     }
 
+    @Override
+    public AppAuthLoginRespVO selectUsernameLogin(AppAuthSelectUsernameLoginReqVO reqVO) {
+        MemberUserDO user = userService.selectByUsername(reqVO.getUsername());
+
+        //如果微信绑定的账号中没有此账号那就返回报错
+        Boolean flag = socialUserApi.wxIsBindByUserId(reqVO.getOpenId(), user.getId());
+        if (!flag) {
+            throw exception(AUTH_SOCIAL_USER_BIND_USER_NOT_FOUND);
+        }
+
+        return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, reqVO.getOpenId());
+    }
+
     @Override
     public AppAuthLoginRespVO weixinMiniAppLogin(AppAuthWeixinMiniAppLoginReqVO reqVO) {
         // 获得对应的手机号信息
@@ -150,8 +192,8 @@ public class MemberAuthServiceImpl implements MemberAuthService {
         Assert.notNull(phoneNumberInfo, "获得手机信息失败,结果为空");
 
         // 获得获得注册用户
-        MemberUserDO user = userService.createUserIfAbsent(phoneNumberInfo.getPurePhoneNumber(),
-                getClientIP(), TerminalEnum.WECHAT_MINI_PROGRAM.getTerminal(), null);
+        MemberUserDO user = userService.createUserIfAbsent(phoneNumberInfo.getPurePhoneNumber(), null,
+                getClientIP(), TerminalEnum.WECHAT_MINI_PROGRAM.getTerminal());
         Assert.notNull(user, "获取用户失败,结果为空");
 
         // 绑定社交用户
@@ -162,10 +204,10 @@ public class MemberAuthServiceImpl implements MemberAuthService {
         return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, openid);
     }
 
-    private AppAuthLoginRespVO createTokenAfterLoginSuccess(MemberUserDO user, String mobile,
+    private AppAuthLoginRespVO createTokenAfterLoginSuccess(MemberUserDO user, String username,
                                                             LoginLogTypeEnum logType, String openid) {
         // 插入登陆日志
-        createLoginLog(user.getId(), mobile, logType, LoginResultEnum.SUCCESS);
+        createLoginLog(user.getId(), username, logType, LoginResultEnum.SUCCESS);
         // 创建 Token 令牌
         OAuth2AccessTokenRespDTO accessTokenRespDTO = oauth2TokenApi.createAccessToken(new OAuth2AccessTokenCreateReqDTO()
                 .setUserId(user.getId()).setUserType(getUserType().getValue())
@@ -179,34 +221,34 @@ public class MemberAuthServiceImpl implements MemberAuthService {
         return socialClientApi.getAuthorizeUrl(type, UserTypeEnum.MEMBER.getValue(), redirectUri);
     }
 
-    private MemberUserDO login0(String mobile, String password) {
+    private MemberUserDO login0(String username, String password) {
         final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_MOBILE;
         // 校验账号是否存在
-        MemberUserDO user = userService.getUserByMobile(mobile);
+        MemberUserDO user = userService.getUserByUsername(username);
         if (user == null) {
-            createLoginLog(null, mobile, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
+            createLoginLog(null, username, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
             throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
         }
         if (!userService.isPasswordMatch(password, user.getPassword())) {
-            createLoginLog(user.getId(), mobile, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
+            createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
             throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
         }
         // 校验是否禁用
         if (ObjectUtil.notEqual(user.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
-            createLoginLog(user.getId(), mobile, logTypeEnum, LoginResultEnum.USER_DISABLED);
+            createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.USER_DISABLED);
             throw exception(AUTH_LOGIN_USER_DISABLED);
         }
         return user;
     }
 
-    private void createLoginLog(Long userId, String mobile, LoginLogTypeEnum logType, LoginResultEnum loginResult) {
+    private void createLoginLog(Long userId, String username, LoginLogTypeEnum logType, LoginResultEnum loginResult) {
         // 插入登录日志
         LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO();
         reqDTO.setLogType(logType.getType());
         reqDTO.setTraceId(TracerUtils.getTraceId());
         reqDTO.setUserId(userId);
         reqDTO.setUserType(getUserType().getValue());
-        reqDTO.setUsername(mobile);
+        reqDTO.setUsername(username);
         reqDTO.setUserAgent(ServletUtils.getUserAgent());
         reqDTO.setUserIp(getClientIP());
         reqDTO.setResult(loginResult.getResult());
@@ -267,6 +309,46 @@ public class MemberAuthServiceImpl implements MemberAuthService {
         return AuthConvert.INSTANCE.convert(accessTokenDO, null);
     }
 
+    @Override
+    public AppAuthLoginRespVO smsRegister(AppAuthSmsRegisterReqVO reqVO) {
+        // 校验验证码
+        String userIp = getClientIP();
+        smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_LOGIN.getScene(), userIp));
+
+        //校验手机号注册是否达到上限
+        verifyMobileIsMaximize(reqVO.getMobile());
+
+        //校验用户名
+        verifyUsername(reqVO.getUsername());
+
+        //创建用户
+        MemberUserDO user = userService.createUser(reqVO.getMobile(), reqVO.getUsername(), DEFAULT_AVATAR, getClientIP(), getTerminal(), reqVO.getLinkId(), reqVO.getUsername(), reqVO.getPassword());
+        // 创建 Token 令牌,记录登录日志
+        return createTokenAfterLoginSuccess(user, reqVO.getMobile(), LoginLogTypeEnum.LOGIN_SMS, null);
+    }
+
+    /**
+     * 校验手机号是否达到上限
+     * @param mobile 手机号
+     */
+    private void verifyMobileIsMaximize(String mobile) {
+        //如果手机号已经到达注册的上限了那就返回报错
+        if (userService.getUserCountByMobile(mobile) >= MOBILE_REGISTER_MAX) {
+            throw exception(MOBILE_IS_MAXIMIZE);
+        }
+    }
+
+    /**
+     * 校验用户名
+     *
+     * @param username 用户名
+     */
+    private void verifyUsername(String username) {
+        if (userService.selectCountByUsername(username) > 0) {
+            throw exception(AUTH_USERNAME_EXISTS);
+        }
+    }
+
     private void createLogoutLog(Long userId) {
         LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO();
         reqDTO.setLogType(LoginLogTypeEnum.LOGOUT_SELF.getType());

+ 33 - 4
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/user/MemberUserService.java

@@ -40,12 +40,12 @@ public interface MemberUserService {
      * 如果用户已经存在,则直接进行返回
      *
      * @param mobile     手机号
+     * @param username   用户名
      * @param registerIp 注册 IP
      * @param terminal   终端 {@link TerminalEnum}
-     * @param linkId     链接编号
      * @return 用户对象
      */
-    MemberUserDO createUserIfAbsent(@Mobile String mobile, String registerIp, Integer terminal, Long linkId);
+    MemberUserDO createUserIfAbsent(@Mobile String mobile, String username, String registerIp, Integer terminal);
 
     /**
      * 创建用户
@@ -57,9 +57,10 @@ public interface MemberUserService {
      * @param registerIp 注册 IP
      * @param terminal   终端 {@link TerminalEnum}
      * @param linkId     链接编号
+     * @param password   密码
      * @return 用户对象
      */
-    MemberUserDO createUser(String mobile, String nickname, String avtar, String registerIp, Integer terminal, Long linkId);
+    MemberUserDO createUser(String mobile, String nickname, String avtar, String registerIp, Integer terminal, Long linkId, String username, String password);
 
     /**
      * 更新用户的最后登陆信息
@@ -190,5 +191,33 @@ public interface MemberUserService {
      */
     boolean updateUserPoint(Long userId, Integer point);
 
-    Long getUserIdBySystemUserId(Long systemUserId);
+    /**
+     * 根据用户名查询用户
+     * @param username 用户名
+     * @return 用户数量
+     */
+    Long selectCountByUsername(String username);
+
+    /**
+     * 根据用户名查询用户
+     * @param username 用户名
+     * @return 用户
+     */
+    MemberUserDO getUserByUsername(String username);
+
+    /**
+     * 根据手机号查询用户的数量
+     * @param mobile 手机号
+     * @return 数量
+     */
+    Long getUserCountByMobile(String mobile);
+
+    MemberUserDO selectByUsername(String username);
+
+    /**
+     * 根据系统用户ID查询用户
+     * @param systemUserId 系统用户ID
+     * @return 用户
+     */
+    List<MemberUserDO> getUserListBySystemUserId(Long systemUserId);
 }

+ 39 - 14
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/user/MemberUserServiceImpl.java

@@ -86,33 +86,33 @@ public class MemberUserServiceImpl implements MemberUserService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public MemberUserDO createUserIfAbsent(String mobile, String registerIp, Integer terminal, Long linkId) {
+    public MemberUserDO createUserIfAbsent(String mobile, String username, String registerIp, Integer terminal) {
         // 用户已经存在
-        MemberUserDO user = memberUserMapper.selectByMobile(mobile);
-        if (user != null) {
-            return user;
-        }
+        return memberUserMapper.selectByMobileAndUsername(mobile, username);
         // 用户不存在,则进行创建
-        return privateCreateUser(mobile, null, null, registerIp, terminal, linkId);
+//        return privateCreateUser(mobile, null, null, registerIp, terminal);
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public MemberUserDO createUser(String mobile, String nickname, String avtar, String registerIp, Integer terminal, Long linkId) {
-        return privateCreateUser(mobile, nickname, avtar, registerIp, terminal, linkId);
+    public MemberUserDO createUser(String mobile, String nickname, String avtar, String registerIp, Integer terminal, Long linkId, String username, String password) {
+        return privateCreateUser(mobile, nickname, avtar, registerIp, terminal, linkId, username, password);
     }
 
     @Transactional(rollbackFor = Exception.class)
     public MemberUserDO privateCreateUser(String mobile, String nickname, String avtar,
-                                          String registerIp, Integer terminal, Long linkId) {
+                                          String registerIp, Integer terminal, Long linkId, String username, String password) {
         // 通过手机号查询系统用户编号
         Long systemUserId = adminUserService.getUserIdByMobile(mobile);
         log.info("注册的手机号:{},系统用户编号:{}", mobile, systemUserId);
 
         // 生成密码
-        String password = IdUtil.fastSimpleUUID();
+        if (password == null) {
+            password = IdUtil.fastSimpleUUID();
+        }
         // 插入用户
         MemberUserDO user = new MemberUserDO();
+        user.setUsername(username);
         user.setMobile(mobile);
         user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
         user.setPassword(encodePassword(password)); // 加密密码
@@ -168,7 +168,13 @@ public class MemberUserServiceImpl implements MemberUserService {
     @Override
     public void updateUser(Long userId, AppMemberUserUpdateReqVO reqVO) {
         MemberUserDO updateObj = BeanUtils.toBean(reqVO, MemberUserDO.class).setId(userId);
-        memberUserMapper.updateById(updateObj);
+        if (memberUserMapper.updateById(updateObj) > 0 && StrUtil.isNotEmpty(reqVO.getNickname())) {
+            //同步修改其它地方保留的用户名
+            memberUserMapper.synchronizationUserNicknameForDUser(reqVO.getNickname(), userId);
+            memberUserMapper.synchronizationUserNicknameForIntegral(reqVO.getNickname(), userId);
+            memberUserMapper.synchronizationUserNicknameForSharePathDesc(reqVO.getNickname(), userId);
+            memberUserMapper.synchronizationUserNicknameForSharePathAnc(reqVO.getNickname(), userId);
+        }
     }
 
     @Override
@@ -344,9 +350,28 @@ public class MemberUserServiceImpl implements MemberUserService {
     }
 
     @Override
-    public Long getUserIdBySystemUserId(Long systemUserId) {
-        MemberUserDO memberUserDO = memberUserMapper.selectOne(MemberUserDO::getSystemUsersId, systemUserId);
-        return memberUserDO == null ? null : memberUserDO.getId();
+    public Long selectCountByUsername(String username) {
+        return memberUserMapper.selectCount(MemberUserDO::getUsername, username);
+    }
+
+    @Override
+    public MemberUserDO getUserByUsername(String username) {
+        return memberUserMapper.selectOne(MemberUserDO::getUsername, username);
+    }
+
+    @Override
+    public Long getUserCountByMobile(String mobile) {
+        return memberUserMapper.selectCount(MemberUserDO::getMobile, mobile);
+    }
+
+    @Override
+    public MemberUserDO selectByUsername(String username) {
+        return memberUserMapper.selectOne(MemberUserDO::getUsername, username);
+    }
+
+    @Override
+    public List<MemberUserDO> getUserListBySystemUserId(Long systemUserId) {
+        return memberUserMapper.selectList(MemberUserDO::getSystemUsersId, systemUserId);
     }
 
 }

+ 18 - 0
feifan-module-member/feifan-module-member-biz/src/main/resources/mapper/user/MemberUserMapper.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.newfeifan.mall.module.member.dal.mysql.user.MemberUserMapper">
+
+    <update id="synchronizationUserNicknameForDUser">
+        update distri_duser set nick_name = #{nickname} where user_id = #{userId};
+    </update>
+    <update id="synchronizationUserNicknameForIntegral">
+        update distri_integral set nick_name = #{nickname} where user_id = #{userId};
+    </update>
+    <update id="synchronizationUserNicknameForSharePathDesc">
+        update distri_share_path set desc_nick_name = #{nickname} where descendant = #{userId};
+    </update>
+    <update id="synchronizationUserNicknameForSharePathAnc">
+        update distri_share_path set anc_name = #{nickname} where ancestor = #{userId};
+    </update>
+
+</mapper>

+ 5 - 0
feifan-module-pay/feifan-module-pay-biz/src/main/java/cn/newfeifan/mall/module/pay/controller/admin/order/vo/PayOrderRespVO.java

@@ -19,4 +19,9 @@ public class PayOrderRespVO extends PayOrderBaseVO {
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime createTime;
 
+    @Schema(description = "待确权积分")
+    private Long jf;
+
+    @Schema(description = "待确权身价")
+    private Double sj;
 }

+ 7 - 3
feifan-module-pay/feifan-module-pay-biz/src/main/java/cn/newfeifan/mall/module/pay/controller/app/order/AppPayOrderController.java

@@ -42,9 +42,13 @@ public class AppPayOrderController {
     @Operation(summary = "获得支付订单")
     @Parameter(name = "id", description = "支付订单编号", required = true, example = "1024")
     public CommonResult<PayOrderRespVO> getOrder(@RequestParam("id") Long id) {
-        CommonResult<PayOrderRespVO> rs =
-                success(PayOrderConvert.INSTANCE.convert(payOrderService.getOrder(id)));
-        return rs;
+        return success(PayOrderConvert.INSTANCE.convert(payOrderService.getOrder(id)));
+    }
+    @GetMapping("/getByStatus")
+    @Operation(summary = "获得支付订单")
+    @Parameter(name = "id", description = "支付订单编号", required = true, example = "1024")
+    public CommonResult<PayOrderRespVO> getOrderByStatus(@RequestParam("id") Long id) {
+        return success(PayOrderConvert.INSTANCE.convert(payOrderService.getOrderByStatus(id)));
     }
 
     @PostMapping("/submit")

+ 6 - 0
feifan-module-pay/feifan-module-pay-biz/src/main/java/cn/newfeifan/mall/module/pay/dal/mysql/order/PayOrderExtensionMapper.java

@@ -1,6 +1,7 @@
 package cn.newfeifan.mall.module.pay.dal.mysql.order;
 
 import cn.newfeifan.mall.framework.mybatis.core.mapper.BaseMapperX;
+import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.newfeifan.mall.module.pay.dal.dataobject.order.PayOrderExtensionDO;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import org.apache.ibatis.annotations.Mapper;
@@ -30,4 +31,9 @@ public interface PayOrderExtensionMapper extends BaseMapperX<PayOrderExtensionDO
                 .le(PayOrderExtensionDO::getCreateTime, minCreateTime));
     }
 
+    default PayOrderExtensionDO selectByPayId(Long id) {
+        return selectList(new LambdaQueryWrapperX<PayOrderExtensionDO>()
+                .eq(PayOrderExtensionDO::getOrderId, id)
+                .orderByDesc(PayOrderExtensionDO::getCreateTime)).get(0);
+    }
 }

+ 18 - 0
feifan-module-pay/feifan-module-pay-biz/src/main/java/cn/newfeifan/mall/module/pay/service/order/PayOrderService.java

@@ -31,6 +31,16 @@ public interface PayOrderService {
      */
     PayOrderDO getOrder(Long id);
 
+    PayOrderDO getOrderByStatus(PayOrderDO payOrderDO);
+
+    /**
+     * 获得支付订单
+     *
+     * @param id 编号
+     * @return 支付订单
+     */
+    PayOrderDO getOrderByStatus(Long id);
+
     /**
      * 获得支付订单
      *
@@ -139,6 +149,14 @@ public interface PayOrderService {
      */
     int syncOrder(LocalDateTime minCreateTime);
 
+    /**
+     * 同步单个支付拓展单
+     *
+     * @param orderExtension 支付拓展单
+     * @return 是否已支付
+     */
+    boolean syncOrder(PayOrderExtensionDO orderExtension);
+
     /**
      * 将已过期的订单,状态修改为已关闭
      *

+ 45 - 2
feifan-module-pay/feifan-module-pay-biz/src/main/java/cn/newfeifan/mall/module/pay/service/order/PayOrderServiceImpl.java

@@ -80,6 +80,37 @@ public class PayOrderServiceImpl implements PayOrderService {
         return orderMapper.selectById(id);
     }
 
+
+    @Override
+    public PayOrderDO getOrderByStatus(PayOrderDO payOrderDO) {
+        //添加验证是否支付成功
+        if(payOrderDO.getStatus().equals(PayOrderStatusEnum.WAITING.getStatus())){
+            //修改程序,当微信支付回调的时候再次向微信请求查询pay订单的支付状态
+            log.info("============支付成功查询:支付订单号{}",payOrderDO.getId());
+            log.info("============支付成功查询:支付订单详情{}",payOrderDO);
+            PayOrderExtensionDO payOrderExtensionDO = orderExtensionMapper.selectByPayId(payOrderDO.getId());
+            syncOrder(payOrderExtensionDO);
+        }
+
+        PayOrderDO newPayOrderDO = orderMapper.selectById(payOrderDO.getId());
+
+        return newPayOrderDO;
+    }
+
+    @Override
+    public PayOrderDO getOrderByStatus(Long id) {
+        //添加验证是否支付成功
+        PayOrderDO payOrderDO = orderMapper.selectById(id);
+        if(payOrderDO.getStatus().equals(PayOrderStatusEnum.WAITING.getStatus())){
+            //修改程序,当微信支付回调的时候再次向微信请求查询pay订单的支付状态
+            log.info("============支付成功查询:支付订单号{}",payOrderDO.getId());
+            log.info("============支付成功查询:支付订单详情{}",payOrderDO);
+            PayOrderExtensionDO payOrderExtensionDO = orderExtensionMapper.selectByPayId(payOrderDO.getId());
+            syncOrder(payOrderExtensionDO);
+        }
+        return orderMapper.selectById(id);
+    }
+
     @Override
     public PayOrderDO getOrder(Long appId, String merchantOrderId) {
         return orderMapper.selectByAppIdAndMerchantOrderId(appId, merchantOrderId);
@@ -141,12 +172,18 @@ public class PayOrderServiceImpl implements PayOrderService {
 
     @Override // 注意,这里不能添加事务注解,避免调用支付渠道失败时,将 PayOrderExtensionDO 回滚了
     public PayOrderSubmitRespVO submitOrder(PayOrderSubmitReqVO reqVO, String userIp) {
+
+        log.warn("[submitOrder--------->unifiedOrderResp][订单id({})000000支付开始]", reqVO.getId());
+
+
         // 1.1 获得 PayOrderDO ,并校验其是否存在
         PayOrderDO order = validateOrderCanSubmit(reqVO.getId());
         // 1.32 校验支付渠道是否有效
         PayChannelDO channel = validateChannelCanSubmit(order.getAppId(), reqVO.getChannelCode());
         PayClient client = channelService.getPayClient(channel.getId());
 
+        log.warn("[submitOrder--------->unifiedOrderResp][订单id({})1111111支付渠道校验通过]", order.getId());
+
         // 2. 插入 PayOrderExtensionDO
         String no = noRedisDAO.generate(payProperties.getOrderNoPrefix());
         PayOrderExtensionDO orderExtension = PayOrderConvert.INSTANCE.convert(reqVO, userIp)
@@ -155,6 +192,8 @@ public class PayOrderServiceImpl implements PayOrderService {
                 .setStatus(PayOrderStatusEnum.WAITING.getStatus());
         orderExtensionMapper.insert(orderExtension);
 
+        log.warn("[submitOrder--------->unifiedOrderResp][订单id({})2222222支付渠道校验通过]", order.getId());
+
         // 3. 调用三方接口
         PayOrderUnifiedReqDTO unifiedOrderReqDTO = PayOrderConvert.INSTANCE.convert2(reqVO, userIp)
                 // 商户相关的字段
@@ -166,7 +205,7 @@ public class PayOrderServiceImpl implements PayOrderService {
                 .setPrice(order.getPrice()).setExpireTime(order.getExpireTime());
         PayOrderRespDTO unifiedOrderResp = client.unifiedOrder(unifiedOrderReqDTO);
 
-        log.error("[submitOrder--------->unifiedOrderResp][订单状态({}),支付状态({})]", order.getId(),unifiedOrderResp.getStatus());
+        log.warn("[submitOrder--------->unifiedOrderResp][订单id({})333333支付完成,支付状态({})]", order.getId(), unifiedOrderResp.getStatus());
 
         // 4. 如果调用直接支付成功,则直接更新支付单状态为成功。例如说:付款码支付,免密支付时,就直接验证支付成功
         if (unifiedOrderResp != null) {
@@ -179,6 +218,7 @@ public class PayOrderServiceImpl implements PayOrderService {
             // 此处需要读取最新的状态
             order = orderMapper.selectById(order.getId());
         }
+        log.warn("如果调用直接支付成功,则直接更新支付单状态为成功。例如说:付款码支付,免密支付时,就直接验证支付成功:{}", unifiedOrderResp);
         return PayOrderConvert.INSTANCE.convert(order, unifiedOrderResp);
     }
 
@@ -272,6 +312,8 @@ public class PayOrderServiceImpl implements PayOrderService {
     @Transactional(rollbackFor = Exception.class)
     // 注意,如果是方法内调用该方法,需要通过 getSelf().notifyPayOrder(channel, notify) 调用,否则事务不生效
     public void notifyOrder(PayChannelDO channel, PayOrderRespDTO notify) {
+        log.warn("public void notifyOrder(PayChannelDO channel, PayOrderRespDTO notify)");
+        log.warn("===========支付订单的状态:{}====", notify.getStatus());
         // 情况一:支付成功的回调
         if (PayOrderStatusRespEnum.isSuccess(notify.getStatus())) {
             notifyOrderSuccess(channel, notify);
@@ -475,7 +517,7 @@ public class PayOrderServiceImpl implements PayOrderService {
      * @param orderExtension 支付拓展单
      * @return 是否已支付
      */
-    private boolean syncOrder(PayOrderExtensionDO orderExtension) {
+    public boolean syncOrder(PayOrderExtensionDO orderExtension) {
         try {
             // 1.1 查询支付订单信息
             PayClient payClient = channelService.getPayClient(orderExtension.getChannelId());
@@ -484,6 +526,7 @@ public class PayOrderServiceImpl implements PayOrderService {
                 return false;
             }
             PayOrderRespDTO respDTO = payClient.getOrder(orderExtension.getNo());
+            log.info("===========微信回调结果PayOrderRespDTO:{}",respDTO);
             // 1.2 回调支付结果
             notifyOrder(orderExtension.getChannelId(), respDTO);
 

+ 15 - 0
feifan-module-system/feifan-module-system-api/src/main/java/cn/newfeifan/mall/module/system/api/social/SocialUserApi.java

@@ -52,4 +52,19 @@ public interface SocialUserApi {
      */
     SocialUserRespDTO getSocialUserByCode(Integer userType, Integer socialType, String code, String state, Boolean isFirst, Boolean isRegister);
 
+    /**
+     * 判断微信是否绑定此账号
+     * @param openId openId
+     * @param userId 用户编号
+     * @return 是否
+     */
+    Boolean wxIsBindByUserId(String openId,Long userId);
+
+    /**
+     * 判断微信是否绑定到上限
+     * @param socialUserId 社交用户编号
+     * @return 是否
+     */
+    Boolean wxBindIsMax(Long socialUserId);
+
 }

+ 11 - 0
feifan-module-system/feifan-module-system-api/src/main/java/cn/newfeifan/mall/module/system/api/social/dto/SocialUserRespDTO.java

@@ -4,6 +4,8 @@ import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
+import java.util.List;
+
 /**
  * 社交用户 Response DTO
  *
@@ -14,6 +16,11 @@ import lombok.NoArgsConstructor;
 @AllArgsConstructor
 public class SocialUserRespDTO {
 
+    /**
+     * 社交平台的编号
+     */
+    private Long id;
+
     /**
      * 社交用户的 openid
      */
@@ -31,5 +38,9 @@ public class SocialUserRespDTO {
      * 关联的用户编号
      */
     private Long userId;
+    /**
+     * 关联的用户编号
+     */
+    private List<Long> userIds;
 
 }

+ 1 - 3
feifan-module-system/feifan-module-system-api/src/main/java/cn/newfeifan/mall/module/system/enums/ErrorCodeConstants.java

@@ -4,7 +4,6 @@ import cn.newfeifan.mall.framework.common.exception.ErrorCode;
 
 /**
  * System 错误码枚举类
- *
  * system 系统,使用 1-002-000-000 段
  */
 public interface ErrorCodeConstants {
@@ -12,7 +11,7 @@ public interface ErrorCodeConstants {
     // ========== AUTH 模块 1-002-000-000 ==========
     ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1_002_000_000, "登录失败,账号密码不正确");
     ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1_002_000_001, "登录失败,账号被禁用");
-    ErrorCode AUTH_LOGIN_USER_IS_FIRST = new ErrorCode(1_002_000_002, "第一次登录请输入手机号校验");
+    ErrorCode AUTH_LOGIN_USER_IS_FIRST = new ErrorCode(1_002_000_002, "注册请输入用户名 + 手机号校验");
     ErrorCode AUTH_LOGIN_USER_ERROR_CODE = new ErrorCode(1_002_000_002, "code校验失败");
     ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1_002_000_004, "验证码不正确,原因:{}");
     ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1_002_000_005, "未绑定账号,需要进行绑定");
@@ -177,5 +176,4 @@ public interface ErrorCodeConstants {
     ErrorCode WECHAT_MSG_TEMPLATE_REDIS_NOT_EXISTS = new ErrorCode(1_002_028_002, "我想消息模板缓存异常");
     ErrorCode CONFIG_NOT_EXISTS = new ErrorCode(1_002_028_003, "系统配置不存在");
     ErrorCode CONFIG_REDIS_NOT_EXISTS = new ErrorCode(1_002_028_004, "系统配置不存在");
-
 }

+ 10 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/api/social/SocialUserApiImpl.java

@@ -42,4 +42,14 @@ public class SocialUserApiImpl implements SocialUserApi {
        return socialUserService.getSocialUserByCode(userType, socialType, code, state, isFirst, isRegister);
     }
 
+    @Override
+    public Boolean wxIsBindByUserId(String openId, Long userId) {
+        return socialUserService.wxIsBindByUserId(openId,userId);
+    }
+
+    @Override
+    public Boolean wxBindIsMax(Long socialUserId) {
+        return socialUserService.wxBindIsMax(socialUserId);
+    }
+
 }

Vissa filer visades inte eftersom för många filer har ändrats