8
0

49 Commity d34a0380da ... d58273f0c1

Autor SHA1 Správa Dátum
  codingliang d58273f0c1 Merge remote-tracking branch 'origin/dev/order-type-up' into dev/order-type-up 6 mesiacov pred
  codingliang 1fe9139474 骑手送达时短信改为非必须 6 mesiacov pred
  codingliang 666bc22829 修复获取最近30天销售数据报错问题 6 mesiacov pred
  codingliang 0d10d5fb25 修改店铺默认排序规则 6 mesiacov pred
  codingliang 723df4daa7 修改店铺默认排序规则 7 mesiacov pred
  codingliang b7e596b778 会员立减金额规则调整 7 mesiacov pred
  codingliang 29e868db1b 修改会员优惠描述 7 mesiacov pred
  codingliang 83b26856b8 新增会员优惠和活动不同时享受限制 7 mesiacov pred
  codingliang 29c8b514d4 调整get-can-reduce接口 7 mesiacov pred
  codingliang 42227d3827 Merge remote-tracking branch 'refs/remotes/origin/dev/vip-up' into dev/order-type-up 7 mesiacov pred
  codingliang d3297c8ef3 会员优惠新增最低金额判断 7 mesiacov pred
  codingliang 7fae66562b 修复小票打印订单打包费单独计算问题 7 mesiacov pred
  codingliang d775235203 修复小票打印订单打包费单独计算问题 7 mesiacov pred
  codingliang 7d337297c8 Merge branch 'refs/heads/dev/vip-up' into dev/order-type-up 7 mesiacov pred
  codingliang 0ba755c9aa 修复构建店铺列表缓存时缺失VIP优惠筛选字段问题 7 mesiacov pred
  codingliang 09ffc774d1 新增到店堂食额外订单类型,同步调整打包费、打印逻辑 7 mesiacov pred
  codingliang 94bc5c25fa 调整骑手申请认证接口 7 mesiacov pred
  codingliang 5542f5e9c9 去除拒绝骑手认证时的退款逻辑 7 mesiacov pred
  codingliang e7f2e25581 小程序跑腿师傅实名认证取消支付步骤 7 mesiacov pred
  codingliang b4ad19c6cc 修复商家缴纳保证金后没有钱包明细问题 7 mesiacov pred
  codingliang 71212e29a3 兼容商户端小程序获取支付参数 7 mesiacov pred
  codingliang 1f8a29cd90 修复只定义异常未抛出异常问题 7 mesiacov pred
  codingliang b4b230e71e 新增商户缴纳保证金(新)接口 7 mesiacov pred
  codingliang c76d99aa99 修复推广码推广失败问题 7 mesiacov pred
  codingliang 6adcf72ad8 购买会员新增推荐码校验 7 mesiacov pred
  codingliang 843a1faa0e 修复会员记录查询条件不生效问题 7 mesiacov pred
  codingliang 8b197446ab 新增获取用户是否可以会员立减接口 7 mesiacov pred
  codingliang 3b8fe243a5 新增推广码导出接口; 7 mesiacov pred
  codingliang c5190b6f78 修复vip导出文件失败问题 7 mesiacov pred
  codingliang e804dff08f vip_promo_record表pay_rel_id长度调整 7 mesiacov pred
  codingliang 8e810d5eba 修复vip导出文件失败问题 7 mesiacov pred
  codingliang fb530e62fd 修复会员购买获取支付参数场景选择错误问题 7 mesiacov pred
  codingliang 9685931a0f 修复店铺查询异常 7 mesiacov pred
  codingliang 4e14861b78 分页查询会员推广记录新增特殊照顾查询接口 7 mesiacov pred
  codingliang 668537176f 文件导出部分接口userId获取方式调整 7 mesiacov pred
  codingliang b9de92501c 会员推广记录导出接口调整 7 mesiacov pred
  wanxl c956adbf46 解决循环依赖问题 7 mesiacov pred
  codingliang a58f832871 tbOrder新增vipPromotion字段,获取支付参数和完成订单时加入会员优惠逻辑 7 mesiacov pred
  codingliang 5b5a6a61cd goodsShop新增vipPromotion字段 7 mesiacov pred
  codingliang e298a57cf4 会员推广管理、特殊照顾学生管理新增admin窄化路径 7 mesiacov pred
  codingliang 0ec0a54bf1 del_flag设置默认值 7 mesiacov pred
  codingliang 1e3fa3826b 特殊学生导出接口调整 7 mesiacov pred
  codingliang 05193a81e8 恢复被删除的低版本poi依赖 7 mesiacov pred
  codingliang c69d9766ec 删除低版本的poi 7 mesiacov pred
  codingliang 53e86ee92a 学号字段类型调整 7 mesiacov pred
  codingliang 15a61dfab7 修复sql中删除字段字段名写错问题 7 mesiacov pred
  codingliang edad3a8d0f 修复AppOrderService引用自身问题 7 mesiacov pred
  codingliang b6e2f11829 新增vip会员管理功能接口 7 mesiacov pred
  codingliang 7502c3cae3 vip会员升级基础代码生成 7 mesiacov pred
82 zmenil súbory, kde vykonal 2859 pridanie a 562 odobranie
  1. 55 0
      db/update_251111.sql
  2. 2 0
      db/update_251128.sql
  3. 2 0
      db/update_251205.sql
  4. 7 0
      src/main/java/com/sqx/modules/app/service/UserService.java
  5. 2 0
      src/main/java/com/sqx/modules/app/service/impl/UserMoneyDetailsServiceImpl.java
  6. 5 3
      src/main/java/com/sqx/modules/app/service/impl/UserMoneyServiceImpl.java
  7. 9 0
      src/main/java/com/sqx/modules/app/service/impl/UserServiceImpl.java
  8. 9 0
      src/main/java/com/sqx/modules/coupon/service/TbCouponUserService.java
  9. 18 0
      src/main/java/com/sqx/modules/coupon/service/impl/TbTbCouponUserServiceImpl.java
  10. 5 11
      src/main/java/com/sqx/modules/datacentre/controller/DataCentreController.java
  11. 28 107
      src/main/java/com/sqx/modules/datacentre/service/impl/DataCentreServiceImpl.java
  12. 17 12
      src/main/java/com/sqx/modules/errand/service/impl/TbIndentServiceImpl.java
  13. 41 9
      src/main/java/com/sqx/modules/exportExecl/controller/ExportExeclController.java
  14. 2 2
      src/main/java/com/sqx/modules/goods/controller/GoodsController.java
  15. 6 2
      src/main/java/com/sqx/modules/goods/controller/GoodsShopController.java
  16. 5 18
      src/main/java/com/sqx/modules/goods/controller/app/AppGoodsController.java
  17. 2 2
      src/main/java/com/sqx/modules/goods/dao/GoodsShopDao.java
  18. 6 0
      src/main/java/com/sqx/modules/goods/dto/ShopQueryDTO.java
  19. 17 15
      src/main/java/com/sqx/modules/goods/entity/GoodsShop.java
  20. 1 2
      src/main/java/com/sqx/modules/goods/service/GoodsService.java
  21. 14 0
      src/main/java/com/sqx/modules/goods/service/GoodsShopService.java
  22. 22 7
      src/main/java/com/sqx/modules/goods/service/impl/GoodsServiceImpl.java
  23. 34 0
      src/main/java/com/sqx/modules/goods/service/impl/GoodsShopServiceImpl.java
  24. 74 0
      src/main/java/com/sqx/modules/member/controller/SpecialFavorStudentController.java
  25. 81 0
      src/main/java/com/sqx/modules/member/controller/VipPromoCodeController.java
  26. 33 0
      src/main/java/com/sqx/modules/member/controller/app/AppSpecialFavorStudentController.java
  27. 52 0
      src/main/java/com/sqx/modules/member/controller/app/AppVipController.java
  28. 15 0
      src/main/java/com/sqx/modules/member/dao/SpecialFavorStudentDao.java
  29. 12 0
      src/main/java/com/sqx/modules/member/dao/VipPromoCodeDao.java
  30. 15 0
      src/main/java/com/sqx/modules/member/dao/VipPromoRecordDao.java
  31. 27 0
      src/main/java/com/sqx/modules/member/dto/CanReduceQueryDTO.java
  32. 30 0
      src/main/java/com/sqx/modules/member/dto/SpecialFavorStudentDTO.java
  33. 25 0
      src/main/java/com/sqx/modules/member/dto/SpecialFavorStudentVerifyDTO.java
  34. 34 0
      src/main/java/com/sqx/modules/member/dto/VipPromoCodeDTO.java
  35. 41 0
      src/main/java/com/sqx/modules/member/dto/VipPromoRecordDTO.java
  36. 63 0
      src/main/java/com/sqx/modules/member/entity/SpecialFavorStudent.java
  37. 63 0
      src/main/java/com/sqx/modules/member/entity/VipPromoCode.java
  38. 73 0
      src/main/java/com/sqx/modules/member/entity/VipPromoRecord.java
  39. 82 0
      src/main/java/com/sqx/modules/member/query/SpecialFavorStudentQuery.java
  40. 50 0
      src/main/java/com/sqx/modules/member/query/VipPromoCodeQuery.java
  41. 105 0
      src/main/java/com/sqx/modules/member/query/VipPromoRecordQuery.java
  42. 27 0
      src/main/java/com/sqx/modules/member/service/SpecialFavorStudentService.java
  43. 36 0
      src/main/java/com/sqx/modules/member/service/VipPromoCodeService.java
  44. 18 0
      src/main/java/com/sqx/modules/member/service/VipPromoRecordService.java
  45. 40 0
      src/main/java/com/sqx/modules/member/service/VipService.java
  46. 152 0
      src/main/java/com/sqx/modules/member/service/impl/SpecialFavorStudentServiceImpl.java
  47. 97 0
      src/main/java/com/sqx/modules/member/service/impl/VipPromoCodeServiceImpl.java
  48. 55 0
      src/main/java/com/sqx/modules/member/service/impl/VipPromoRecordServiceImpl.java
  49. 227 0
      src/main/java/com/sqx/modules/member/service/impl/VipServiceImpl.java
  50. 50 0
      src/main/java/com/sqx/modules/member/vo/SpecialFavorStudentVO.java
  51. 42 0
      src/main/java/com/sqx/modules/member/vo/VipPromoCodeVO.java
  52. 51 0
      src/main/java/com/sqx/modules/member/vo/VipPromoRecordVO.java
  53. 26 0
      src/main/java/com/sqx/modules/member/vo/VipReduceVO.java
  54. 7 0
      src/main/java/com/sqx/modules/order/dao/AppOrderDao.java
  55. 13 10
      src/main/java/com/sqx/modules/order/entity/TbOrder.java
  56. 14 0
      src/main/java/com/sqx/modules/order/service/AppOrderService.java
  57. 110 19
      src/main/java/com/sqx/modules/order/service/impl/AppAppOrderServiceImpl.java
  58. 4 19
      src/main/java/com/sqx/modules/pay/controller/app/ApiWeiXinErrRiderPayController.java
  59. 0 2
      src/main/java/com/sqx/modules/pay/controller/app/ApiWeiXinPayController.java
  60. 4 0
      src/main/java/com/sqx/modules/pay/dto/GetPayParamDTO.java
  61. 8 0
      src/main/java/com/sqx/modules/pay/dto/PayOrderDTO.java
  62. 42 0
      src/main/java/com/sqx/modules/pay/dto/RiderCertificationDTO.java
  63. 5 0
      src/main/java/com/sqx/modules/pay/entity/PayDetails.java
  64. 2 2
      src/main/java/com/sqx/modules/pay/service/WxErrRiderService.java
  65. 23 60
      src/main/java/com/sqx/modules/pay/service/impl/NewPayServiceImpl.java
  66. 1 0
      src/main/java/com/sqx/modules/pay/service/impl/PayDetailsServiceImpl.java
  67. 28 25
      src/main/java/com/sqx/modules/pay/service/impl/WxErrRiderServiceImpl.java
  68. 8 62
      src/main/java/com/sqx/modules/pay/service/impl/WxServiceImpl.java
  69. 2 0
      src/main/java/com/sqx/modules/printInfo/entity/eOrderTypeExtra.java
  70. 51 21
      src/main/java/com/sqx/modules/shop/controller/app/ShopMoneyController.java
  71. 142 0
      src/main/java/com/sqx/modules/utils/PromotionCodeUtil.java
  72. 108 0
      src/main/java/com/sqx/modules/utils/VipExpirationUtil.java
  73. 19 7
      src/main/java/com/sqx/modules/utils/fieYun/FeiYunUtils.java
  74. 5 0
      src/main/java/com/sqx/scheduler/config/SchedulerLock.java
  75. 107 11
      src/main/java/com/sqx/scheduler/export/ExportScheduler.java
  76. 30 5
      src/main/java/com/sqx/scheduler/order/OrderScheduler.java
  77. 7 1
      src/main/resources/mapper/goods/GoodsShopMapper.xml
  78. 40 0
      src/main/resources/mapper/member/SpecialFavorStudentMapper.xml
  79. 8 0
      src/main/resources/mapper/member/VipPromoCodeMapper.xml
  80. 49 0
      src/main/resources/mapper/member/VipPromoRecordMapper.xml
  81. 13 0
      src/main/resources/mapper/order/OrderMapper.xml
  82. 4 128
      src/test/java/OrderTest.java

+ 55 - 0
db/update_251111.sql

@@ -0,0 +1,55 @@
+DROP TABLE IF EXISTS special_favor_student;
+CREATE TABLE special_favor_student(
+    `id` bigint NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
+    `del_flag` VARCHAR(1) NOT NULL DEFAULT '0' COMMENT '删除标识;0未删除、1已删除' ,
+    `name` VARCHAR(32) NOT NULL   COMMENT '真实姓名' ,
+    `student_number` VARCHAR(32) NOT NULL   COMMENT '学号' ,
+    `verify_status` VARCHAR(1) NOT NULL  DEFAULT 0 COMMENT '验证状态;0未认证、1已认证' ,
+    `create_time` DATETIME NOT NULL   COMMENT '创建时间' ,
+    `verify_user_id` bigint    COMMENT '验证用户id' ,
+    `last_verify_time` DATETIME    COMMENT '最后验证时间' ,
+    PRIMARY KEY (id)
+)  COMMENT = '特殊照顾学生';
+
+DROP TABLE IF EXISTS vip_promo_code;
+CREATE TABLE vip_promo_code(
+    `id` bigint NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
+    `del_flag` VARCHAR(1) NOT NULL DEFAULT '0' COMMENT '删除标识;0未删除、1已删除' ,
+    `user_name` VARCHAR(32) NOT NULL   COMMENT '推广人名称' ,
+    `promo_code` VARCHAR(32) NOT NULL   COMMENT '推广码' ,
+    `id_card` VARCHAR(32) NOT NULL   COMMENT '推广人身份证号码' ,
+    `phone` VARCHAR(32) NOT NULL   COMMENT '推广人手机号码' ,
+    `promo_count` INT NOT NULL  DEFAULT 0 COMMENT '推广人次' ,
+    `create_time` DATETIME NOT NULL   COMMENT '创建时间' ,
+    PRIMARY KEY (id)
+)  COMMENT = '会员推广码';
+
+
+DROP TABLE IF EXISTS vip_promo_record;
+CREATE TABLE vip_promo_record(
+    `id` bigint NOT NULL AUTO_INCREMENT  COMMENT 'id' ,
+    `del_flag` VARCHAR(1) NOT NULL DEFAULT '0' COMMENT '删除标识;0未删除、1已删除' ,
+    `promo_code_id` bigint    COMMENT '推广码id' ,
+    `user_id` bigint NOT NULL   COMMENT '用户id' ,
+    `user_name` VARCHAR(32) NOT NULL   COMMENT '用户名称' ,
+    `user_phone` VARCHAR(32) NOT NULL   COMMENT '用户手机号' ,
+    `create_time` DATETIME NOT NULL   COMMENT '创建时间' ,
+    `pay_type` VARCHAR(1) NOT NULL   COMMENT '支付类型;1微信支付、2余额支付、3暖心照顾' ,
+    `pay_amount` DECIMAL(24,6) NOT NULL  DEFAULT 0 COMMENT '支付金额' ,
+    `pay_rel_id` VARCHAR(64)    COMMENT '支付关联id' ,
+    PRIMARY KEY (id)
+)  COMMENT = '会员推广记录';
+
+-- 支付详情添加额外参数字段
+alter table pay_details add extra varchar(100) comment '额外备用参数' after remark;
+
+-- 商品添加参与vip优惠标识 0否 1是
+alter table goods_shop add vip_promotion varchar(1) not null default 0 comment '是否参与vip优惠 0否 1是';
+
+-- 新增会员每单立减金额(元)、会员每天优惠单数(个)配置
+INSERT INTO `tcwm2.5`.`common_info`(`id`, `create_at`, `max`, `min`, `type`, `value`, `condition_from`) VALUES (444, '2025-11-13 14:47:44', NULL, '会员每单立减金额(元)', 444, '2', 'huiyuan');
+INSERT INTO `tcwm2.5`.`common_info`(`id`, `create_at`, `max`, `min`, `type`, `value`, `condition_from`) VALUES (445, '2025-11-13 14:47:44', NULL, '会员每天优惠单数(个)', 445, '2', 'huiyuan');
+
+-- 订单添加是否会员优惠字段 0否 1是
+alter table tb_order add vip_promotion varchar(1) not null default '0' comment '是否会员优惠 0否 1是';
+CREATE INDEX idx_user_vip_pay_time ON tb_order(user_id, vip_promotion, is_pay, pay_time);

+ 2 - 0
db/update_251128.sql

@@ -0,0 +1,2 @@
+
+INSERT INTO `tcwm2.5`.`common_info`(`id`, `create_at`, `max`, `min`, `type`, `value`, `condition_from`) VALUES (446, '2025-11-28 14:47:44', NULL, '会员立减最低金额(元)', 446, '10', 'huiyuan');

+ 2 - 0
db/update_251205.sql

@@ -0,0 +1,2 @@
+-- 创建订单表订单状态、支付时间、店铺ID索引 用于查询按店铺分组的订单状态、支付时间的统计信息
+CREATE INDEX idx_status_pay_time_shop ON tb_order(status, pay_time, shop_id);

+ 7 - 0
src/main/java/com/sqx/modules/app/service/UserService.java

@@ -237,4 +237,11 @@ public interface UserService extends IService<UserEntity> {
     Result sendMsgDXB(String phone, String state, int code);
     Result sendMsgDXB(String phone, String state, int code);
 
 
     UserEntity getByAdminId(Long adminUserId);
     UserEntity getByAdminId(Long adminUserId);
+
+    /**
+     * 更新用户为会员
+     * @param userId             用户id
+     * @param futureTimeWithDays 会员过期时间
+     */
+    void updateUserToVip(Long userId, String futureTimeWithDays);
 }
 }

+ 2 - 0
src/main/java/com/sqx/modules/app/service/impl/UserMoneyDetailsServiceImpl.java

@@ -22,6 +22,7 @@ import com.sqx.modules.pay.controller.query.WalletDetailQuery;
 import com.sqx.modules.pay.vo.WalletDetailVO;
 import com.sqx.modules.pay.vo.WalletDetailVO;
 import com.sqx.modules.utils.excel.ExcelData;
 import com.sqx.modules.utils.excel.ExcelData;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
 import java.math.BigDecimal;
 import java.math.BigDecimal;
@@ -38,6 +39,7 @@ public class UserMoneyDetailsServiceImpl extends ServiceImpl<UserMoneyDetailsDao
     @Autowired
     @Autowired
     private CommonInfoDao commonInfoDao;
     private CommonInfoDao commonInfoDao;
 
 
+    @Lazy
     @Autowired
     @Autowired
     private TbIndentService tbIndentService;
     private TbIndentService tbIndentService;
 
 

+ 5 - 3
src/main/java/com/sqx/modules/app/service/impl/UserMoneyServiceImpl.java

@@ -12,6 +12,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.sqx.common.exception.SqxException;
 import com.sqx.common.exception.SqxException;
 import com.sqx.common.utils.PageUtils;
 import com.sqx.common.utils.PageUtils;
 import com.sqx.common.utils.Result;
 import com.sqx.common.utils.Result;
+import com.sqx.common.utils.SpringContextUtils;
 import com.sqx.modules.app.bo.UpdateMoneyBO;
 import com.sqx.modules.app.bo.UpdateMoneyBO;
 import com.sqx.modules.app.dao.UserDao;
 import com.sqx.modules.app.dao.UserDao;
 import com.sqx.modules.app.dao.UserMoneyDao;
 import com.sqx.modules.app.dao.UserMoneyDao;
@@ -32,6 +33,7 @@ import com.sqx.modules.pay.service.NewPayService;
 import com.sqx.modules.utils.SenInfoCheckUtil;
 import com.sqx.modules.utils.SenInfoCheckUtil;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
@@ -57,10 +59,9 @@ public class UserMoneyServiceImpl extends ServiceImpl<UserMoneyDao, UserMoney> i
     private CommonInfoService commonInfoService;
     private CommonInfoService commonInfoService;
     @Autowired
     @Autowired
     private RechargeRecordService rechargeRecordService;
     private RechargeRecordService rechargeRecordService;
+    @Lazy
     @Autowired
     @Autowired
     private GoodsShopService goodsShopService;
     private GoodsShopService goodsShopService;
-    @Autowired
-    private NewPayService newPayService;
 
 
     @Override
     @Override
     public void updateMoney(int i, Long userId, double money) {
     public void updateMoney(int i, Long userId, double money) {
@@ -273,7 +274,7 @@ public class UserMoneyServiceImpl extends ServiceImpl<UserMoneyDao, UserMoney> i
         Integer changeType = updateMoneyBO.getType();
         Integer changeType = updateMoneyBO.getType();
         if (changeType == 2) {
         if (changeType == 2) {
             if (userMoney.getMoney().compareTo(changeAmount) <= 0) {
             if (userMoney.getMoney().compareTo(changeAmount) <= 0) {
-                throw new SqxException("当前店铺钱包余额不足,扣减失败!");
+                throw new SqxException("用户钱包余额不足,扣减失败!");
             }
             }
         }
         }
 
 
@@ -322,6 +323,7 @@ public class UserMoneyServiceImpl extends ServiceImpl<UserMoneyDao, UserMoney> i
         UserMoneyDetails userMoneyDetails = updateUserMoney(updateMoneyBO);
         UserMoneyDetails userMoneyDetails = updateUserMoney(updateMoneyBO);
 
 
         String traceNo = IdWorker.getTimeId();
         String traceNo = IdWorker.getTimeId();
+        NewPayService newPayService = SpringContextUtils.getBean(NewPayService.class);
         newPayService.wechatSplitBill(traceNo, mchId, amount);
         newPayService.wechatSplitBill(traceNo, mchId, amount);
 
 
         userMoneyDetails.setRemark(traceNo);
         userMoneyDetails.setRemark(traceNo);

+ 9 - 0
src/main/java/com/sqx/modules/app/service/impl/UserServiceImpl.java

@@ -812,6 +812,15 @@ public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements
         return this.getOne(queryWrapper);
         return this.getOne(queryWrapper);
     }
     }
 
 
+    @Override
+    public void updateUserToVip(Long userId, String futureTimeWithDays) {
+        UserEntity user = new UserEntity();
+        user.setUserId(userId);
+        user.setIsVip(1);
+        user.setVipExpirationTime(futureTimeWithDays);
+        this.updateById(user);
+    }
+
     private Result sendMsgAlibaba(String phone, String state, int code) {
     private Result sendMsgAlibaba(String phone, String state, int code) {
         //阿里云短信accessKeyId
         //阿里云短信accessKeyId
         CommonInfo three = commonInfoService.findOne(93);
         CommonInfo three = commonInfoService.findOne(93);

+ 9 - 0
src/main/java/com/sqx/modules/coupon/service/TbCouponUserService.java

@@ -18,4 +18,13 @@ public interface TbCouponUserService extends IService<TbCouponUser> {
 
 
     Result selectCouponByUserId(Integer page, Integer limit, Long userId, Integer status, String phone,String shopName,Long shopId,Integer shopFlag);
     Result selectCouponByUserId(Integer page, Integer limit, Long userId, Integer status, String phone,String shopName,Long shopId,Integer shopFlag);
 
 
+    /**
+     * 会员购买成功后添加优惠券
+     *
+     * @param userId            用户id
+     * @param money             优惠券金额
+     * @param expirationDays 有效天数
+     * @param expirationTime    优惠券过期时间
+     */
+    void addAfterVipBuySuccess(Long userId, BigDecimal money, String expirationDays, String expirationTime);
 }
 }

+ 18 - 0
src/main/java/com/sqx/modules/coupon/service/impl/TbTbCouponUserServiceImpl.java

@@ -15,6 +15,7 @@ import com.sqx.modules.integral.dao.UserIntegralDao;
 import com.sqx.modules.integral.dao.UserIntegralDetailsDao;
 import com.sqx.modules.integral.dao.UserIntegralDetailsDao;
 import com.sqx.modules.integral.entity.UserIntegral;
 import com.sqx.modules.integral.entity.UserIntegral;
 import com.sqx.modules.integral.entity.UserIntegralDetails;
 import com.sqx.modules.integral.entity.UserIntegralDetails;
+import com.sqx.modules.utils.VipExpirationUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
@@ -128,4 +129,21 @@ public class TbTbCouponUserServiceImpl extends ServiceImpl<TbCouponUserDao, TbCo
         PageUtils pageUtils = new PageUtils(tbCouponUserDao.selectCouponByUserId(pages, userId, status, phone,shopName,shopId,shopFalg));
         PageUtils pageUtils = new PageUtils(tbCouponUserDao.selectCouponByUserId(pages, userId, status, phone,shopName,shopId,shopFalg));
         return Result.success().put("data", pageUtils);
         return Result.success().put("data", pageUtils);
     }
     }
+
+    @Override
+    public void addAfterVipBuySuccess(Long userId, BigDecimal money, String expirationDays, String expirationTime) {
+        TbCouponUser tbCouponUser = new TbCouponUser();
+        tbCouponUser.setUserId(userId);
+        tbCouponUser.setCouponName("会员专属优惠券");
+        tbCouponUser.setCouponPicture("图片");
+        tbCouponUser.setCreateTime(VipExpirationUtil.formatCurrentTime());
+        tbCouponUser.setExpirationTime(expirationTime);
+        tbCouponUser.setMinMoney(BigDecimal.valueOf(0));
+        tbCouponUser.setGoodsType("0");
+        tbCouponUser.setMoney(money);
+        tbCouponUser.setStatus(0);
+        tbCouponUser.setEndTime(expirationDays);
+        tbCouponUser.setShopId(0L);
+        tbCouponUserDao.insert(tbCouponUser);
+    }
 }
 }

+ 5 - 11
src/main/java/com/sqx/modules/datacentre/controller/DataCentreController.java

@@ -15,7 +15,11 @@ import com.sqx.modules.order.service.AppOrderService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
 
 import javax.validation.Valid;
 import javax.validation.Valid;
 import java.math.BigDecimal;
 import java.math.BigDecimal;
@@ -251,13 +255,6 @@ public class DataCentreController {
         return dataCentreService.selectCashDeposit(phone, type, page, limit, userId);
         return dataCentreService.selectCashDeposit(phone, type, page, limit, userId);
     }
     }
 
 
-   /* @ApiOperation("用户中心 用户列表")
-    @GetMapping(value = "findAllUser")
-    public Result findAllUser(Integer page, Integer limit, String phone, Integer userType, String platform, String nickName, String invitationCode){
-
-        return dataCentreService.findAllUser(page, limit, phone, userType, platform, nickName, invitationCode);
-    }*/
-
     @ApiOperation("查看反馈列表")
     @ApiOperation("查看反馈列表")
     @GetMapping(value = "selectFeedbackList")
     @GetMapping(value = "selectFeedbackList")
     public Result selectFeedbackList(Integer page, Integer limit, Integer feedbackType) {
     public Result selectFeedbackList(Integer page, Integer limit, Integer feedbackType) {
@@ -265,12 +262,9 @@ public class DataCentreController {
         return dataCentreService.selectFeedbackList(page, limit, feedbackType);
         return dataCentreService.selectFeedbackList(page, limit, feedbackType);
     }
     }
 
 
-    /*==========================================================*/
-
     @ApiOperation("管理端赠送用户会员")
     @ApiOperation("管理端赠送用户会员")
     @PostMapping(value = "presenterVip")
     @PostMapping(value = "presenterVip")
     public Result presenterVip(Long userId) {
     public Result presenterVip(Long userId) {
-
         return dataCentreService.presenterVip(userId);
         return dataCentreService.presenterVip(userId);
     }
     }
 
 

+ 28 - 107
src/main/java/com/sqx/modules/datacentre/service/impl/DataCentreServiceImpl.java

@@ -1,7 +1,5 @@
 package com.sqx.modules.datacentre.service.impl;
 package com.sqx.modules.datacentre.service.impl;
 
 
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.sqx.common.utils.DateUtils;
 import com.sqx.common.utils.DateUtils;
@@ -10,12 +8,10 @@ import com.sqx.common.utils.Result;
 import com.sqx.modules.app.dao.UserDao;
 import com.sqx.modules.app.dao.UserDao;
 import com.sqx.modules.app.entity.UserEntity;
 import com.sqx.modules.app.entity.UserEntity;
 import com.sqx.modules.app.entity.UserMoneyDetails;
 import com.sqx.modules.app.entity.UserMoneyDetails;
-import com.sqx.modules.app.service.UserMoneyDetailsService;
 import com.sqx.modules.app.service.UserService;
 import com.sqx.modules.app.service.UserService;
 import com.sqx.modules.common.entity.CommonInfo;
 import com.sqx.modules.common.entity.CommonInfo;
 import com.sqx.modules.common.service.CommonInfoService;
 import com.sqx.modules.common.service.CommonInfoService;
-import com.sqx.modules.coupon.dao.TbCouponUserDao;
-import com.sqx.modules.coupon.entity.TbCouponUser;
+import com.sqx.modules.coupon.service.TbCouponUserService;
 import com.sqx.modules.datacentre.dao.DataCentreDao;
 import com.sqx.modules.datacentre.dao.DataCentreDao;
 import com.sqx.modules.datacentre.query.DataCenterQuery;
 import com.sqx.modules.datacentre.query.DataCenterQuery;
 import com.sqx.modules.datacentre.query.RankListQuery;
 import com.sqx.modules.datacentre.query.RankListQuery;
@@ -25,48 +21,34 @@ import com.sqx.modules.errand.entity.Feedback;
 import com.sqx.modules.errand.entity.TbIndent;
 import com.sqx.modules.errand.entity.TbIndent;
 import com.sqx.modules.order.dao.AppOrderDao;
 import com.sqx.modules.order.dao.AppOrderDao;
 import com.sqx.modules.order.entity.TbOrder;
 import com.sqx.modules.order.entity.TbOrder;
-import com.sqx.modules.pay.controller.app.AliPayController;
-import com.sqx.modules.pay.controller.query.WalletDetailQuery;
-import com.sqx.modules.pay.dao.PayDetailsDao;
 import com.sqx.modules.pay.entity.CashOut;
 import com.sqx.modules.pay.entity.CashOut;
 import com.sqx.modules.pay.entity.PayDetails;
 import com.sqx.modules.pay.entity.PayDetails;
-import com.sqx.modules.pay.service.WxErrRiderService;
-import com.sqx.modules.pay.vo.WalletDetailVO;
+import com.sqx.modules.utils.VipExpirationUtil;
 import com.sqx.modules.utils.excel.ExcelData;
 import com.sqx.modules.utils.excel.ExcelData;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
 
 
 import java.math.BigDecimal;
 import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
 import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
 
 
 @Service
 @Service
 @Slf4j
 @Slf4j
+@RequiredArgsConstructor
 public class DataCentreServiceImpl implements DataCentreService {
 public class DataCentreServiceImpl implements DataCentreService {
 
 
-    @Autowired
-    private DataCentreDao dataCentreDao;
-    @Autowired
-    private UserDao userDao;
-    @Autowired
-    private AppOrderDao appOrderDao;
-    @Autowired
-    private WxErrRiderService wxErrRiderService;
-    @Autowired
-    private AliPayController aliPayController;
-    @Autowired
-    private UserService userService;
-    @Autowired
-    private PayDetailsDao payDetailsDao;
-    @Autowired
-    private UserMoneyDetailsService userMoneyDetailsService;
-    @Autowired
-    private CommonInfoService commonInfoService;
-    @Autowired
-    private TbCouponUserDao tbCouponUserDao;
+    private final DataCentreDao dataCentreDao;
+    private final UserDao userDao;
+    private final AppOrderDao appOrderDao;
+    private final UserService userService;
+    private final CommonInfoService commonInfoService;
+    private final TbCouponUserService tbCouponUserService;
 
 
     @Override
     @Override
     public Result dataCentre() {
     public Result dataCentre() {
@@ -181,44 +163,6 @@ public class DataCentreServiceImpl implements DataCentreService {
     @Transactional
     @Transactional
     @Override
     @Override
     public Result checkCertification(Long userId, String checkCertification, String checkCertificationMessage) {
     public Result checkCertification(Long userId, String checkCertification, String checkCertificationMessage) {
-        if("2".equals(checkCertification)){
-            UserEntity userEntity = userService.selectUserById(userId);
-            PayDetails payDetails = payDetailsDao.selectByOrderId(userEntity.getCheckNumber());
-            if(payDetails.getType().equals(4)){
-                String code=AliPayController.alipayRefund(payDetails);
-                if(StringUtils.isNotBlank(code)){
-                    log.error(code);
-                    JSONObject jsonObject = JSON.parseObject(code);
-                    JSONObject alipay_trade_refund_response = jsonObject.getJSONObject("alipay_trade_refund_response");
-                    String code1 = alipay_trade_refund_response.getString("code");
-                    if(!"10000".equals(code1)){
-                        return Result.error("退款失败!"+alipay_trade_refund_response.getString("sub_msg"));
-                    }
-                }else{
-                    return Result.error("退款失败!");
-                }
-            }else{
-                boolean flag= wxErrRiderService.wxRefund(payDetails);
-                if(!flag){
-                    return Result.error("退款失败,请联系客服!");
-                }
-            }
-            UserEntity userEntity1 = new UserEntity();
-            userEntity1.setUserId(userId);
-            userEntity1.setCheckCertification("2");
-            userEntity1.setCashDeposit(BigDecimal.valueOf(0));
-            userDao.updateById(userEntity1);
-            //退保证金的记录
-            UserMoneyDetails userMoneyDetails=new UserMoneyDetails();
-            userMoneyDetails.setUserId(userId);
-            userMoneyDetails.setTitle("退还保证金");
-            userMoneyDetails.setContent("实名认证审核未通过,保证金:"+payDetails.getMoney()+"元已退还至原支付途径");
-            userMoneyDetails.setType(2);
-            userMoneyDetails.setClassify(1);
-            userMoneyDetails.setMoney(BigDecimal.valueOf(payDetails.getMoney()));
-            userMoneyDetails.setCreateTime(new SimpleDateFormat("yyyy-MM-dd :HH:mm:ss").format(new Date()));
-            userMoneyDetailsService.save(userMoneyDetails);
-        }
         dataCentreDao.checkCertification(userId, checkCertification, checkCertificationMessage);
         dataCentreDao.checkCertification(userId, checkCertification, checkCertificationMessage);
         return Result.success();
         return Result.success();
     }
     }
@@ -383,46 +327,25 @@ public class DataCentreServiceImpl implements DataCentreService {
     @Transactional
     @Transactional
     @Override
     @Override
     public Result presenterVip(Long userId) {
     public Result presenterVip(Long userId) {
-        UserEntity userEntity1 = userDao.selectById(userId);
-        if(userEntity1.getIsVip()==1){
+        UserEntity user = userDao.selectById(userId);
+        if(user.getIsVip() ==1 && VipExpirationUtil.isVipValid(user.getVipExpirationTime())){
             return Result.error("该用户已经是会员,不能重复添加!");
             return Result.error("该用户已经是会员,不能重复添加!");
         }
         }
-        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        /*Calendar calendar1 = java.util.Calendar.getInstance();
-        Calendar calendar2 = java.util.Calendar.getInstance();
-        try {
-            calendar1.setTime(dateFormat.parse(userEntity1.getVipExpirationTime()));
-            calendar2.setTime(dateFormat.parse(dateFormat.format(new Date())));
-        } catch (java.text.ParseException e) {
-            System.out.println("日期格式不正确");
-        }
-        if(calendar1.compareTo(calendar2)>0){
-            return Result.error("用户已经是会员,请勿重复操作!");
-        }*/
+
+        // 读取配置
         CommonInfo one = commonInfoService.findOne(314);
         CommonInfo one = commonInfoService.findOne(314);
         CommonInfo one1 = commonInfoService.findOne(315);
         CommonInfo one1 = commonInfoService.findOne(315);
         CommonInfo one2 = commonInfoService.findOne(316);
         CommonInfo one2 = commonInfoService.findOne(316);
-        UserEntity userEntity = new UserEntity();
-        userEntity.setUserId(userId);
-        userEntity.setIsVip(1);
-        Calendar calendar = Calendar.getInstance();
-        calendar.add(Calendar.DATE, +Integer.valueOf(one.getValue()));    //得到前一个月
-        userEntity.setVipExpirationTime(dateFormat.format(calendar.getTime()));
-        userDao.updateById(userEntity);
+
+        // 会员失效时间
+        String expirationTime = VipExpirationUtil.getFutureTimeWithDays(Integer.valueOf(one.getValue()));
+
+        // 更新用户为会员
+        userService.updateUserToVip(userId, expirationTime);
+
+        // 新增会员专属优惠券
         for(int i = 0;i<Integer.valueOf(one1.getValue());i++){
         for(int i = 0;i<Integer.valueOf(one1.getValue());i++){
-            TbCouponUser tbCouponUser = new TbCouponUser();
-            tbCouponUser.setUserId(userId);
-            tbCouponUser.setCouponName("会员专属优惠券");
-            tbCouponUser.setCouponPicture("图片");
-            tbCouponUser.setCreateTime(dateFormat.format(new Date()));
-            tbCouponUser.setExpirationTime(dateFormat.format(calendar.getTime()));
-            tbCouponUser.setMinMoney(BigDecimal.valueOf(0));
-            tbCouponUser.setGoodsType("0");
-            tbCouponUser.setMoney(new BigDecimal(one2.getValue()));
-            tbCouponUser.setStatus(0);
-            tbCouponUser.setEndTime(one.getValue());
-            tbCouponUser.setShopId(0L);
-            tbCouponUserDao.insert(tbCouponUser);
+            tbCouponUserService.addAfterVipBuySuccess(userId, new BigDecimal(one2.getValue()), one.getValue(), expirationTime);
         }
         }
         return Result.success();
         return Result.success();
     }
     }
@@ -461,6 +384,4 @@ public class DataCentreServiceImpl implements DataCentreService {
         userDao.updateById(userEntity);
         userDao.updateById(userEntity);
         return Result.success();
         return Result.success();
     }
     }
-
-
 }
 }

+ 17 - 12
src/main/java/com/sqx/modules/errand/service/impl/TbIndentServiceImpl.java

@@ -1558,8 +1558,9 @@ public class TbIndentServiceImpl extends ServiceImpl<TbIndentDao, TbIndent> impl
      */
      */
     private void orderHandTakeoutOrder(TbIndent indentOrder, Long userId, OrderRiderDeliveryDTO deliveryDTO) {
     private void orderHandTakeoutOrder(TbIndent indentOrder, Long userId, OrderRiderDeliveryDTO deliveryDTO) {
         Long smsTemplateId = deliveryDTO.getSmsTemplateId();
         Long smsTemplateId = deliveryDTO.getSmsTemplateId();
+        // 短信模板为空,不发送短信
         if (ObjectUtil.isNull(smsTemplateId)) {
         if (ObjectUtil.isNull(smsTemplateId)) {
-            throw new SqxException("短信模板id不能为空");
+            return;
         }
         }
 
 
         MyGlobalThreadPool.execute(() -> {
         MyGlobalThreadPool.execute(() -> {
@@ -1856,13 +1857,23 @@ public class TbIndentServiceImpl extends ServiceImpl<TbIndentDao, TbIndent> impl
      */
      */
     private void handTakeoutOrder(TbIndent indentOrder, Long userId, RiderDeliveryDTO deliveryDTO) {
     private void handTakeoutOrder(TbIndent indentOrder, Long userId, RiderDeliveryDTO deliveryDTO) {
         // 6表示跑腿订单处于已完成状态
         // 6表示跑腿订单处于已完成状态
-        //锁内用锁外数据进行判断会拿等待锁前的数据判断
+        // 锁内用锁外数据进行判断会拿等待锁前的数据判断
         if ("6".equals(indentOrder.getIndentState())) {
         if ("6".equals(indentOrder.getIndentState())) {
             return;
             return;
         }
         }
+
+        // 订单新增送达图片
+        String imgStr = deliveryDTO.getImgs();
+        if (StrUtil.isNotBlank(imgStr)) {
+            TbOrder tbOrder = appOrderService.getById(indentOrder.getOrderId());
+            tbOrder.setDeliveryImgs(imgStr);
+            appOrderService.updateById(tbOrder);
+        }
+
+        // 短信模板为空,不发送短信
         Long smsTemplateId = deliveryDTO.getSmsTemplateId();
         Long smsTemplateId = deliveryDTO.getSmsTemplateId();
         if (ObjectUtil.isNull(smsTemplateId)) {
         if (ObjectUtil.isNull(smsTemplateId)) {
-            throw new SqxException("短信模板id不能为空");
+            return;
         }
         }
 
 
         // 收货人手机
         // 收货人手机
@@ -1880,15 +1891,9 @@ public class TbIndentServiceImpl extends ServiceImpl<TbIndentDao, TbIndent> impl
             return;
             return;
         }
         }
 
 
-        // 订单新增送达图片
-        String imgs = deliveryDTO.getImgs();
-        if (StrUtil.isNotBlank(imgs)) {
-            TbOrder tbOrder = appOrderService.getById(indentOrder.getOrderId());
-            tbOrder.setDeliveryImgs(imgs);
-            appOrderService.updateById(tbOrder);
-        }
         TbIndentSmsSendLog tbIndentSmsSendLog=smsSendLogService.getSendSuccessByOrderId(indentOrder.getIndentId());
         TbIndentSmsSendLog tbIndentSmsSendLog=smsSendLogService.getSendSuccessByOrderId(indentOrder.getIndentId());
-//        有发送成功记录则不再发送
+
+        // 有发送成功记录则不再发送
         if(tbIndentSmsSendLog!=null){
         if(tbIndentSmsSendLog!=null){
             log.error("外卖跑腿订单【{}】短信已发送成功,短信id【{}】", deliveryDTO.getIndentNumber(),tbIndentSmsSendLog.getId());
             log.error("外卖跑腿订单【{}】短信已发送成功,短信id【{}】", deliveryDTO.getIndentNumber(),tbIndentSmsSendLog.getId());
             return;
             return;
@@ -2290,7 +2295,7 @@ public class TbIndentServiceImpl extends ServiceImpl<TbIndentDao, TbIndent> impl
                 goodsShopRelevancy1.setSales(goodsShopRelevancy.getSales() - goodsNum);//加销量
                 goodsShopRelevancy1.setSales(goodsShopRelevancy.getSales() - goodsNum);//加销量
                 goodsShopRelevancy1.setInventory(goodsShopRelevancy.getInventory() + goodsNum);//减库存
                 goodsShopRelevancy1.setInventory(goodsShopRelevancy.getInventory() + goodsNum);//减库存
                 goodsShopRelevancyDao.updateById(goodsShopRelevancy1);
                 goodsShopRelevancyDao.updateById(goodsShopRelevancy1);
-                goodsShopDao.updateShopSales(2, goodsNum, goodsShopRelevancy.getShopId());
+                // goodsShopDao.updateShopSales(2, goodsNum, goodsShopRelevancy.getShopId());
             }
             }
         }
         }
 
 

+ 41 - 9
src/main/java/com/sqx/modules/exportExecl/controller/ExportExeclController.java

@@ -1,21 +1,24 @@
 package com.sqx.modules.exportExecl.controller;
 package com.sqx.modules.exportExecl.controller;
 
 
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.jcraft.jsch.SftpException;
 import com.jcraft.jsch.SftpException;
 import com.sqx.common.utils.PageUtils;
 import com.sqx.common.utils.PageUtils;
 import com.sqx.common.utils.Result;
 import com.sqx.common.utils.Result;
 import com.sqx.common.utils.SftpUtil;
 import com.sqx.common.utils.SftpUtil;
+import com.sqx.common.utils.ShiroUtils;
 import com.sqx.modules.address.query.InsideAddressQuery;
 import com.sqx.modules.address.query.InsideAddressQuery;
 import com.sqx.modules.common.service.CommonInfoService;
 import com.sqx.modules.common.service.CommonInfoService;
 import com.sqx.modules.datacentre.query.RankListQuery;
 import com.sqx.modules.datacentre.query.RankListQuery;
 import com.sqx.modules.datacentre.query.ShopCenterQuery;
 import com.sqx.modules.datacentre.query.ShopCenterQuery;
 import com.sqx.modules.exportExecl.dto.AccountEntry;
 import com.sqx.modules.exportExecl.dto.AccountEntry;
-import com.sqx.modules.exportExecl.mapper.ExportJobMapper;
 import com.sqx.modules.exportExecl.model.ExportJob;
 import com.sqx.modules.exportExecl.model.ExportJob;
 import com.sqx.modules.exportExecl.service.ExportJobService;
 import com.sqx.modules.exportExecl.service.ExportJobService;
+import com.sqx.modules.member.query.SpecialFavorStudentQuery;
+import com.sqx.modules.member.query.VipPromoCodeQuery;
+import com.sqx.modules.member.query.VipPromoRecordQuery;
 import com.sqx.modules.order.dao.AppOrderDao;
 import com.sqx.modules.order.dao.AppOrderDao;
 import com.sqx.modules.order.dto.OrderQueryDto;
 import com.sqx.modules.order.dto.OrderQueryDto;
 import com.sqx.modules.pay.controller.query.CashOutQueryDTO;
 import com.sqx.modules.pay.controller.query.CashOutQueryDTO;
@@ -27,21 +30,15 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
 import lombok.RequiredArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.poi.util.IOUtils;
-import org.jetbrains.annotations.NotNull;
 import org.springframework.util.StringUtils;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestAttribute;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.bind.annotation.RestController;
 
 
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponse;
-import javax.validation.Valid;
-import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.URLEncoder;
 import java.net.URLEncoder;
-import java.nio.file.Files;
-import java.nio.file.Paths;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatter;
 import java.util.Date;
 import java.util.Date;
@@ -319,4 +316,39 @@ public class ExportExeclController {
         }
         }
     }
     }
 
 
+    @GetMapping("exportSpecialFavorStudent")
+    @ApiOperation("导出特殊照顾学生列表")
+    public Result exportSpecialFavorStudent(SpecialFavorStudentQuery queryDTO) {
+        Long userId = ShiroUtils.getUserId();
+        ExportJob exportJob = buildExportJob("特殊照顾学生列表.xlsx","specialFavorStudent", userId.toString(),
+                queryDTO.buildQueryConditionString(),
+                JSONUtil.toJsonStr(queryDTO));
+        exportJobService.save(exportJob);
+
+        return Result.success("特殊照顾学生列表导出成功");
+    }
+
+    @GetMapping("exportVipPromoCode")
+    @ApiOperation("导出会员推广码记录列表")
+    public Result exportVipPromoCode(VipPromoCodeQuery queryDTO) {
+        Long userId = ShiroUtils.getUserId();
+        ExportJob exportJob = buildExportJob("会员码广码记录列表.xlsx","vipPromoCode", userId.toString(),
+                queryDTO.buildQueryConditionString(),
+                JSONUtil.toJsonStr(queryDTO));
+        exportJobService.save(exportJob);
+
+        return Result.success("会员码广码记录列表导出成功");
+    }
+
+    @GetMapping("exportVipPromoRecord")
+    @ApiOperation("导出会员充值记录列表")
+    public Result exportVipPromoRecord(VipPromoRecordQuery queryDTO) {
+        Long userId = ShiroUtils.getUserId();
+        ExportJob exportJob = buildExportJob("会员充值记录列表.xlsx","vipPromoRecord", userId.toString(),
+                queryDTO.buildQueryConditionString(),
+                JSONUtil.toJsonStr(queryDTO));
+        exportJobService.save(exportJob);
+
+        return Result.success("会员充值记录列表导出成功");
+    }
 }
 }

+ 2 - 2
src/main/java/com/sqx/modules/goods/controller/GoodsController.java

@@ -103,9 +103,9 @@ public class GoodsController extends AbstractController {
 
 
     @ApiOperation("查看所有商铺")
     @ApiOperation("查看所有商铺")
     @GetMapping(value = "selectAllShop")
     @GetMapping(value = "selectAllShop")
-    public Result selectAllShop(Integer page, Integer limit, String shopName,String region,Integer isActivity){
+    public Result selectAllShop(Integer page, Integer limit, String shopName,String region,Integer isActivity, String vipPromotion){
 
 
-        return goodsService.selectAllShop(page, limit, shopName,region,isActivity);
+        return goodsService.selectAllShop(page, limit, shopName,region,isActivity,vipPromotion);
     }
     }
 
 
     @ApiOperation("查看商品评价详情")
     @ApiOperation("查看商品评价详情")

+ 6 - 2
src/main/java/com/sqx/modules/goods/controller/GoodsShopController.java

@@ -136,7 +136,11 @@ public class GoodsShopController {
         return Result.success();
         return Result.success();
     }
     }
 
 
-
-
+    @ApiOperation(value = "修改商品是否参与vip优惠", notes = "vipPromotion 是否参与vip优惠活动,0否1是")
+    @PutMapping("/vip-promotion/{shopId}/{vipPromotion}")
+    public Result updateVipPromotion(@PathVariable Long shopId, @PathVariable String vipPromotion){
+        goodsShopService.updateVipPromotion(shopId, vipPromotion);
+        return Result.success();
+    }
 
 
 }
 }

+ 5 - 18
src/main/java/com/sqx/modules/goods/controller/app/AppGoodsController.java

@@ -2,7 +2,6 @@ package com.sqx.modules.goods.controller.app;
 
 
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.StrUtil;
 import com.sqx.common.utils.Result;
 import com.sqx.common.utils.Result;
-import com.sqx.modules.app.annotation.Login;
 import com.sqx.modules.goods.dto.ShopQueryDTO;
 import com.sqx.modules.goods.dto.ShopQueryDTO;
 import com.sqx.modules.goods.entity.GoodsShop;
 import com.sqx.modules.goods.entity.GoodsShop;
 import com.sqx.modules.goods.service.GoodsService;
 import com.sqx.modules.goods.service.GoodsService;
@@ -11,7 +10,11 @@ import com.sqx.modules.shop.service.SearchHistoryService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
 
 @Api(tags={"用户端-商品"})
 @Api(tags={"用户端-商品"})
 @RestController
 @RestController
@@ -46,22 +49,6 @@ public class AppGoodsController {
         return goodsService.selectGoodsById(goodsId);
         return goodsService.selectGoodsById(goodsId);
     }
     }
 
 
-    /*@Login
-    @ApiOperation("获取该商品规格名")
-    @GetMapping(value = "selectSkuByGoodsId")
-    public Result selectSkuByGoodsId(Long goodsId){
-        //goodsService.selectSkuByGoodsId(goodsId)
-        return null;
-    }
-
-    @Login
-    @ApiOperation("获取该商品详细规格")
-    @GetMapping(value = "selectAttrByGoodsId")
-    public Result selectAttrByGoodsId(Long goodsId){
-        //goodsService.selectAttrByGoodsId(goodsId);
-        return null;
-    }*/
-
     @ApiOperation("条件筛选店铺")
     @ApiOperation("条件筛选店铺")
     @GetMapping(value = "selectShop")
     @GetMapping(value = "selectShop")
     public Result selectShop(ShopQueryDTO queryDTO){
     public Result selectShop(ShopQueryDTO queryDTO){

+ 2 - 2
src/main/java/com/sqx/modules/goods/dao/GoodsShopDao.java

@@ -17,7 +17,7 @@ import java.util.List;
 @Mapper
 @Mapper
 public interface GoodsShopDao extends BaseMapper<GoodsShop> {
 public interface GoodsShopDao extends BaseMapper<GoodsShop> {
 
 
-    IPage<GoodsShop> selectAllShop(@Param("pages") Page<GoodsShop> pages, @Param("shopName") String shopName, @Param("region") String region, @Param("isActivity") Integer isActivity);
+    IPage<GoodsShop> selectAllShop(@Param("pages") Page<GoodsShop> pages, @Param("shopName") String shopName, @Param("region") String region, @Param("isActivity") Integer isActivity, @Param("vipPromotion") String vipPromotion);
 
 
     IPage<GoodsShop> selectAllShopByAdmin(Page<GoodsShop> pages,@Param("shopName") String shopName,@Param("userId") Long userId);
     IPage<GoodsShop> selectAllShopByAdmin(Page<GoodsShop> pages,@Param("shopName") String shopName,@Param("userId") Long userId);
 
 
@@ -45,7 +45,7 @@ public interface GoodsShopDao extends BaseMapper<GoodsShop> {
 
 
     IPage<GoodsShop> selectSearch(Page<GoodsShop> pages, String impotr, Double lng, Double lat, String city);
     IPage<GoodsShop> selectSearch(Page<GoodsShop> pages, String impotr, Double lng, Double lat, String city);
 
 
-    IPage<GoodsShop> selectShop(Page<GoodsShop> pages, Integer screen, Integer shopTypeId, Double lng, Double lat, String city, String impotr,Long activityId);
+    IPage<GoodsShop> selectShop(@Param("pages") Page<GoodsShop> pages, @Param("screen") Integer screen, @Param("shopTypeId") Integer shopTypeId, @Param("lng") Double lng, @Param("lat") Double lat, @Param("city") String city, @Param("impotr") String impotr, @Param("activityId") Long activityId, @Param("vipPromotion") String vipPromotion);
 
 
     IPage<Evaluate> selectEvaluate(Page<Evaluate> pages, Long shopId, String goodsId, Integer grade);
     IPage<Evaluate> selectEvaluate(Page<Evaluate> pages, Long shopId, String goodsId, Integer grade);
 
 

+ 6 - 0
src/main/java/com/sqx/modules/goods/dto/ShopQueryDTO.java

@@ -1,6 +1,8 @@
 package com.sqx.modules.goods.dto;
 package com.sqx.modules.goods.dto;
 
 
 import com.sqx.common.query.PageQuery;
 import com.sqx.common.query.PageQuery;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.Data;
 
 
 /**
 /**
@@ -10,6 +12,7 @@ import lombok.Data;
  * @date : 2024-08-28 13:45
  * @date : 2024-08-28 13:45
  */
  */
 @Data
 @Data
+@ApiModel("app店铺查询参数")
 public class ShopQueryDTO extends PageQuery {
 public class ShopQueryDTO extends PageQuery {
     private Long userId;
     private Long userId;
     /**
     /**
@@ -27,4 +30,7 @@ public class ShopQueryDTO extends PageQuery {
 
 
     private String impotr;
     private String impotr;
     private Long activityId;
     private Long activityId;
+
+    @ApiModelProperty("是否参与vip优惠 0否 1是")
+    private String vipPromotion;
 }
 }

+ 17 - 15
src/main/java/com/sqx/modules/goods/entity/GoodsShop.java

@@ -204,11 +204,20 @@ public class GoodsShop implements Serializable {
     @ApiModelProperty("商家佣金比例")
     @ApiModelProperty("商家佣金比例")
     private BigDecimal shopRate;
     private BigDecimal shopRate;
 
 
-   /* @ApiModelProperty("商户缴纳保证金订单号")
-    private Integer checkNumber;*/
-
+    @ApiModelProperty("排序")
     private Integer sort;
     private Integer sort;
 
 
+    @ApiModelProperty("是否供应商 0是  1不是")
+    private Integer isSupplier;
+
+    @ApiModelProperty("消息配置  0开启  1关闭")
+    private Integer messageConfiguration;
+
+    @ApiModelProperty("是否隐藏 0不隐藏 1是隐藏")
+    private Integer isConceal;
+
+    @ApiModelProperty("是否参与vip优惠 0否 1是")
+    private String vipPromotion;
 
 
     @ApiModelProperty("距离")
     @ApiModelProperty("距离")
     @TableField(exist = false)
     @TableField(exist = false)
@@ -218,7 +227,6 @@ public class GoodsShop implements Serializable {
     @TableField(exist = false)
     @TableField(exist = false)
     private Double errandTime;
     private Double errandTime;
 
 
-
     @ApiModelProperty("商铺类型名称")
     @ApiModelProperty("商铺类型名称")
     @TableField(exist = false)
     @TableField(exist = false)
     private String shopTypeName;
     private String shopTypeName;
@@ -257,16 +265,10 @@ public class GoodsShop implements Serializable {
     @ApiModelProperty("参与活动列表")
     @ApiModelProperty("参与活动列表")
     private List<ShopActivityVO>  shopActivityList;
     private List<ShopActivityVO>  shopActivityList;
 
 
+    @TableField(exist = false)
+    @ApiModelProperty("会员优惠描述")
+    private String vipPromotionDesc;
+
     public GoodsShop() {
     public GoodsShop() {
     }
     }
-
-
-    @ApiModelProperty("是否供应商 0是  1不是")
-    private Integer isSupplier;
-
-    @ApiModelProperty("消息配置  0开启  1关闭")
-    private Integer messageConfiguration;
-
-    @ApiModelProperty("是否隐藏 0不隐藏 1是隐藏")
-    private Integer isConceal;
-}
+}

+ 1 - 2
src/main/java/com/sqx/modules/goods/service/GoodsService.java

@@ -1,6 +1,5 @@
 package com.sqx.modules.goods.service;
 package com.sqx.modules.goods.service;
 
 
-import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.sqx.common.utils.Result;
 import com.sqx.common.utils.Result;
 import com.sqx.modules.goods.dto.ShopQueryDTO;
 import com.sqx.modules.goods.dto.ShopQueryDTO;
@@ -30,7 +29,7 @@ public interface GoodsService extends IService<Goods> {
 
 
     Result selectShortShop(double lng, double lat, String shopName, Integer page, Integer limit, Long shopId);
     Result selectShortShop(double lng, double lat, String shopName, Integer page, Integer limit, Long shopId);
 
 
-    Result selectAllShop(Integer page, Integer limit, String shopName,String region,Integer isActivity);
+    Result selectAllShop(Integer page, Integer limit, String shopName, String region, Integer isActivity, String vipPromotion);
 
 
     Result selectAdminGoodsList(Integer page, Integer limit, Integer classifyId, String goodsName, Integer status, Long shopId, String shopName);
     Result selectAdminGoodsList(Integer page, Integer limit, Integer classifyId, String goodsName, Integer status, Long shopId, String shopName);
 
 

+ 14 - 0
src/main/java/com/sqx/modules/goods/service/GoodsShopService.java

@@ -8,6 +8,7 @@ import com.sqx.modules.goods.entity.GoodsShopRelevancy;
 import com.sqx.modules.goods.vo.GoodsShopVo;
 import com.sqx.modules.goods.vo.GoodsShopVo;
 
 
 import java.util.List;
 import java.util.List;
+import java.util.Map;
 
 
 public interface GoodsShopService extends IService<GoodsShop> {
 public interface GoodsShopService extends IService<GoodsShop> {
 
 
@@ -63,4 +64,17 @@ public interface GoodsShopService extends IService<GoodsShop> {
      * @return 店铺列表
      * @return 店铺列表
      */
      */
     List<GoodsShop> getAllShops();
     List<GoodsShop> getAllShops();
+
+    /**
+     * 修改商品是否参与vip优惠
+     * @param shopId 店铺id
+     * @param vipPromotion 是否参与vip优惠活动,0否1是
+     */
+    void updateVipPromotion(Long shopId, String vipPromotion);
+
+    /**
+     * 更新店铺销售数量
+     * @param shopSalesMap 店铺销售数量映射表,key为店铺id,value为销售数量
+     */
+    void updateShopSales(Map<Long, Integer> shopSalesMap);
 }
 }

+ 22 - 7
src/main/java/com/sqx/modules/goods/service/impl/GoodsServiceImpl.java

@@ -452,9 +452,9 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsDao, Goods> implements Go
     }
     }
 
 
     @Override
     @Override
-    public Result selectAllShop(Integer page, Integer limit, String shopName, String region, Integer isActivity) {
+    public Result selectAllShop(Integer page, Integer limit, String shopName, String region, Integer isActivity, String vipPromotion) {
         Page<GoodsShop> pages = new Page<>(page, limit);
         Page<GoodsShop> pages = new Page<>(page, limit);
-        PageUtils pageUtils = new PageUtils(goodsShopDao.selectAllShop(pages, shopName, region, isActivity));
+        PageUtils pageUtils = new PageUtils(goodsShopDao.selectAllShop(pages, shopName, region, isActivity,vipPromotion));
         return Result.success().put("data", pageUtils);
         return Result.success().put("data", pageUtils);
     }
     }
 
 
@@ -534,12 +534,10 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsDao, Goods> implements Go
             city = getCity(lat, lng);
             city = getCity(lat, lng);
         }
         }
 
 
-        IPage<GoodsShop> goodsShopIPage = goodsShopDao.selectShop(pages, queryDTO.getScreen(), queryDTO.getShopTypeId(), lng, lat, city, queryDTO.getImpotr(), queryDTO.getActivityId());
+        IPage<GoodsShop> goodsShopIPage = goodsShopDao.selectShop(pages, queryDTO.getScreen(), queryDTO.getShopTypeId(), lng, lat, city, queryDTO.getImpotr(), queryDTO.getActivityId(), queryDTO.getVipPromotion());
         List<GoodsShop> records = goodsShopIPage.getRecords();
         List<GoodsShop> records = goodsShopIPage.getRecords();
 
 
         if (CollUtil.isNotEmpty(records)) {
         if (CollUtil.isNotEmpty(records)) {
-            CommonInfo one1 = commonInfoService.findOne(292);
-            CommonInfo one2 = commonInfoService.findOne(293);
             List<Long> shopIdList = records.stream().map(GoodsShop::getShopId).collect(Collectors.toList());
             List<Long> shopIdList = records.stream().map(GoodsShop::getShopId).collect(Collectors.toList());
             List<Goods> goodsList = goodsDao.selectGoodsBySalesAndGoodsNameAndShopIds(shopIdList, queryDTO.getImpotr());
             List<Goods> goodsList = goodsDao.selectGoodsBySalesAndGoodsNameAndShopIds(shopIdList, queryDTO.getImpotr());
             Map<Long, List<Goods>> goodsMap = goodsList.stream().collect(Collectors.groupingBy(Goods::getShopId));
             Map<Long, List<Goods>> goodsMap = goodsList.stream().collect(Collectors.groupingBy(Goods::getShopId));
@@ -551,13 +549,27 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsDao, Goods> implements Go
             List<ShopActivityVO> shopActivityVOS = activityShopService.getActivityByShopIds(shopIdList);
             List<ShopActivityVO> shopActivityVOS = activityShopService.getActivityByShopIds(shopIdList);
             Map<Long, List<ShopActivityVO>> shopActivityMap = shopActivityVOS.stream().collect(Collectors.groupingBy(ShopActivityVO::getShopId));
             Map<Long, List<ShopActivityVO>> shopActivityMap = shopActivityVOS.stream().collect(Collectors.groupingBy(ShopActivityVO::getShopId));
 
 
+            CommonInfo vipPromotionMinAmount = commonInfoService.findOne(446);
+            CommonInfo vipPromotionAmount = commonInfoService.findOne(444);
+            String vipPromotionDesc = "满" + vipPromotionMinAmount.getValue() + "元减" + vipPromotionAmount.getValue() + "元";
+
+            CommonInfo one1 = commonInfoService.findOne(292);
+            CommonInfo one2 = commonInfoService.findOne(293);
             for (int a = 0; a < goodsShopIPage.getRecords().size(); a++) {
             for (int a = 0; a < goodsShopIPage.getRecords().size(); a++) {
                 GoodsShop goodsShop = goodsShopIPage.getRecords().get(a);
                 GoodsShop goodsShop = goodsShopIPage.getRecords().get(a);
                 Long shopId = goodsShop.getShopId();
                 Long shopId = goodsShop.getShopId();
                 goodsShop.setCouponList(couponMap.get(shopId));
                 goodsShop.setCouponList(couponMap.get(shopId));
 
 
-                // 设置活动信息
-                goodsShop.setShopActivityList(shopActivityMap.get(shopId));
+                // 会员专区查询
+                if (StrUtil.equals(queryDTO.getVipPromotion(), goodsShop.getVipPromotion())) {
+                    // 设置会员优惠描述
+                    goodsShop.setVipPromotionDesc(vipPromotionDesc);
+                }
+                // 非会员专区查询
+                else {
+                    // 设置活动信息
+                    goodsShop.setShopActivityList(shopActivityMap.get(shopId));
+                }
 
 
                 if (StringUtils.isNotEmpty(queryDTO.getImpotr())) {
                 if (StringUtils.isNotEmpty(queryDTO.getImpotr())) {
                     goodsShop.setGoodsList(goodsMap.get(shopId));
                     goodsShop.setGoodsList(goodsMap.get(shopId));
@@ -611,6 +623,9 @@ public class GoodsServiceImpl extends ServiceImpl<GoodsDao, Goods> implements Go
         if (StrUtil.isNotBlank(queryDTO.getCity())) {
         if (StrUtil.isNotBlank(queryDTO.getCity())) {
             keyBuilder.append("_city_").append(queryDTO.getCity());
             keyBuilder.append("_city_").append(queryDTO.getCity());
         }
         }
+        if (StrUtil.isNotBlank(queryDTO.getVipPromotion())) {
+            keyBuilder.append("_vip_").append(queryDTO.getVipPromotion());
+        }
 
 
         return keyBuilder.toString();
         return keyBuilder.toString();
     }
     }

+ 34 - 0
src/main/java/com/sqx/modules/goods/service/impl/GoodsShopServiceImpl.java

@@ -1,5 +1,7 @@
 package com.sqx.modules.goods.service.impl;
 package com.sqx.modules.goods.service.impl;
 
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
@@ -62,6 +64,8 @@ import java.util.ArrayList;
 import java.util.Date;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 
 @Service
 @Service
 public class GoodsShopServiceImpl extends ServiceImpl<GoodsShopDao, GoodsShop> implements GoodsShopService {
 public class GoodsShopServiceImpl extends ServiceImpl<GoodsShopDao, GoodsShop> implements GoodsShopService {
@@ -606,4 +610,34 @@ public class GoodsShopServiceImpl extends ServiceImpl<GoodsShopDao, GoodsShop> i
         queryWrapper.eq(GoodsShop::getStatus, 1);
         queryWrapper.eq(GoodsShop::getStatus, 1);
         return list(queryWrapper);
         return list(queryWrapper);
     }
     }
+
+    @Override
+    public void updateVipPromotion(Long shopId, String vipPromotion) {
+        GoodsShop goodsShop = new GoodsShop();
+        goodsShop.setShopId(shopId);
+        goodsShop.setVipPromotion(StrUtil.equals(vipPromotion,"1") ? "1" : "0");
+        baseMapper.updateById(goodsShop);
+    }
+
+    @Override
+    public void updateShopSales(Map<Long, Integer> shopSalesMap) {
+        LambdaQueryWrapper<GoodsShop> queryWrapper = Wrappers.lambdaQuery();
+        // 通过审核
+        queryWrapper.eq(GoodsShop::getStatus, 1);
+        // 已上架
+        queryWrapper.eq(GoodsShop::getPutawayFlag, 0);
+        // 未被封禁
+        queryWrapper.eq(GoodsShop::getBannedFlag, 0);
+        List<GoodsShop> goodsShops = list(queryWrapper);
+        if (CollUtil.isNotEmpty(goodsShops)) {
+            List<GoodsShop> newGoodsShops = goodsShops.stream().map(e -> {
+                GoodsShop goodsShop = new GoodsShop();
+                goodsShop.setShopId(e.getShopId());
+                goodsShop.setShopSales(shopSalesMap.getOrDefault(e.getShopId(), 0));
+                return goodsShop;
+            }).collect(Collectors.toList());
+
+            updateBatchById(newGoodsShops);
+        }
+    }
 }
 }

+ 74 - 0
src/main/java/com/sqx/modules/member/controller/SpecialFavorStudentController.java

@@ -0,0 +1,74 @@
+package com.sqx.modules.member.controller;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.sqx.common.exception.SqxException;
+import com.sqx.common.utils.Result;
+import com.sqx.modules.member.dto.SpecialFavorStudentDTO;
+import com.sqx.modules.member.query.SpecialFavorStudentQuery;
+import com.sqx.modules.member.service.SpecialFavorStudentService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.validation.Valid;
+import java.util.Arrays;
+
+@Api(tags = "特殊照顾学生")
+@RestController
+@RequestMapping("admin/special-favor-student")
+@RequiredArgsConstructor
+public class SpecialFavorStudentController{
+    
+    private final SpecialFavorStudentService specialFavorStudentService;
+
+    @GetMapping("pages")
+    @ApiOperation("分页查询特殊照顾学生列表")
+    public Result pages(@Valid SpecialFavorStudentQuery query) {
+        return Result.success().put("data", specialFavorStudentService.pages(query));
+    }
+
+    @PostMapping
+    @ApiOperation("添加特殊照顾学生")
+    public Result add(@RequestBody @Valid SpecialFavorStudentDTO dto) {
+        specialFavorStudentService.save(dto);
+        return Result.success();
+    }
+
+    @PutMapping
+    @ApiOperation("修改特殊照顾学生")
+    public Result update(@RequestBody @Valid SpecialFavorStudentDTO dto) {
+        if (ObjectUtil.isNull(dto.getId())) {
+            throw new SqxException("id不能为空");
+        }
+        specialFavorStudentService.update(dto);
+        return Result.success();
+    }
+
+    @DeleteMapping
+    @ApiOperation("删除特殊照顾学生")
+    public Result delete(@RequestBody @ApiParam("id的集合") Long[] ids) {
+        specialFavorStudentService.removeByIds(Arrays.asList(ids));
+        return Result.success();
+    }
+
+    @PostMapping("import")
+    @ApiOperation("导入特殊照顾学生")
+    public Result importData(@RequestParam("file") MultipartFile file) {
+        if (file.isEmpty()) {
+            throw new SqxException("文件不能为空");
+        }
+
+        specialFavorStudentService.importData(file);
+        return Result.success();
+    }
+}

+ 81 - 0
src/main/java/com/sqx/modules/member/controller/VipPromoCodeController.java

@@ -0,0 +1,81 @@
+package com.sqx.modules.member.controller;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.sqx.common.exception.SqxException;
+import com.sqx.common.utils.PageUtils;
+import com.sqx.common.utils.Result;
+import com.sqx.modules.member.dto.VipPromoCodeDTO;
+import com.sqx.modules.member.query.VipPromoCodeQuery;
+import com.sqx.modules.member.query.VipPromoRecordQuery;
+import com.sqx.modules.member.service.VipPromoCodeService;
+import com.sqx.modules.member.service.VipPromoRecordService;
+import com.sqx.modules.utils.PromotionCodeUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+import java.util.Arrays;
+
+@Api(tags = "会员推广管理")
+@RestController
+@RequestMapping("admin/vip-promo")
+@RequiredArgsConstructor
+public class VipPromoCodeController{
+    
+    private final VipPromoCodeService vipPromoCodeService;
+    private final VipPromoRecordService vipPromoRecordService;
+
+    @GetMapping("pages")
+    @ApiOperation("分页查询会员推广码")
+    public Result pages(@Valid VipPromoCodeQuery query) {
+        PageUtils page = vipPromoCodeService.pages(query);
+        return Result.success().put("data", page);
+    }
+
+    @GetMapping("generate-promo-code")
+    @ApiOperation("生成会员推广码")
+    public Result generatePromoCode() {
+        String promoCode = PromotionCodeUtil.generatePromotionCode();
+        return Result.success().put("data", promoCode);
+    }
+
+    @PostMapping
+    @ApiOperation("添加会员推广码")
+    public Result add(@RequestBody @Valid VipPromoCodeDTO dto) {
+        vipPromoCodeService.save(dto);
+        return Result.success();
+    }
+
+    @PutMapping
+    @ApiOperation("修改会员推广码")
+    public Result update(@RequestBody @Valid VipPromoCodeDTO dto) {
+        if (ObjectUtil.isNull(dto.getId())) {
+            throw new SqxException("id不能为空");
+        }
+        vipPromoCodeService.update(dto);
+        return Result.success();
+    }
+
+    @DeleteMapping
+    @ApiOperation("删除会员推广码")
+    public Result delete(@RequestBody @ApiParam("id的集合") Long[] ids) {
+        vipPromoCodeService.removeByIds(Arrays.asList(ids));
+        return Result.success();
+    }
+
+    @GetMapping("record/pages")
+    @ApiOperation("分页查询会员推广记录")
+    public Result recordPages(@Valid VipPromoRecordQuery query) {
+        PageUtils page = vipPromoRecordService.pages(query);
+        return Result.success().put("data", page);
+    }
+}

+ 33 - 0
src/main/java/com/sqx/modules/member/controller/app/AppSpecialFavorStudentController.java

@@ -0,0 +1,33 @@
+package com.sqx.modules.member.controller.app;
+
+import com.sqx.common.utils.Result;
+import com.sqx.modules.app.annotation.Login;
+import com.sqx.modules.member.dto.SpecialFavorStudentVerifyDTO;
+import com.sqx.modules.member.service.SpecialFavorStudentService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestAttribute;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+
+@Api(tags = "特殊照顾学生")
+@RestController
+@RequestMapping("app/special-favor-student")
+@RequiredArgsConstructor
+public class AppSpecialFavorStudentController {
+    
+    private final SpecialFavorStudentService specialFavorStudentService;
+
+    @Login
+    @ApiOperation("特殊照顾学生认证审核")
+    @PostMapping("verify")
+    public Result verify(@RequestBody @Valid SpecialFavorStudentVerifyDTO dto, @RequestAttribute("userId") Long userId) {
+        specialFavorStudentService.verify(userId, dto);
+        return Result.success();
+    }
+}

+ 52 - 0
src/main/java/com/sqx/modules/member/controller/app/AppVipController.java

@@ -0,0 +1,52 @@
+package com.sqx.modules.member.controller.app;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.sqx.common.utils.Result;
+import com.sqx.modules.app.annotation.Login;
+import com.sqx.modules.member.dto.CanReduceQueryDTO;
+import com.sqx.modules.member.service.VipService;
+import com.sqx.modules.member.vo.VipReduceVO;
+import com.sqx.modules.pay.vo.PayTransactionsVO;
+import icu.xuyijie.secureapi.annotation.DecryptParam;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
+/**
+ * @author codingliang
+ * @date 2025-11-12
+ */
+@RestController
+@RequestMapping(value = "app/vip")
+@RequiredArgsConstructor
+public class AppVipController {
+
+    private final VipService vipService;
+
+    @Login
+    @ApiOperation(value = "获取用户是否可以会员立减")
+    @GetMapping(value = "get-can-reduce")
+    public Result getCanReduce(@RequestAttribute("userId") Long userId, @Valid CanReduceQueryDTO canReduceQueryDTO){
+        VipReduceVO vipReduceVO = vipService.getVipReduceInfo(userId, canReduceQueryDTO);
+        return Result.success().put("data", vipReduceVO);
+    }
+
+    @Login
+    @ApiOperation(value = "获取购买vip支付参数", notes = "promoCode 为推荐码")
+    @GetMapping(value = "get-pay-param")
+    public Result getPayParam(@RequestAttribute("userId") Long userId, @DecryptParam(value = "promoCode") String promoCode){
+        PayTransactionsVO payParamVO = vipService.getPayParam(userId, promoCode);
+
+        return Result.success(BeanUtil.beanToMap(payParamVO, false, true));
+    }
+
+    @Login
+    @ApiOperation(value = "余额购买vip", notes = "promoCode 为推荐码")
+    @GetMapping(value = "balance-pay")
+    public Result balancePay(@RequestAttribute("userId") Long userId, @DecryptParam(value = "promoCode") String promoCode){
+        vipService.balancePay(userId, promoCode);
+        return Result.success();
+    }
+}

+ 15 - 0
src/main/java/com/sqx/modules/member/dao/SpecialFavorStudentDao.java

@@ -0,0 +1,15 @@
+package com.sqx.modules.member.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.sqx.modules.member.entity.SpecialFavorStudent;
+import com.sqx.modules.member.query.SpecialFavorStudentQuery;
+import com.sqx.modules.member.vo.SpecialFavorStudentVO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface SpecialFavorStudentDao extends BaseMapper<SpecialFavorStudent> {
+
+    IPage<SpecialFavorStudentVO> pages(@Param("page") IPage<SpecialFavorStudentVO> page, @Param("query") SpecialFavorStudentQuery query);
+}

+ 12 - 0
src/main/java/com/sqx/modules/member/dao/VipPromoCodeDao.java

@@ -0,0 +1,12 @@
+package com.sqx.modules.member.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.sqx.modules.member.entity.VipPromoCode;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface VipPromoCodeDao extends BaseMapper<VipPromoCode> {
+
+    void incrementPromoCountById(@Param("promoCodeId") Long promoCodeId);
+}

+ 15 - 0
src/main/java/com/sqx/modules/member/dao/VipPromoRecordDao.java

@@ -0,0 +1,15 @@
+package com.sqx.modules.member.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.sqx.modules.member.entity.VipPromoRecord;
+import com.sqx.modules.member.query.VipPromoRecordQuery;
+import com.sqx.modules.member.vo.VipPromoRecordVO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface VipPromoRecordDao extends BaseMapper<VipPromoRecord> {
+
+    IPage<VipPromoRecordVO> pages(@Param("page") IPage<VipPromoRecordVO> page, @Param("query") VipPromoRecordQuery query);
+}

+ 27 - 0
src/main/java/com/sqx/modules/member/dto/CanReduceQueryDTO.java

@@ -0,0 +1,27 @@
+package com.sqx.modules.member.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+
+/**
+ * 查询是否可以减免参数
+ * @author codingliang
+ * @date 2025-11-30
+ */
+@Data
+public class CanReduceQueryDTO {
+
+    /**
+     * 店铺id
+     */
+    @NotNull(message = "店铺id不能为空")
+    private Long shopId;
+
+    /**
+     * 订单原始价格
+     */
+    @NotNull(message = "订单原始价格不能为空")
+    private BigDecimal originalPrice;
+}

+ 30 - 0
src/main/java/com/sqx/modules/member/dto/SpecialFavorStudentDTO.java

@@ -0,0 +1,30 @@
+package com.sqx.modules.member.dto;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+
+@Data
+@ApiModel(value = "特殊照顾学生")
+public class SpecialFavorStudentDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    @ApiModelProperty(name = "id")
+    private Long id;
+
+    @ApiModelProperty(name = "真实姓名")
+    @NotBlank(message = "真实姓名不能为空")
+    @ExcelProperty(value = "姓名")
+    private String name;
+    
+    @ApiModelProperty(name = "学号")
+    @NotBlank(message = "学号不能为空")
+    @ExcelProperty(value = "学号")
+    private String studentNumber;
+}

+ 25 - 0
src/main/java/com/sqx/modules/member/dto/SpecialFavorStudentVerifyDTO.java

@@ -0,0 +1,25 @@
+package com.sqx.modules.member.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * 特殊照顾学生审核DTO
+ * @author codingliang
+ * @date 2025-11-12
+ */
+@Data
+@ApiModel(description = "特殊照顾学生审核")
+public class SpecialFavorStudentVerifyDTO {
+
+    @ApiModelProperty(value = "学生姓名")
+    @NotBlank(message = "学生姓名不能为空")
+    private String name;
+
+    @ApiModelProperty(value = "学生学号")
+    @NotBlank(message = "学生学号不能为空")
+    private String studentNumber;
+}

+ 34 - 0
src/main/java/com/sqx/modules/member/dto/VipPromoCodeDTO.java

@@ -0,0 +1,34 @@
+package com.sqx.modules.member.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+* 会员推广码
+* @author : codingliang
+* @date : 2025-11-11
+*/
+@Data
+@ApiModel(value = "会员推广码")
+public class VipPromoCodeDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "id")
+    private Long id;
+
+    @ApiModelProperty(value = "推广人名称")
+    private String userName;
+
+    @ApiModelProperty(value = "推广码")
+    private String promoCode;
+
+    @ApiModelProperty(value = "推广人身份证号码")
+    private String idCard;
+
+    @ApiModelProperty(value = "推广人手机号码")
+    private String phone;
+}

+ 41 - 0
src/main/java/com/sqx/modules/member/dto/VipPromoRecordDTO.java

@@ -0,0 +1,41 @@
+package com.sqx.modules.member.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Builder;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+* 会员推广记录
+* @author : codingliang
+* @date : 2025-11-11
+*/
+@Data
+@Builder
+public class VipPromoRecordDTO {
+
+    @ApiModelProperty("推荐码")
+    private String promoCode;
+
+    @ApiModelProperty("用户id")
+    private Long userId;
+    
+    @ApiModelProperty("用户名称")
+    private String userName;
+    
+    @ApiModelProperty("用户手机号")
+    private String userPhone;
+    
+    @ApiModelProperty("创建时间")
+    private Date createTime;
+
+    @ApiModelProperty("支付类型;1微信支付、2余额支付、3暖心照顾")
+    private String payType;
+    
+    @ApiModelProperty("支付金额")
+    private Double payAmount;
+    
+    @ApiModelProperty("支付关联id")
+    private String payRelId;
+}

+ 63 - 0
src/main/java/com/sqx/modules/member/entity/SpecialFavorStudent.java

@@ -0,0 +1,63 @@
+package com.sqx.modules.member.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+ /**
+ * 特殊照顾学生
+ * @author : codingliang
+ * @date : 2025-11-11
+ */
+@Data
+@TableName("special_favor_student")
+public class SpecialFavorStudent implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * id
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 删除标识;0未删除、1已删除
+     */
+    @TableLogic(value = "0", delval = "1")
+    private String delFlag;
+    
+    /**
+     * 真实姓名
+     */
+    private String name;
+    
+    /**
+     * 学号
+     */
+    private String studentNumber;
+    
+    /**
+     * 验证状态;0未认证、1已认证
+     */
+    private String verifyStatus;
+    
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+    
+    /**
+     * 验证用户id
+     */
+    private Long verifyUserId;
+    
+    /**
+     * 最后验证时间
+     */
+    private Date lastVerifyTime;
+}

+ 63 - 0
src/main/java/com/sqx/modules/member/entity/VipPromoCode.java

@@ -0,0 +1,63 @@
+package com.sqx.modules.member.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+* 会员推广码
+* @author : codingliang
+* @date : 2025-11-11
+*/
+@Data
+@TableName("vip_promo_code")
+public class VipPromoCode implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * id
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 删除标识;0未删除、1已删除
+     */
+    @TableLogic(value = "0", delval = "1")
+    private String delFlag;
+
+    /**
+     * 推广人名称
+     */
+    private String userName;
+
+    /**
+     * 推广码
+     */
+    private String promoCode;
+
+    /**
+     * 推广人身份证号码
+     */
+    private String idCard;
+
+    /**
+     * 推广人手机号码
+     */
+    private String phone;
+
+    /**
+     * 推广人次
+     */
+    private Integer promoCount;
+
+     /**
+      * 创建时间
+      */
+     private Date createTime;
+}

+ 73 - 0
src/main/java/com/sqx/modules/member/entity/VipPromoRecord.java

@@ -0,0 +1,73 @@
+package com.sqx.modules.member.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+* 会员推广记录
+* @author : codingliang
+* @date : 2025-11-11
+*/
+@Data
+@TableName("vip_promo_record")
+public class VipPromoRecord implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * id
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 删除标识;0未删除、1已删除
+     */
+    @TableLogic(value = "0", delval = "1")
+    private String delFlag;
+
+    /**
+     * 推广码id
+     */
+    private Long promoCodeId;
+
+    /**
+     * 用户id
+     */
+    private Long userId;
+    
+    /**
+     * 用户名称
+     */
+    private String userName;
+    
+    /**
+     * 用户手机号
+     */
+    private String userPhone;
+    
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 支付类型;1微信支付、2余额支付、3暖心照顾
+     */
+    private String payType;
+    
+    /**
+     * 支付金额
+     */
+    private Double payAmount;
+    
+    /**
+     * 支付关联id
+     */
+    private String payRelId;
+}

+ 82 - 0
src/main/java/com/sqx/modules/member/query/SpecialFavorStudentQuery.java

@@ -0,0 +1,82 @@
+package com.sqx.modules.member.query;
+
+import cn.hutool.core.util.StrUtil;
+import com.sqx.common.query.PageQuery;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * 特殊照顾学生查询参数
+ * @author codingliang
+ * @date 2025-11-12
+ */
+@Data
+@ApiModel("特殊照顾学生查询参数")
+public class SpecialFavorStudentQuery extends PageQuery {
+
+    @ApiModelProperty("真实姓名")
+    private String name;
+
+    @ApiModelProperty("学号")
+    private String studentNumber;
+
+    @ApiModelProperty("验证状态;0未认证、1已认证")
+    private String verifyStatus;
+
+    @ApiModelProperty("查询认证开始时间")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date startTime;
+
+    @ApiModelProperty("查询认证结束时间")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date endTime;
+
+    /**
+     * 拼接查询条件字符串
+     * @return 拼接后的查询条件字符串
+     */
+    public String buildQueryConditionString() {
+        StringBuilder conditionBuilder = new StringBuilder();
+
+        // 拼接真实姓名条件
+        if (StrUtil.isNotBlank(this.name)) {
+            conditionBuilder.append("真实姓名: ").append(this.name).append(",");
+        }
+
+        // 拼接学号条件
+        if (StrUtil.isNotBlank(this.studentNumber)) {
+            conditionBuilder.append("学号: ").append(this.studentNumber).append(",");
+        }
+
+        // 拼接验证状态条件(转换为中文)
+        if (StrUtil.isNotBlank(this.verifyStatus)) {
+            String verifyStatusText = "1".equals(this.verifyStatus) ? "已验证" : "未验证";
+            conditionBuilder.append("验证状态: ").append(verifyStatusText).append(",");
+        }
+
+        // 拼接认证开始时间条件
+        if (this.startTime != null) {
+            conditionBuilder.append("认证开始时间: ")
+                    .append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.startTime))
+                    .append(",");
+        }
+
+        // 拼接认证结束时间条件
+        if (this.endTime != null) {
+            conditionBuilder.append("认证结束时间: ")
+                    .append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.endTime))
+                    .append(",");
+        }
+
+        // 拼接分页信息
+        conditionBuilder.append("当前页码: ").append(getPage())
+                .append(",每页条数: ").append(getLimit());
+
+        return conditionBuilder.toString();
+    }
+}

+ 50 - 0
src/main/java/com/sqx/modules/member/query/VipPromoCodeQuery.java

@@ -0,0 +1,50 @@
+package com.sqx.modules.member.query;
+
+import cn.hutool.core.util.StrUtil;
+import com.sqx.common.query.PageQuery;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 会员推广码查询参数
+ * @author codingliang
+ * @date 2025-11-12
+ */
+@Data
+@ApiModel(description = "会员推广码查询参数")
+public class VipPromoCodeQuery extends PageQuery {
+
+    @ApiModelProperty(value = "会员用户名")
+    private String userName;
+
+    @ApiModelProperty(value = "推广码")
+    private String promoCode;
+
+    @ApiModelProperty(value = "推广人手机号码")
+    private String phone;
+
+    public String buildQueryConditionString() {
+        StringBuilder sb = new StringBuilder();
+
+        // 会员用户名
+        if (StrUtil.isNotBlank(userName)) {
+            sb.append("会员用户名:").append(userName).append(", ");
+        }
+
+        // 推广码
+        if (StrUtil.isNotBlank(promoCode)) {
+            sb.append("推广码:").append(promoCode).append(", ");
+        }
+
+        // 推广人手机号码
+        if (StrUtil.isNotBlank(phone)) {
+            sb.append("推广人手机号码:").append(phone).append(", ");
+        }
+
+        sb.append("页码:").append(getPage()).append(", ");
+        sb.append("每页条数:").append(getLimit());
+
+        return sb.toString();
+    }
+}

+ 105 - 0
src/main/java/com/sqx/modules/member/query/VipPromoRecordQuery.java

@@ -0,0 +1,105 @@
+package com.sqx.modules.member.query;
+
+import com.sqx.common.query.PageQuery;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+@Data
+@ApiModel(description = "会员推广记录查询参数")
+public class VipPromoRecordQuery extends PageQuery {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "推广码id")
+    private Long promoCodeId;
+
+    @ApiModelProperty(value = "用户手机号")
+    private String userPhone;
+
+    // @ApiModelProperty(value = "支付类型 1微信支付、2余额支付、3暖心照顾")
+    // private String payType;
+
+    @ApiModelProperty(value = "是否暖心照顾 1是、0否")
+    private String specialFlag;
+    
+    @ApiModelProperty(value = "查询开始时间")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date startTime;
+
+    @ApiModelProperty(value = "查询结束时间")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date endTime;
+
+    /**
+     * 拼接查询条件字符串
+     * @return 拼接后的查询条件字符串
+     */
+    public String buildQueryConditionString() {
+        StringBuilder sb = new StringBuilder();
+
+        // 推广码id
+        if (getPromoCodeId() != null) {
+            sb.append("推广码id:").append(getPromoCodeId()).append(", ");
+        }
+
+        // 用户手机号
+        if (getUserPhone() != null && !getUserPhone().trim().isEmpty()) {
+            sb.append("用户手机号:").append(getUserPhone()).append(", ");
+        }
+
+        // 是否暖心照顾
+        if (getSpecialFlag() != null && !getSpecialFlag().trim().isEmpty()) {
+            String specialFlagText = "";
+            switch (getSpecialFlag()) {
+                case "1":
+                    specialFlagText = "是";
+                    break;
+                case "0":
+                    specialFlagText = "否";
+                    break;
+                default:
+                    specialFlagText = getSpecialFlag();
+            }
+            sb.append("是否暖心照顾:").append(specialFlagText).append(", ");
+        }
+
+        // 支付类型
+        // if (getPayType() != null && !getPayType().trim().isEmpty()) {
+        //     String payTypeText = "";
+        //     switch (getPayType()) {
+        //         case "1":
+        //             payTypeText = "微信支付";
+        //             break;
+        //         case "2":
+        //             payTypeText = "余额支付";
+        //             break;
+        //         case "3":
+        //             payTypeText = "暖心照顾";
+        //             break;
+        //         default:
+        //             payTypeText = getPayType();
+        //     }
+        //     sb.append("支付类型:").append(payTypeText).append(", ");
+        // }
+
+        // 开始时间
+        if (getStartTime() != null) {
+            sb.append("开始时间:").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(getStartTime())).append(", ");
+        }
+
+        // 结束时间
+        if (getEndTime() != null) {
+            sb.append("结束时间:").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(getEndTime())).append(", ");
+        }
+
+        // 分页信息
+        sb.append("页码:").append(getPage()).append(", ");
+        sb.append("每页条数:").append(getLimit());
+
+        return sb.toString();
+    }
+}

+ 27 - 0
src/main/java/com/sqx/modules/member/service/SpecialFavorStudentService.java

@@ -0,0 +1,27 @@
+package com.sqx.modules.member.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.sqx.common.utils.PageUtils;
+import com.sqx.modules.member.dto.SpecialFavorStudentDTO;
+import com.sqx.modules.member.dto.SpecialFavorStudentVerifyDTO;
+import com.sqx.modules.member.entity.SpecialFavorStudent;
+import com.sqx.modules.member.query.SpecialFavorStudentQuery;
+import org.springframework.web.multipart.MultipartFile;
+
+public interface SpecialFavorStudentService extends IService<SpecialFavorStudent> {
+
+    PageUtils pages(SpecialFavorStudentQuery query);
+
+    void save(SpecialFavorStudentDTO dto);
+
+    void update(SpecialFavorStudentDTO dto);
+
+    void importData(MultipartFile file);
+
+    /**
+     * 特殊照顾学生认证审核
+     * @param userId 登录用户id
+     * @param dto    特殊照顾学生认证审核参数
+     */
+    void verify(Long userId, SpecialFavorStudentVerifyDTO dto);
+}

+ 36 - 0
src/main/java/com/sqx/modules/member/service/VipPromoCodeService.java

@@ -0,0 +1,36 @@
+package com.sqx.modules.member.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.sqx.common.utils.PageUtils;
+import com.sqx.modules.member.dto.VipPromoCodeDTO;
+import com.sqx.modules.member.entity.VipPromoCode;
+import com.sqx.modules.member.query.VipPromoCodeQuery;
+
+/**
+ * 会员推广码
+ *
+ * @author : codingliang
+ * @date : 2025-11-11
+ */
+public interface VipPromoCodeService extends IService<VipPromoCode> {
+
+    PageUtils pages(VipPromoCodeQuery query);
+
+    void save(VipPromoCodeDTO dto);
+
+    void update(VipPromoCodeDTO dto);
+
+    /**
+     * 根据推广码获取会员推广码
+     *
+     * @param promoCode 推广码
+     * @return 会员推广码
+     */
+    VipPromoCode getByCode(String promoCode);
+
+    /**
+     * 增加推广次数
+     * @param promoCodeId 会员推广码id
+     */
+    void increasePromoCount(Long promoCodeId);
+}

+ 18 - 0
src/main/java/com/sqx/modules/member/service/VipPromoRecordService.java

@@ -0,0 +1,18 @@
+package com.sqx.modules.member.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.sqx.common.utils.PageUtils;
+import com.sqx.modules.member.dto.VipPromoRecordDTO;
+import com.sqx.modules.member.entity.VipPromoRecord;
+import com.sqx.modules.member.query.VipPromoRecordQuery;
+
+public interface VipPromoRecordService extends IService<VipPromoRecord> {
+
+    PageUtils pages(VipPromoRecordQuery query);
+
+    /**
+     * 新增会员推广记录
+     * @param recordDTO 会员推广记录dto
+     */
+    void add(VipPromoRecordDTO recordDTO);
+}

+ 40 - 0
src/main/java/com/sqx/modules/member/service/VipService.java

@@ -0,0 +1,40 @@
+package com.sqx.modules.member.service;
+
+import com.sqx.modules.member.dto.CanReduceQueryDTO;
+import com.sqx.modules.member.vo.VipReduceVO;
+import com.sqx.modules.pay.entity.PayDetails;
+import com.sqx.modules.pay.vo.PayTransactionsVO;
+
+import javax.validation.Valid;
+
+public interface VipService {
+
+    /**
+     * 获取购买vip支付参数
+     * @param userId 用户id
+     * @param promoCode 优惠券码,可选
+     * @return 支付参数
+     */
+    PayTransactionsVO getPayParam(Long userId, String promoCode);
+
+     /**
+      * 处理会员支付成功通知
+      * @param payDetails 支付详情
+      */
+    void paySuccess(PayDetails payDetails);
+
+     /**
+      * 余额购买vip
+      * @param userId 用户id
+      * @param promoCode 优惠券码,可选
+      */
+    void balancePay(Long userId, String promoCode);
+
+     /**
+      * 获取用户是否可以会员立减
+      * @param userId 用户id
+      * @param canReduceQueryDTO 查询是否可以减免参数
+      * @return vip 立减信息
+      */
+    VipReduceVO getVipReduceInfo(Long userId, @Valid CanReduceQueryDTO canReduceQueryDTO);
+}

+ 152 - 0
src/main/java/com/sqx/modules/member/service/impl/SpecialFavorStudentServiceImpl.java

@@ -0,0 +1,152 @@
+package com.sqx.modules.member.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sqx.common.exception.SqxException;
+import com.sqx.common.utils.PageUtils;
+import com.sqx.common.validator.ValidatorUtils;
+import com.sqx.modules.app.entity.UserEntity;
+import com.sqx.modules.app.service.UserService;
+import com.sqx.modules.member.dao.SpecialFavorStudentDao;
+import com.sqx.modules.member.dto.SpecialFavorStudentDTO;
+import com.sqx.modules.member.dto.SpecialFavorStudentVerifyDTO;
+import com.sqx.modules.member.dto.VipPromoRecordDTO;
+import com.sqx.modules.member.entity.SpecialFavorStudent;
+import com.sqx.modules.member.query.SpecialFavorStudentQuery;
+import com.sqx.modules.member.service.SpecialFavorStudentService;
+import com.sqx.modules.member.service.VipPromoRecordService;
+import com.sqx.modules.member.vo.SpecialFavorStudentVO;
+import com.sqx.modules.utils.VipExpirationUtil;
+import com.sqx.modules.utils.excel.EasyExcelUtil;
+import com.sqx.modules.utils.excel.ExcelFinishCallBack;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+@Service
+@RequiredArgsConstructor
+public class SpecialFavorStudentServiceImpl extends ServiceImpl<SpecialFavorStudentDao, SpecialFavorStudent> implements SpecialFavorStudentService {
+
+    private final UserService userService;
+    private final VipPromoRecordService vipPromoRecordService;
+
+    @Override
+    public PageUtils pages(SpecialFavorStudentQuery query) {
+        IPage<SpecialFavorStudentVO> page = baseMapper.pages(new Page<>(query.getPage(), query.getLimit()), query);
+        return new PageUtils(page);
+    }
+
+    @Override
+    public void save(SpecialFavorStudentDTO dto) {
+        // 检验参数
+        checkParam(dto);
+
+        SpecialFavorStudent specialFavorStudent = new SpecialFavorStudent();
+        BeanUtil.copyProperties(dto, specialFavorStudent);
+        specialFavorStudent.setCreateTime(new Date());
+        baseMapper.insert(specialFavorStudent);
+    }
+
+    @Override
+    public void update(SpecialFavorStudentDTO dto) {
+        // 校验参数
+        checkParam(dto);
+
+        SpecialFavorStudent specialFavorStudent = new SpecialFavorStudent();
+        BeanUtil.copyProperties(dto, specialFavorStudent);
+        baseMapper.updateById(specialFavorStudent);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void importData(MultipartFile file) {
+        EasyExcelUtil.readAnalysis(file, SpecialFavorStudentDTO.class, new ExcelFinishCallBack<SpecialFavorStudentDTO>() {
+            @Override
+            public void doAfterAllAnalysed(List<SpecialFavorStudentDTO> result) {
+                if (!result.isEmpty()) {
+                    saveBatchData(result);
+                }
+            }
+
+            @Override
+            public void doSaveBatch(List<SpecialFavorStudentDTO> result) {
+                saveBatchData(result);
+            }
+
+            private void saveBatchData(List<SpecialFavorStudentDTO> dtoList) {
+                List<SpecialFavorStudent> entities = new ArrayList<>();
+                Date now = new Date();
+                for (SpecialFavorStudentDTO dto : dtoList) {
+                    // 校验参数
+                    ValidatorUtils.validateEntity(dto);
+                    checkParam(dto);
+
+                    SpecialFavorStudent entity = new SpecialFavorStudent();
+                    BeanUtil.copyProperties(dto, entity);
+                    entity.setCreateTime(now);
+                    entities.add(entity);
+                }
+
+                // 批量保存
+                saveBatch(entities);
+            }
+        });
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void verify(Long userId, SpecialFavorStudentVerifyDTO dto) {
+        LambdaQueryWrapper<SpecialFavorStudent> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(SpecialFavorStudent::getStudentNumber, dto.getStudentNumber());
+        queryWrapper.eq(SpecialFavorStudent::getName, dto.getName());
+
+        SpecialFavorStudent specialFavorStudent = baseMapper.selectOne(queryWrapper);
+        if (ObjectUtil.isNull(specialFavorStudent)) {
+            throw new SqxException("认证失败,身份不符合");
+        }
+
+        UserEntity user = userService.getById(userId);
+        if(ObjectUtil.isNotNull(user.getIsVip()) && user.getIsVip() == 1 && VipExpirationUtil.isVipValid(user.getVipExpirationTime())) {
+            throw new SqxException("已经是会员,不能重复购买!");
+        }
+
+        // 更新认证状态
+        specialFavorStudent.setVerifyStatus("1");
+        specialFavorStudent.setVerifyUserId(userId);
+        specialFavorStudent.setLastVerifyTime(new Date());
+
+        updateById(specialFavorStudent);
+
+        // 添加会员推广记录
+        VipPromoRecordDTO recordDTO = VipPromoRecordDTO.builder()
+                .userId(userId)
+                .userName(user.getNickName())
+                .userPhone(user.getPhone())
+                .payType("3")
+                .payAmount(0.0)
+                .build();
+        vipPromoRecordService.add(recordDTO);
+
+        // 更新用户为会员
+        userService.updateUserToVip(userId, VipExpirationUtil.getFutureTimeWithDays(30));
+    }
+
+    private void checkParam(SpecialFavorStudentDTO dto) {
+        // 校验学号是否存在
+        LambdaQueryWrapper<SpecialFavorStudent> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(SpecialFavorStudent::getStudentNumber, dto.getStudentNumber());
+        queryWrapper.ne(ObjectUtil.isNotNull(dto.getId()), SpecialFavorStudent::getId, dto.getId());
+        if (count(queryWrapper) > 0) {
+            throw new SqxException("学号[" + dto.getStudentNumber() + "]已存在");
+        }
+    }
+}

+ 97 - 0
src/main/java/com/sqx/modules/member/service/impl/VipPromoCodeServiceImpl.java

@@ -0,0 +1,97 @@
+package com.sqx.modules.member.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sqx.common.exception.SqxException;
+import com.sqx.common.utils.PageUtils;
+import com.sqx.modules.app.service.UserService;
+import com.sqx.modules.member.dao.VipPromoCodeDao;
+import com.sqx.modules.member.dto.VipPromoCodeDTO;
+import com.sqx.modules.member.entity.VipPromoCode;
+import com.sqx.modules.member.query.VipPromoCodeQuery;
+import com.sqx.modules.member.service.VipPromoCodeService;
+import com.sqx.modules.member.vo.VipPromoCodeVO;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+@RequiredArgsConstructor
+public class VipPromoCodeServiceImpl extends ServiceImpl<VipPromoCodeDao, VipPromoCode> implements VipPromoCodeService {
+
+    private final UserService userService;
+
+    @Override
+    public PageUtils pages(VipPromoCodeQuery query) {
+        IPage<VipPromoCode> page = baseMapper.selectPage(
+                new Page<>(query.getPage(), query.getLimit()),
+                new LambdaQueryWrapper<VipPromoCode>()
+                        .like(StrUtil.isNotBlank(query.getUserName()), VipPromoCode::getUserName, query.getUserName())
+                        .like(StrUtil.isNotBlank(query.getPromoCode()), VipPromoCode::getPromoCode, query.getPromoCode())
+                        .like(StrUtil.isNotBlank(query.getPhone()), VipPromoCode::getPhone, query.getPhone())
+                        .orderByDesc(VipPromoCode::getCreateTime)
+        );
+
+        List<VipPromoCodeVO> vos = page.getRecords().stream().map(e -> {
+            VipPromoCodeVO vo = new VipPromoCodeVO();
+            BeanUtil.copyProperties(e, vo);
+            return vo;
+        }).collect(Collectors.toList());
+
+        return new PageUtils(vos, (int) page.getTotal(), query.getLimit(), query.getPage());
+    }
+
+    @Override
+    public void save(VipPromoCodeDTO dto) {
+        // 检验参数
+        checkParam(dto);
+
+        VipPromoCode vipPromoCode = new VipPromoCode();
+        BeanUtil.copyProperties(dto, vipPromoCode);
+        vipPromoCode.setCreateTime(new Date());
+        baseMapper.insert(vipPromoCode);
+    }
+
+    @Override
+    public void update(VipPromoCodeDTO dto) {
+        // 校验参数
+        checkParam(dto);
+
+        VipPromoCode vipPromoCode = new VipPromoCode();
+        BeanUtil.copyProperties(dto, vipPromoCode);
+        baseMapper.updateById(vipPromoCode);
+    }
+
+    @Override
+    public VipPromoCode getByCode(String promoCode) {
+        LambdaQueryWrapper<VipPromoCode> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(VipPromoCode::getPromoCode, promoCode);
+        return baseMapper.selectOne(wrapper);
+    }
+
+    @Override
+    public void increasePromoCount(Long promoCodeId) {
+        baseMapper.incrementPromoCountById(promoCodeId);
+    }
+
+    private void checkParam(VipPromoCodeDTO dto) {
+        LambdaQueryWrapper<VipPromoCode> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(VipPromoCode::getPromoCode, dto.getPromoCode());
+        wrapper.ne(ObjectUtil.isNotNull(dto.getId()), VipPromoCode::getId, dto.getId());
+        if (baseMapper.selectCount(wrapper) > 0) {
+            throw new SqxException("推广码已存在");
+        }
+
+        if (ObjectUtil.isNull(userService.queryByPhone(dto.getPhone()))) {
+            throw new SqxException("手机号码不存在,请确认!");
+        }
+    }
+}

+ 55 - 0
src/main/java/com/sqx/modules/member/service/impl/VipPromoRecordServiceImpl.java

@@ -0,0 +1,55 @@
+package com.sqx.modules.member.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sqx.common.utils.PageUtils;
+import com.sqx.modules.member.dao.VipPromoRecordDao;
+import com.sqx.modules.member.dto.VipPromoRecordDTO;
+import com.sqx.modules.member.entity.VipPromoCode;
+import com.sqx.modules.member.entity.VipPromoRecord;
+import com.sqx.modules.member.query.VipPromoRecordQuery;
+import com.sqx.modules.member.service.VipPromoCodeService;
+import com.sqx.modules.member.service.VipPromoRecordService;
+import com.sqx.modules.member.vo.VipPromoRecordVO;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Date;
+
+@Service
+@RequiredArgsConstructor
+public class VipPromoRecordServiceImpl extends ServiceImpl<VipPromoRecordDao, VipPromoRecord> implements VipPromoRecordService {
+
+    private final VipPromoCodeService vipPromoCodeService;
+
+    @Override
+    public PageUtils pages(VipPromoRecordQuery query) {
+        IPage<VipPromoRecordVO> pages = baseMapper.pages(new Page<>(query.getPage(), query.getLimit()), query);
+
+        return new PageUtils(pages);
+    }
+
+    @Override
+    @Transactional
+    public void add(VipPromoRecordDTO recordDTO) {
+        VipPromoRecord record = new VipPromoRecord();
+        BeanUtil.copyProperties(recordDTO, record);
+
+        record.setCreateTime(new Date());
+        if (StrUtil.isNotBlank(recordDTO.getPromoCode())) {
+            VipPromoCode promoCode = vipPromoCodeService.getByCode(recordDTO.getPromoCode());
+            if (ObjectUtil.isNotNull(promoCode)) {
+                record.setPromoCodeId(promoCode.getId());
+
+                vipPromoCodeService.increasePromoCount(promoCode.getId());
+            }
+        }
+
+        save(record);
+    }
+}

+ 227 - 0
src/main/java/com/sqx/modules/member/service/impl/VipServiceImpl.java

@@ -0,0 +1,227 @@
+package com.sqx.modules.member.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.sqx.common.exception.SqxException;
+import com.sqx.common.utils.Constant;
+import com.sqx.modules.app.bo.UpdateMoneyBO;
+import com.sqx.modules.app.entity.UserEntity;
+import com.sqx.modules.app.service.UserMoneyService;
+import com.sqx.modules.app.service.UserService;
+import com.sqx.modules.common.entity.CommonInfo;
+import com.sqx.modules.common.service.CommonInfoService;
+import com.sqx.modules.coupon.service.TbCouponUserService;
+import com.sqx.modules.goods.entity.GoodsShop;
+import com.sqx.modules.goods.service.GoodsShopService;
+import com.sqx.modules.member.dto.CanReduceQueryDTO;
+import com.sqx.modules.member.dto.VipPromoRecordDTO;
+import com.sqx.modules.member.entity.VipPromoCode;
+import com.sqx.modules.member.service.VipPromoCodeService;
+import com.sqx.modules.member.service.VipPromoRecordService;
+import com.sqx.modules.member.service.VipService;
+import com.sqx.modules.member.vo.VipReduceVO;
+import com.sqx.modules.order.entity.TbOrder;
+import com.sqx.modules.order.service.AppOrderService;
+import com.sqx.modules.pay.dto.GetPayParamDTO;
+import com.sqx.modules.pay.entity.PayDetails;
+import com.sqx.modules.pay.enums.PayChannelEnum;
+import com.sqx.modules.pay.enums.PaySceneEnum;
+import com.sqx.modules.pay.service.NewPayService;
+import com.sqx.modules.pay.vo.PayTransactionsVO;
+import com.sqx.modules.utils.VipExpirationUtil;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.validation.Valid;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+/**
+ * vip服务
+ * @author codingliang
+ * @date 2025-11-12
+ */
+@Service
+@RequiredArgsConstructor
+public class VipServiceImpl implements VipService {
+
+    private final NewPayService newPayService;
+    private final UserService userService;
+    private final CommonInfoService commonInfoService;
+    private final TbCouponUserService tbCouponUserService;
+    private final VipPromoCodeService vipPromoCodeService;
+    private final VipPromoRecordService vipPromoRecordService;
+    private final UserMoneyService userMoneyService;
+    private final GoodsShopService goodsShopService;
+    private final AppOrderService appOrderService;
+
+
+    @Override
+    public PayTransactionsVO getPayParam(Long userId, String promoCode) {
+        UserEntity user = userService.getById(userId);
+        beforePay(user, promoCode);
+
+        // 查询会员价格
+        CommonInfo one = commonInfoService.findOne(313);
+        BigDecimal vipPrice = BigDecimal.valueOf(Double.valueOf(one.getValue()));
+
+        // 构建获取支付参数dto
+        GetPayParamDTO dto = GetPayParamDTO.builder()
+                .orderNo(IdWorker.getTimeId())
+                .orderDesc("墨轩商场会员")
+                .amount(vipPrice.setScale(2, RoundingMode.HALF_UP))
+                .userId(userId)
+                .userThirdId(user.getOpenId())
+                .payChannel(PayChannelEnum.WECHAT_JS_API)
+                .paySceneEnum(PaySceneEnum.VIP_PAY)
+                .extra(promoCode)
+                .build();
+
+        return newPayService.getWechatTransactionsParamVO(dto);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void paySuccess(PayDetails payDetails) {
+        Long userId = payDetails.getUserId();
+        UserEntity user = userService.getById(userId);
+        VipPromoRecordDTO recordDTO = VipPromoRecordDTO.builder()
+                .userId(userId)
+                .userName(user.getNickName())
+                .userPhone(user.getPhone())
+                .payType("1")
+                .promoCode(payDetails.getExtra())
+                .payAmount(payDetails.getMoney())
+                .payRelId(payDetails.getOrderId())
+                .build();
+        vipPromoRecordService.add(recordDTO);
+
+        // 更新用户为会员
+        afterPaySuccess(payDetails.getUserId());
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void balancePay(Long userId, String promoCode) {
+        UserEntity user = userService.getById(userId);
+        beforePay(user, promoCode);
+
+        // 会员价格
+        CommonInfo vipPrice = commonInfoService.findOne(313);
+
+        // 扣减用户余额
+        UpdateMoneyBO updateMoneyBO = UpdateMoneyBO.builder()
+                .type(2)
+                .classify(3)
+                .userId(userId)
+                .amount(new BigDecimal(vipPrice.getValue()))
+                .title("购买会员")
+                .build();
+        userMoneyService.updateUserMoney(updateMoneyBO);
+
+        // 新增会员充值记录
+        VipPromoRecordDTO recordDTO = VipPromoRecordDTO.builder()
+                .userId(userId)
+                .userName(user.getNickName())
+                .userPhone(user.getPhone())
+                .payType("2")
+                .promoCode(promoCode)
+                .payAmount(Double.valueOf(vipPrice.getValue()))
+                .payRelId("")
+                .build();
+        vipPromoRecordService.add(recordDTO);
+
+        // 更新用户为会员
+        afterPaySuccess(userId);
+    }
+
+    private void beforePay(UserEntity user, String promoCode) {
+        if(ObjectUtil.isNotNull(user.getIsVip()) && user.getIsVip() == 1 && VipExpirationUtil.isVipValid(user.getVipExpirationTime())) {
+            throw new SqxException("已经是会员,不能重复购买!");
+        }
+
+        VipPromoCode vipPromoCode = vipPromoCodeService.getByCode(promoCode);
+        if (ObjectUtil.isNull(vipPromoCode)) {
+            throw new SqxException("无效的推广码!");
+        }
+    }
+
+    @Override
+    public VipReduceVO getVipReduceInfo(Long userId, @Valid CanReduceQueryDTO canReduceQueryDTO) {
+        // 查询订单原始金额是否达到会员立减金额
+        CommonInfo vipPromotionMinAmount = commonInfoService.findOne(446);
+        if (canReduceQueryDTO.getOriginalPrice().compareTo(new BigDecimal(vipPromotionMinAmount.getValue())) < 0) {
+            return VipReduceVO.builder().reduceAmount(BigDecimal.ZERO)
+                    .canReduceFlag(Constant.NO)
+                    .vipReduceDesc("订单金额未达到会员立减金额")
+                    .build();
+        }
+
+        // 查询店铺是否参与会员立减
+        GoodsShop goodsShop = goodsShopService.getById(canReduceQueryDTO.getShopId());
+        if (ObjectUtil.isNull(goodsShop)) {
+            throw new SqxException("无效的店铺id!");
+        }
+        String goodsShopVipPromotion = goodsShop.getVipPromotion();
+        if (!StrUtil.equals(goodsShopVipPromotion, Constant.YES)) {
+            return VipReduceVO.builder()
+                    .reduceAmount(BigDecimal.ZERO)
+                    .canReduceFlag(Constant.NO)
+                    .vipReduceDesc("店铺未参与会员立减")
+                    .build();
+        }
+
+        // 查询用户是否为会员
+        UserEntity user = userService.getById(userId);
+        String vipFlag = ObjectUtil.isNotNull(user.getIsVip()) && user.getIsVip() == 1 && VipExpirationUtil.isVipValid(user.getVipExpirationTime())
+                ? Constant.YES : Constant.NO;
+        if (!StrUtil.equals(vipFlag, Constant.YES)) {
+            return VipReduceVO.builder().reduceAmount(BigDecimal.ZERO)
+                    .canReduceFlag(Constant.NO)
+                    .vipReduceDesc("用户非会员,不能立减")
+                    .build();
+        }
+
+        // 会员每天限制优惠单数(单)
+        int count = appOrderService.getCurDayVipPromotionByUserCount(userId);
+        CommonInfo vipPromotionCount = commonInfoService.findOne(445);
+        if (count >= Integer.parseInt(vipPromotionCount.getValue())) {
+            return VipReduceVO.builder().reduceAmount(BigDecimal.ZERO)
+                    .canReduceFlag(Constant.NO)
+                    .vipReduceDesc("会员当日优惠单数已达上限")
+                    .build();
+        }
+
+        // 会员每单立减金额(元)
+        CommonInfo vipPromotionAmount = commonInfoService.findOne(444);
+        BigDecimal vipPromotionAmountDecimal = new BigDecimal(vipPromotionAmount.getValue());
+        return  VipReduceVO.builder().reduceAmount(vipPromotionAmountDecimal)
+                .canReduceFlag(Constant.YES)
+                .vipReduceDesc("会员每单立减金额" + vipPromotionAmountDecimal + "元")
+                .build();
+    }
+
+    private void afterPaySuccess(Long userId) {
+        // 会员期限(天)
+        CommonInfo vipExpirationDays = commonInfoService.findOne(314);
+
+        // 会员赠送红包数量
+        CommonInfo vipRedPacketNum = commonInfoService.findOne(315);
+
+        // 会员赠送红包金额
+        CommonInfo vipRedPacketMoney = commonInfoService.findOne(316);
+
+        // 会员失效时间
+        String expirationTime = VipExpirationUtil.getFutureTimeWithDays(Integer.valueOf(vipExpirationDays.getValue()));
+
+        // 更新用户为会员
+        userService.updateUserToVip(userId, VipExpirationUtil.getFutureTimeWithDays(30));
+
+        // 新增会员专属优惠券
+        for(int i = 0; i<Integer.valueOf(vipRedPacketNum.getValue()); i++){
+            tbCouponUserService.addAfterVipBuySuccess(userId, new BigDecimal(vipRedPacketMoney.getValue()), vipExpirationDays.getValue(), expirationTime);
+        }
+    }
+}

+ 50 - 0
src/main/java/com/sqx/modules/member/vo/SpecialFavorStudentVO.java

@@ -0,0 +1,50 @@
+package com.sqx.modules.member.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+* 特殊照顾学生
+* @author : codingliang
+* @date : 2025-11-11
+*/
+@Data
+public class SpecialFavorStudentVO implements Serializable {
+   private static final long serialVersionUID = 1L;
+
+
+   @ApiModelProperty(value = "id")
+   @ExcelProperty("id")
+   private Long id;
+
+   @ApiModelProperty(value = "真实姓名")
+   private String name;
+
+   @ApiModelProperty(value = "学号")
+   private String studentNumber;
+
+   @ApiModelProperty(value = "验证状态;0未认证、1已认证")
+   private String verifyStatus;
+
+   @ApiModelProperty(value = "创建时间")
+   @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+   private Date createTime;
+
+   @ApiModelProperty(value = "验证用户id")
+   private Long verifyUserId;
+
+   @ApiModelProperty(value = "验证用户名")
+   private String verifyUserName;
+
+   @ApiModelProperty(value = "验证用户手机号")
+   private String verifyUserPhone;
+
+   @ApiModelProperty(value = "最后验证时间")
+   @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+   private Date lastVerifyTime;
+}

+ 42 - 0
src/main/java/com/sqx/modules/member/vo/VipPromoCodeVO.java

@@ -0,0 +1,42 @@
+package com.sqx.modules.member.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+* 会员推广码
+* @author : codingliang
+* @date : 2025-11-11
+*/
+@Data
+@ApiModel(description = "会员推广码")
+public class VipPromoCodeVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "id")
+    private Long id;
+
+    @ApiModelProperty(value = "推广人名称")
+    private String userName;
+
+    @ApiModelProperty(value = "推广码")
+    private String promoCode;
+
+    @ApiModelProperty(value = "推广人身份证号码")
+    private String idCard;
+
+    @ApiModelProperty(value = "推广人手机号码")
+    private String phone;
+
+    @ApiModelProperty(value = "推广人次")
+    private Integer promoCount;
+
+    @ApiModelProperty(value = "创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+}

+ 51 - 0
src/main/java/com/sqx/modules/member/vo/VipPromoRecordVO.java

@@ -0,0 +1,51 @@
+package com.sqx.modules.member.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+* 会员推广记录
+* @author : codingliang
+* @date : 2025-11-11
+*/
+@Data
+@ApiModel(description = "会员推广记录VO")
+public class VipPromoRecordVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "id")
+    private Long id;
+
+    @ApiModelProperty(value = "推广码id")
+    private Long promoCodeId;
+
+    @ApiModelProperty(value = "推广码")
+    private String promoCode;
+
+    @ApiModelProperty(value = "用户id")
+    private Long userId;
+    
+    @ApiModelProperty(value = "用户名称")
+    private String userName;
+
+    @ApiModelProperty(value = "用户手机号")
+    private String userPhone;
+    
+    @ApiModelProperty(value = "创建时间")
+    private Date createTime;
+
+    @ApiModelProperty(value = "支付类型;1微信支付、2余额支付、3暖心照顾")
+    private String payType;
+    
+    @ApiModelProperty(value = "支付金额")
+    private Double payAmount;
+
+    @ApiModelProperty(value = "会员过期时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date expireTime;
+}

+ 26 - 0
src/main/java/com/sqx/modules/member/vo/VipReduceVO.java

@@ -0,0 +1,26 @@
+package com.sqx.modules.member.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Builder;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * vip 立减信息
+ * @author codingliang
+ * @date 2025-11-16
+ */
+@Data
+@Builder
+public class VipReduceVO {
+
+    @ApiModelProperty(value = "用户是否可以会员立减")
+    private String canReduceFlag;
+
+    @ApiModelProperty(value = "立减金额")
+    private BigDecimal reduceAmount;
+
+    @ApiModelProperty(value = "立减描述")
+    private String vipReduceDesc;
+}

+ 7 - 0
src/main/java/com/sqx/modules/order/dao/AppOrderDao.java

@@ -15,6 +15,7 @@ import org.apache.ibatis.annotations.Param;
 import java.math.BigDecimal;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 import java.util.List;
 import java.util.List;
+import java.util.Map;
 
 
 @Mapper
 @Mapper
 public interface AppOrderDao extends BaseMapper<TbOrder> {
 public interface AppOrderDao extends BaseMapper<TbOrder> {
@@ -114,4 +115,10 @@ public interface AppOrderDao extends BaseMapper<TbOrder> {
     IPage<GoodsSkuSalesCountVO> getGoodsSkuSalesCount(Page<GoodsSkuSalesCountVO> pages, GoodsSkuQuery query);
     IPage<GoodsSkuSalesCountVO> getGoodsSkuSalesCount(Page<GoodsSkuSalesCountVO> pages, GoodsSkuQuery query);
 
 
     List<TbOrder> temp();
     List<TbOrder> temp();
+
+    /**
+     * 统计近近30天每个店铺的已完成的订单数量
+     * @return 店铺id-订单数量映射列表
+     */
+    List<Map<String, Object>> countFinishByShopIdWithLast30Days();
 }
 }

+ 13 - 10
src/main/java/com/sqx/modules/order/entity/TbOrder.java

@@ -66,7 +66,7 @@ public class TbOrder implements Serializable {
     @ApiModelProperty("订单类型 1上门 2外卖")
     @ApiModelProperty("订单类型 1上门 2外卖")
     private Integer orderType;
     private Integer orderType;
 
 
-    @ApiModelProperty("订单类型拓展 1上门 2骑手配送 3商家配送")
+    @ApiModelProperty("订单类型拓展 0上门堂食 1上门打包 2骑手配送 3商家配送")
     private Integer orderTypeExtra;
     private Integer orderTypeExtra;
 
 
     @ApiModelProperty("订单父id")
     @ApiModelProperty("订单父id")
@@ -135,6 +135,18 @@ public class TbOrder implements Serializable {
     @ApiModelProperty("打印状态  已打印:1 未打印:0")
     @ApiModelProperty("打印状态  已打印:1 未打印:0")
     private Integer isPrint;
     private Integer isPrint;
 
 
+    @ApiModelProperty("超时时间")
+    private Long timeOut;
+
+    @ApiModelProperty("身份证号")
+    private String idCard;
+
+    @ApiModelProperty("快跑者回调订单号")
+    private String tradeNo;
+
+    @ApiModelProperty("是否会员优惠 0否 1是")
+    private String vipPromotion;
+
     @ApiModelProperty("商铺名")
     @ApiModelProperty("商铺名")
     @TableField(exist = false)
     @TableField(exist = false)
     private String shopName;
     private String shopName;
@@ -267,9 +279,6 @@ public class TbOrder implements Serializable {
     @ApiModelProperty("站点名称")
     @ApiModelProperty("站点名称")
     private String stationName;
     private String stationName;
 
 
-    @ApiModelProperty("超时时间")
-    private Long timeOut;
-
     @ApiModelProperty("交易号")
     @ApiModelProperty("交易号")
     @TableField(exist = false)
     @TableField(exist = false)
     private String transactionId;
     private String transactionId;
@@ -291,10 +300,4 @@ public class TbOrder implements Serializable {
     @ApiModelProperty("完成订单时间")
     @ApiModelProperty("完成订单时间")
     @TableField(exist = false)
     @TableField(exist = false)
     private String finishTime;
     private String finishTime;
-
-    @ApiModelProperty("身份证号")
-    private String idCard;
-
-    @ApiModelProperty("快跑者回调订单号")
-    private String tradeNo;
 }
 }

+ 14 - 0
src/main/java/com/sqx/modules/order/service/AppOrderService.java

@@ -16,6 +16,7 @@ import com.sqx.modules.utils.excel.ExcelData;
 
 
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 import java.util.List;
 import java.util.List;
+import java.util.Map;
 
 
 public interface AppOrderService extends IService<TbOrder> {
 public interface AppOrderService extends IService<TbOrder> {
 
 
@@ -198,4 +199,17 @@ public interface AppOrderService extends IService<TbOrder> {
      * @param query 查询参数
      * @param query 查询参数
      */
      */
     void exportGoodsSkuSalesCount(GoodsSkuQuery query);
     void exportGoodsSkuSalesCount(GoodsSkuQuery query);
+
+     /**
+     * 查询用户当天会员优惠单数量
+     * @param userId 用户id
+     * @return 会员优惠单数量
+     */
+    int getCurDayVipPromotionByUserCount(Long userId);
+
+     /**
+      * 统计最近30天内每个店铺的订单完成数量
+      * @return 店铺id-订单完成数量映射
+      */
+    Map<Long, Integer> countFinishByShopIdWithLast30Days();
 }
 }

+ 110 - 19
src/main/java/com/sqx/modules/order/service/impl/AppAppOrderServiceImpl.java

@@ -103,6 +103,7 @@ import com.sqx.modules.shop.service.ShopTypeService;
 import com.sqx.modules.sys.entity.SysUserEntity;
 import com.sqx.modules.sys.entity.SysUserEntity;
 import com.sqx.modules.sys.service.SysUserService;
 import com.sqx.modules.sys.service.SysUserService;
 import com.sqx.modules.utils.SenInfoCheckUtil;
 import com.sqx.modules.utils.SenInfoCheckUtil;
+import com.sqx.modules.utils.VipExpirationUtil;
 import com.sqx.modules.utils.excel.EasyExcelUtil;
 import com.sqx.modules.utils.excel.EasyExcelUtil;
 import com.sqx.modules.utils.excel.ExcelData;
 import com.sqx.modules.utils.excel.ExcelData;
 import com.sqx.modules.utils.fieYun.FeiYunUtils;
 import com.sqx.modules.utils.fieYun.FeiYunUtils;
@@ -134,6 +135,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 
 @Service
 @Service
 @Slf4j
 @Slf4j
@@ -150,8 +152,6 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
     @Autowired
     @Autowired
     private UserService userService;
     private UserService userService;
     @Autowired
     @Autowired
-    private AppOrderService orderService;
-    @Autowired
     private PayDetailsService payDetailsService;
     private PayDetailsService payDetailsService;
     @Autowired
     @Autowired
     private OrderGoodsDao orderGoodsDao;
     private OrderGoodsDao orderGoodsDao;
@@ -499,9 +499,6 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
         // 给支付的时候商品描述用
         // 给支付的时候商品描述用
         parentOrder.setShopName(goodsShop.getShopName());
         parentOrder.setShopName(goodsShop.getShopName());
 
 
-        // // 设置订单类型
-        // parentOrder.setOrderType(payOrderDTO.getOrderType());
-
         // 校验订单类型
         // 校验订单类型
         checkOrderType(parentOrder, payOrderDTO, goodsShop);
         checkOrderType(parentOrder, payOrderDTO, goodsShop);
 
 
@@ -514,6 +511,9 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
         // 校验地址、配送费信息
         // 校验地址、配送费信息
         checkAddress(parentOrder, payOrderDTO.getAddressId(), goodsShop);
         checkAddress(parentOrder, payOrderDTO.getAddressId(), goodsShop);
 
 
+        // 校验是否参与vip优惠
+        checkVipPromotion(parentOrder, goodsShop, userId);
+
         // 检查活动优惠信息
         // 检查活动优惠信息
         checkActivity(payOrderDTO.getActivityId(), parentOrder);
         checkActivity(payOrderDTO.getActivityId(), parentOrder);
 
 
@@ -562,8 +562,10 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
             } else {
             } else {
                 order.setOrderTypeExtra(2);
                 order.setOrderTypeExtra(2);
             }
             }
-        } else {
-            order.setOrderTypeExtra(1);
+        }
+        // 其他 到店订单
+        else {
+            order.setOrderTypeExtra(payOrderDTO.getPackType());
         }
         }
 
 
         // 骑手配送订单
         // 骑手配送订单
@@ -601,6 +603,11 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
      * @param parentOrder 订单信息
      * @param parentOrder 订单信息
      */
      */
     private void checkActivity(Long activityId, TbOrder parentOrder) {
     private void checkActivity(Long activityId, TbOrder parentOrder) {
+        // 参加了会员优惠,则不参与活动优惠
+        if (StrUtil.equals(parentOrder.getVipPromotion(), Constant.YES)) {
+            return;
+        }
+
         OrderSuitActivityVO orderBestActivity = null;
         OrderSuitActivityVO orderBestActivity = null;
 
 
         // 获取当前订单适用的活动列表
         // 获取当前订单适用的活动列表
@@ -651,7 +658,7 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
             //减库存
             //减库存
             goodsShopRelevancy1.setInventory(goodsShopRelevancy.getInventory() - goodsNum);
             goodsShopRelevancy1.setInventory(goodsShopRelevancy.getInventory() - goodsNum);
             goodsShopRelevancyDao.updateById(goodsShopRelevancy1);
             goodsShopRelevancyDao.updateById(goodsShopRelevancy1);
-            goodsShopDao.updateShopSales(1, goodsNum, goodsShopRelevancy.getShopId());
+            // goodsShopDao.updateShopSales(1, goodsNum, goodsShopRelevancy.getShopId());
         }
         }
     }
     }
 
 
@@ -1220,7 +1227,12 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
                 OrderGoods orderGoods = orderGoodsList.get(a);
                 OrderGoods orderGoods = orderGoodsList.get(a);
                 BigDecimal goodsNum = new BigDecimal(orderGoods.getGoodsNum());
                 BigDecimal goodsNum = new BigDecimal(orderGoods.getGoodsNum());
                 BigDecimal goodsPrice = orderGoods.getGoodsPrice();
                 BigDecimal goodsPrice = orderGoods.getGoodsPrice();
-                BigDecimal goodsPacks = orderGoods.getGoodsPack();
+
+                // orderTypeExtra不为0时需要计算打包费,为0时不计算打包费
+                BigDecimal goodsPacks = BigDecimal.valueOf(0);
+                if (parentOrder.getOrderTypeExtra() != 0) {
+                    goodsPacks = orderGoods.getGoodsPack();
+                }
 
 
                 // 当前子订单总打包费
                 // 当前子订单总打包费
                 BigDecimal sumGoodsPack = goodsNum.multiply(goodsPacks);
                 BigDecimal sumGoodsPack = goodsNum.multiply(goodsPacks);
@@ -2007,7 +2019,7 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
                 goodsShopRelevancy1.setSales(goodsShopRelevancy.getSales() - goodsNum);//加销量
                 goodsShopRelevancy1.setSales(goodsShopRelevancy.getSales() - goodsNum);//加销量
                 goodsShopRelevancy1.setInventory(goodsShopRelevancy.getInventory() + goodsNum);//减库存
                 goodsShopRelevancy1.setInventory(goodsShopRelevancy.getInventory() + goodsNum);//减库存
                 goodsShopRelevancyDao.updateById(goodsShopRelevancy1);
                 goodsShopRelevancyDao.updateById(goodsShopRelevancy1);
-                goodsShopDao.updateShopSales(2, goodsNum, goodsShopRelevancy.getShopId());
+                // goodsShopDao.updateShopSales(2, goodsNum, goodsShopRelevancy.getShopId());
             }
             }
 
 
             return Result.success("取消订单成功!");
             return Result.success("取消订单成功!");
@@ -2228,14 +2240,16 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
         contentBuffer.append("平台服务费:").append(pingRate.setScale(2, BigDecimal.ROUND_DOWN)).append(",");
         contentBuffer.append("平台服务费:").append(pingRate.setScale(2, BigDecimal.ROUND_DOWN)).append(",");
         contentBuffer.append("短信服务费:").append(smsSendMoney.setScale(2, BigDecimal.ROUND_DOWN)).append(",");
         contentBuffer.append("短信服务费:").append(smsSendMoney.setScale(2, BigDecimal.ROUND_DOWN)).append(",");
         if (ObjectUtils.isNotEmpty(tbOrder.getOrderTypeExtra())&&tbOrder.getOrderTypeExtra()==2) {
         if (ObjectUtils.isNotEmpty(tbOrder.getOrderTypeExtra())&&tbOrder.getOrderTypeExtra()==2) {
-            //        配送费大于等于1.5就不需要骑手额外配送费
-//            if (tbOrder.getErrandMoney().doubleValue()<1.5) {
-                contentBuffer.append("骑手额外配送费:").append(rider.setScale(2, BigDecimal.ROUND_DOWN)).append(",");
-//            }
+            contentBuffer.append("骑手额外配送费:").append(rider.setScale(2, BigDecimal.ROUND_DOWN)).append(",");
         }
         }
-        contentBuffer.append("到账金额:").append(shopMoney.setScale(2, BigDecimal.ROUND_DOWN));
 
 
+        // 会员优惠
+        if (StrUtil.equals(tbOrder.getVipPromotion(), Constant.YES)) {
+            CommonInfo commonInfo = commonInfoService.findOne(444);
+            contentBuffer.append("会员优惠金额:").append(commonInfo.getValue()).append("元,");
+        }
 
 
+        contentBuffer.append("到账金额:").append(shopMoney.setScale(2, BigDecimal.ROUND_DOWN));
 
 
 
 
         if (shopIds == 0) {
         if (shopIds == 0) {
@@ -2519,7 +2533,7 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
                 goodsShopRelevancy1.setSales(goodsShopRelevancy.getSales() - goodsNum);//加销量
                 goodsShopRelevancy1.setSales(goodsShopRelevancy.getSales() - goodsNum);//加销量
                 goodsShopRelevancy1.setInventory(goodsShopRelevancy.getInventory() + goodsNum);//减库存
                 goodsShopRelevancy1.setInventory(goodsShopRelevancy.getInventory() + goodsNum);//减库存
                 goodsShopRelevancyDao.updateById(goodsShopRelevancy1);
                 goodsShopRelevancyDao.updateById(goodsShopRelevancy1);
-                goodsShopDao.updateShopSales(2, goodsNum, goodsShopRelevancy.getShopId());
+                // goodsShopDao.updateShopSales(2, goodsNum, goodsShopRelevancy.getShopId());
             }
             }
 
 
             // 取消跑腿订单
             // 取消跑腿订单
@@ -2677,7 +2691,7 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
                 goodsShopRelevancy1.setSales(goodsShopRelevancy.getSales() - goodsNum);//加销量
                 goodsShopRelevancy1.setSales(goodsShopRelevancy.getSales() - goodsNum);//加销量
                 goodsShopRelevancy1.setInventory(goodsShopRelevancy.getInventory() + goodsNum);//减库存
                 goodsShopRelevancy1.setInventory(goodsShopRelevancy.getInventory() + goodsNum);//减库存
                 goodsShopRelevancyDao.updateById(goodsShopRelevancy1);
                 goodsShopRelevancyDao.updateById(goodsShopRelevancy1);
-                goodsShopDao.updateShopSales(2, goodsNum, goodsShopRelevancy.getShopId());
+                // goodsShopDao.updateShopSales(2, goodsNum, goodsShopRelevancy.getShopId());
             }
             }
 
 
             // 打印退款小票
             // 打印退款小票
@@ -2817,7 +2831,7 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
                             tbOrder.setStatus(5);
                             tbOrder.setStatus(5);
                         } else if ("SUCCESS".equals(trade_state)) {
                         } else if ("SUCCESS".equals(trade_state)) {
                             tbOrder.setPayType(1);
                             tbOrder.setPayType(1);
-                            orderService.updateOrderAfterPaySuccess(tbOrder);
+                            updateOrderAfterPaySuccess(tbOrder);
                         }
                         }
                     } else {
                     } else {
                         RhtQrcodePayApi qrcodePay = new RhtQrcodePayApi(wechatMchConfig.getMchId(), wechatMchConfig.getMchKey(), RHT_PAY_BASE_URL);
                         RhtQrcodePayApi qrcodePay = new RhtQrcodePayApi(wechatMchConfig.getMchId(), wechatMchConfig.getMchKey(), RHT_PAY_BASE_URL);
@@ -2841,7 +2855,7 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
                                 log.error("超时任务处理订单【{}】支付成功,但未获取到支付订单!支付通知信息:{}", orderNumber, response2);
                                 log.error("超时任务处理订单【{}】支付成功,但未获取到支付订单!支付通知信息:{}", orderNumber, response2);
                             }
                             }
                             tbOrder.setPayType(1);
                             tbOrder.setPayType(1);
-                            orderService.updateOrderAfterPaySuccess(tbOrder);
+                            updateOrderAfterPaySuccess(tbOrder);
                         }
                         }
 
 
                     }
                     }
@@ -2972,6 +2986,34 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
         EasyExcelUtil.exportExcel(records, GoodsSkuSalesCountVO.class, "sku销售记录", "sheet1");
         EasyExcelUtil.exportExcel(records, GoodsSkuSalesCountVO.class, "sku销售记录", "sheet1");
     }
     }
 
 
+    @Override
+    public int getCurDayVipPromotionByUserCount(Long userId) {
+        // 查询用户当天会员优惠单数量
+        QueryWrapper<TbOrder> wrapper = new QueryWrapper<>();
+        wrapper.eq("user_id", userId)
+                .eq("vip_promotion", Constant.YES)
+                .eq("is_pay", Constant.YES)
+                // 8商家拒绝接单 5订单已取消 不纳入统计
+                .notIn("status", "5", "8")
+                .ge("pay_time", LocalDateTime.now().toLocalDate().atStartOfDay())
+                .le("pay_time", LocalDateTime.now().toLocalDate().atTime(23, 59, 59));
+        return count(wrapper);
+    }
+
+    @Override
+    public Map<Long, Integer> countFinishByShopIdWithLast30Days() {
+        // 统计近近30天每个店铺的已完成订单数量
+        List<Map<String, Object>> shopSalesList = baseMapper.countFinishByShopIdWithLast30Days();
+        // 转换为ShopId -> OrderCount的Map返回
+        return shopSalesList.stream()
+                .filter(map -> map.containsKey("shop_id") && map.containsKey("order_count"))
+                .filter(map -> map.get("shop_id") != null && map.get("order_count") != null)
+                .collect(Collectors.toMap(
+                        map -> Long.valueOf(map.get("shop_id").toString()),
+                        map -> Integer.valueOf(map.get("order_count").toString())
+                ));
+    }
+
     /**
     /**
      * 更新订单状态和支付顺序
      * 更新订单状态和支付顺序
      *
      *
@@ -2990,4 +3032,53 @@ public class AppAppOrderServiceImpl extends ServiceImpl<AppOrderDao, TbOrder> im
             lock.unlock();
             lock.unlock();
         }
         }
     }
     }
+
+    /**
+     * 校验是否参与vip优惠
+     * @param order 订单信息
+     * @param goodsShop 店铺信息
+     * @param userId 用户id
+     */
+    private void checkVipPromotion(TbOrder order, GoodsShop goodsShop, Long userId) {
+        // 检查店铺是否支持会员优惠
+        if (!StrUtil.equals(goodsShop.getVipPromotion(), Constant.YES)) {
+            return;
+        }
+
+        // 判断订单是否达到会员立减最低金额(元)
+        CommonInfo vipPromotionMinAmount = commonInfoService.findOne(446);
+        if (order.getPayMoney().compareTo(new BigDecimal(vipPromotionMinAmount.getValue())) < 0) {
+            return;
+        }
+
+        // 检查用户是否为会员,且会员是否过期
+        UserEntity user = userService.getById(userId);
+        if(ObjectUtil.isNotNull(user.getIsVip()) && user.getIsVip() == 1 && VipExpirationUtil.isVipValid(user.getVipExpirationTime())) {
+            // 查询用户当天会员优惠单数量
+            int count = getCurDayVipPromotionByUserCount(userId);
+
+            // 会员每天限制优惠单数(单)
+            CommonInfo vipPromotionCount = commonInfoService.findOne(445);
+            if (count >= Integer.parseInt(vipPromotionCount.getValue())) {
+                return;
+            }
+
+            // 会员每单立减金额(元)
+            CommonInfo vipPromotionAmount = commonInfoService.findOne(444);
+            BigDecimal payMoney = order.getPayMoney().subtract(new BigDecimal(vipPromotionAmount.getValue()));
+
+            //如果使用红包后,订单价格小于0,则改为0.01元
+            if (payMoney.doubleValue() <= 0) {
+                payMoney = new BigDecimal("0.01");
+            }
+
+            // 设置订单支付金额
+            order.setPayMoney(payMoney);
+
+            // 订单设置为vip优惠订单
+            order.setVipPromotion(Constant.YES);
+
+            log.info("preOrder==>[{}],订单参与会员优惠,优惠后金额为:{}元", order.getOrderId(), payMoney);
+        }
+    }
 }
 }

+ 4 - 19
src/main/java/com/sqx/modules/pay/controller/app/ApiWeiXinErrRiderPayController.java

@@ -4,6 +4,7 @@ import com.sqx.common.utils.Result;
 import com.sqx.modules.app.annotation.Login;
 import com.sqx.modules.app.annotation.Login;
 import com.sqx.modules.app.dao.UserDao;
 import com.sqx.modules.app.dao.UserDao;
 import com.sqx.modules.app.entity.UserEntity;
 import com.sqx.modules.app.entity.UserEntity;
+import com.sqx.modules.pay.dto.RiderCertificationDTO;
 import com.sqx.modules.pay.service.WxErrRiderService;
 import com.sqx.modules.pay.service.WxErrRiderService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
@@ -12,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
 import java.io.BufferedReader;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStream;
@@ -70,28 +72,11 @@ public class ApiWeiXinErrRiderPayController {
     @Login
     @Login
     @ApiOperation("小程序跑腿师傅实名认证")
     @ApiOperation("小程序跑腿师傅实名认证")
     @PostMapping("/wxPayJsApiRiderCertification/{type}")
     @PostMapping("/wxPayJsApiRiderCertification/{type}")
-    public Result wxPayJsApiRiderCertification(@RequestAttribute("userId") Long userId, @PathVariable("type") Integer type, @RequestBody UserEntity userEntity) throws Exception{
-        Integer userType = 2;
-        return wxService.wxPayJsApiRiderCertification(userId,type,userEntity, userType);
-    }
-
-    /*@Login
-    @ApiOperation("公众号跑腿师傅实名认证")
-    @PostMapping("/wxPayMpRiderCertification")
-    public Result wxPayMpRiderCertification(@RequestAttribute("userId") Long userId, @RequestBody UserEntity userEntity) throws Exception{
-        Integer userType = 2;
-        return wxService.wxPayJsApiRiderCertification(userId,2,userEntity, userType);
+    public Result wxPayJsApiRiderCertification(@RequestAttribute("userId") Long userId, @PathVariable("type") Integer type, @RequestBody @Valid RiderCertificationDTO dto) {
+        return wxService.wxPayJsApiRiderCertification(userId, dto);
     }
     }
 
 
     @Login
     @Login
-    @ApiOperation("app跑腿师傅实名认证")
-    @PostMapping("/appRiderCertification")
-    public Result appRiderCertification(@RequestAttribute("userId") Long userId, @RequestBody UserEntity userEntity) throws Exception{
-        Integer userType = 2;
-        return wxService.wxPayJsApiRiderCertification(userId,1,userEntity, userType);
-    }*/
-
-    @Login
     @ApiOperation("判断用户是否已实名认证成功")
     @ApiOperation("判断用户是否已实名认证成功")
     @GetMapping(value = "selectCertificationFlag")
     @GetMapping(value = "selectCertificationFlag")
     public Result selectCertificationFlag(@RequestAttribute Long userId){
     public Result selectCertificationFlag(@RequestAttribute Long userId){

+ 0 - 2
src/main/java/com/sqx/modules/pay/controller/app/ApiWeiXinPayController.java

@@ -67,7 +67,6 @@ public class ApiWeiXinPayController {
     @ApiOperation("余额购买会员")
     @ApiOperation("余额购买会员")
     @PostMapping(value = "balanceBuyVip")
     @PostMapping(value = "balanceBuyVip")
     public Result balanceBuyVip(@RequestAttribute Long userId){
     public Result balanceBuyVip(@RequestAttribute Long userId){
-
         return wxService.balanceBuyVip(userId);
         return wxService.balanceBuyVip(userId);
     }
     }
 
 
@@ -75,7 +74,6 @@ public class ApiWeiXinPayController {
     @ApiOperation("微信支付宝购买会员")
     @ApiOperation("微信支付宝购买会员")
     @PostMapping(value = "wxPayJsApiBuyVip")
     @PostMapping(value = "wxPayJsApiBuyVip")
     public Result wxPayJsApiBuyVip(@RequestAttribute Long userId, Integer type) throws Exception {
     public Result wxPayJsApiBuyVip(@RequestAttribute Long userId, Integer type) throws Exception {
-
         return wxService.wxPayJsApiBuyVip(userId, type);
         return wxService.wxPayJsApiBuyVip(userId, type);
     }
     }
 
 

+ 4 - 0
src/main/java/com/sqx/modules/pay/dto/GetPayParamDTO.java

@@ -48,4 +48,8 @@ public class GetPayParamDTO {
      * 支付场景
      * 支付场景
      */
      */
     private PaySceneEnum paySceneEnum;
     private PaySceneEnum paySceneEnum;
+    /**
+     * 额外参数
+     */
+    private String extra;
 }
 }

+ 8 - 0
src/main/java/com/sqx/modules/pay/dto/PayOrderDTO.java

@@ -5,6 +5,8 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 import org.springframework.format.annotation.DateTimeFormat;
 
 
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Pattern;
 import javax.validation.constraints.Pattern;
@@ -34,6 +36,12 @@ public class PayOrderDTO {
     @NotNull(message = "订单类型不能为空")
     @NotNull(message = "订单类型不能为空")
     private Integer orderType;
     private Integer orderType;
 
 
+    @ApiModelProperty("打包类型 0堂食 1打包")
+    @NotNull(message = "打包类型不能为空")
+    @Max(value = 1, message = "打包类型只能为0或1")
+    @Min(value = 0, message = "打包类型只能为0或1")
+    private Integer packType;
+
     @ApiModelProperty("活动id")
     @ApiModelProperty("活动id")
     private Long activityId;
     private Long activityId;
 
 

+ 42 - 0
src/main/java/com/sqx/modules/pay/dto/RiderCertificationDTO.java

@@ -0,0 +1,42 @@
+package com.sqx.modules.pay.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * 骑手认证dto
+ * @author codingliang
+ * @date 2025-11-25
+ */
+@Data
+@ApiModel(value = "RiderCertificationDTO", description = "骑手认证dto")
+public class RiderCertificationDTO {
+
+    @ApiModelProperty("用户名")
+    @NotBlank(message = "用户名不能为空")
+    private String userName;
+
+    @ApiModelProperty("证件号码")
+    @NotBlank(message = "证件号码不能为空")
+    private String identityCardNumber;
+
+    @ApiModelProperty("身份证正面图片")
+    @NotBlank(message = "身份证正面图片不能为空")
+    private String identityCardFront;
+
+    @ApiModelProperty("身份证反面图片")
+    @NotBlank(message = "身份证反面图片不能为空")
+    private String identityCardVerso;
+
+    @ApiModelProperty("手持身份证正面图片")
+    @NotBlank(message = "手持身份证正面图片不能为空")
+    private String selfIdentityCard;
+
+    @ApiModelProperty("站点id")
+    @NotNull(message = "站点id不能为空")
+    private Integer riderStationId;
+}

+ 5 - 0
src/main/java/com/sqx/modules/pay/entity/PayDetails.java

@@ -74,6 +74,11 @@ public class PayDetails implements Serializable {
      */
      */
     private String remark;
     private String remark;
 
 
+     /**
+     * 额外备用参数
+     */
+    private String extra;
+
     /**
     /**
      * 支付系统交易订单号
      * 支付系统交易订单号
      */
      */

+ 2 - 2
src/main/java/com/sqx/modules/pay/service/WxErrRiderService.java

@@ -1,7 +1,7 @@
 package com.sqx.modules.pay.service;
 package com.sqx.modules.pay.service;
 
 
 import com.sqx.common.utils.Result;
 import com.sqx.common.utils.Result;
-import com.sqx.modules.app.entity.UserEntity;
+import com.sqx.modules.pay.dto.RiderCertificationDTO;
 import com.sqx.modules.pay.entity.PayDetails;
 import com.sqx.modules.pay.entity.PayDetails;
 
 
 import java.math.BigDecimal;
 import java.math.BigDecimal;
@@ -17,7 +17,7 @@ public interface WxErrRiderService {
 
 
     Result payOrder(Long userId, String indentNumber, Integer type, Integer userType) throws Exception;
     Result payOrder(Long userId, String indentNumber, Integer type, Integer userType) throws Exception;
 
 
-    Result wxPayJsApiRiderCertification(Long userId,Integer type, UserEntity userEntity, Integer userType) throws  Exception;
+    Result wxPayJsApiRiderCertification(Long userId, RiderCertificationDTO dto);
 
 
     String payBack(String resXml,Integer type);;
     String payBack(String resXml,Integer type);;
 
 

+ 23 - 60
src/main/java/com/sqx/modules/pay/service/impl/NewPayServiceImpl.java

@@ -4,8 +4,6 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
 import cn.hutool.json.JSONUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.ekyong.www.pay.common.Constant;
 import com.ekyong.www.pay.common.Constant;
 import com.ekyong.www.pay.pay.qrcode.api.RhtQrcodePayApi;
 import com.ekyong.www.pay.pay.qrcode.api.RhtQrcodePayApi;
 import com.ekyong.www.pay.pay.qrcode.bean.QrcodeOpenPayRequestBean;
 import com.ekyong.www.pay.pay.qrcode.bean.QrcodeOpenPayRequestBean;
@@ -18,43 +16,14 @@ import com.ekyong.www.pay.pay.split.bean.SplitPayResponseBean;
 import com.ekyong.www.pay.util.SignUtil;
 import com.ekyong.www.pay.util.SignUtil;
 import com.sqx.common.exception.SqxException;
 import com.sqx.common.exception.SqxException;
 import com.sqx.common.utils.SpringContextUtils;
 import com.sqx.common.utils.SpringContextUtils;
-import com.sqx.modules.activity.service.ActivityPartRecordService;
-import com.sqx.modules.activity.service.ActivityService;
-import com.sqx.modules.address.entity.Address;
-import com.sqx.modules.address.service.AddressService;
 import com.sqx.modules.app.bo.UpdateMoneyBO;
 import com.sqx.modules.app.bo.UpdateMoneyBO;
-import com.sqx.modules.app.dao.UserBrowseDao;
-import com.sqx.modules.app.dao.UserDao;
-import com.sqx.modules.app.dao.UserMoneyDao;
-import com.sqx.modules.app.dao.UserMoneyDetailsDao;
 import com.sqx.modules.app.service.UserMoneyService;
 import com.sqx.modules.app.service.UserMoneyService;
-import com.sqx.modules.app.service.UserService;
 import com.sqx.modules.common.service.CommonInfoService;
 import com.sqx.modules.common.service.CommonInfoService;
-import com.sqx.modules.coupon.dao.TbCouponUserDao;
-import com.sqx.modules.datacentre.service.DataCentreService;
-import com.sqx.modules.errand.dao.TbIndentDao;
-import com.sqx.modules.errand.service.TbIndentService;
-import com.sqx.modules.errand.service.TbIndentSmsSendLogService;
-import com.sqx.modules.errand.service.TbIndentSmsTemplateService;
-import com.sqx.modules.goods.dao.GoodsDao;
-import com.sqx.modules.goods.dao.GoodsShopDao;
-import com.sqx.modules.goods.dao.GoodsShopRelevancyDao;
-import com.sqx.modules.goods.dao.GoodsSkuDao;
-import com.sqx.modules.goods.entity.GoodsShop;
 import com.sqx.modules.goods.service.GoodsShopService;
 import com.sqx.modules.goods.service.GoodsShopService;
-import com.sqx.modules.integral.dao.UserIntegralDao;
-import com.sqx.modules.integral.dao.UserIntegralDetailsDao;
-import com.sqx.modules.message.dao.MessageInfoDao;
-import com.sqx.modules.order.dao.AppOrderDao;
-import com.sqx.modules.order.dao.EvaluateDao;
-import com.sqx.modules.order.dao.OrderGoodsDao;
-import com.sqx.modules.order.entity.OrderGoods;
+import com.sqx.modules.member.service.VipService;
 import com.sqx.modules.order.entity.TbOrder;
 import com.sqx.modules.order.entity.TbOrder;
 import com.sqx.modules.order.service.AppOrderService;
 import com.sqx.modules.order.service.AppOrderService;
-import com.sqx.modules.order.service.EvaluateRiderService;
 import com.sqx.modules.pay.config.WechatPayConfig;
 import com.sqx.modules.pay.config.WechatPayConfig;
-import com.sqx.modules.pay.controller.app.AliPayController;
-import com.sqx.modules.pay.dao.PayDetailsDao;
 import com.sqx.modules.pay.dto.GetPayParamDTO;
 import com.sqx.modules.pay.dto.GetPayParamDTO;
 import com.sqx.modules.pay.entity.PayDetails;
 import com.sqx.modules.pay.entity.PayDetails;
 import com.sqx.modules.pay.enums.PayChannelEnum;
 import com.sqx.modules.pay.enums.PayChannelEnum;
@@ -62,32 +31,18 @@ import com.sqx.modules.pay.enums.PaySceneEnum;
 import com.sqx.modules.pay.enums.PayStateEnums;
 import com.sqx.modules.pay.enums.PayStateEnums;
 import com.sqx.modules.pay.service.NewPayService;
 import com.sqx.modules.pay.service.NewPayService;
 import com.sqx.modules.pay.service.PayDetailsService;
 import com.sqx.modules.pay.service.PayDetailsService;
-import com.sqx.modules.pay.service.WxErrService;
 import com.sqx.modules.pay.vo.WechatTransactionsParamVO;
 import com.sqx.modules.pay.vo.WechatTransactionsParamVO;
-import com.sqx.modules.shop.service.ShopMessageService;
-import com.sqx.modules.shop.service.ShopTypeService;
-import com.sqx.modules.sys.service.SysUserService;
 import lombok.RequiredArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.util.EntityUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.PlatformTransactionManager;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
 
 
 import java.math.BigDecimal;
 import java.math.BigDecimal;
 import java.net.URLDecoder;
 import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
 import java.time.Duration;
 import java.time.Duration;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatter;
 import java.util.Arrays;
 import java.util.Arrays;
-import java.util.List;
 import java.util.Map;
 import java.util.Map;
 
 
 @Slf4j
 @Slf4j
@@ -99,7 +54,6 @@ public class NewPayServiceImpl implements NewPayService {
     private final CommonInfoService commonInfoService;
     private final CommonInfoService commonInfoService;
     private final UserMoneyService userMoneyService;
     private final UserMoneyService userMoneyService;
     private final GoodsShopService goodsShopService;
     private final GoodsShopService goodsShopService;
-    private final DataCentreService dataCentreService;
 
 
     /**
     /**
      * 润海通支付接口地址
      * 润海通支付接口地址
@@ -132,7 +86,7 @@ public class NewPayServiceImpl implements NewPayService {
             return JSONUtil.toBean(payDetails.getRemark(), WechatTransactionsParamVO.class);
             return JSONUtil.toBean(payDetails.getRemark(), WechatTransactionsParamVO.class);
         }
         }
 
 
-        WechatPayConfig wechatMchConfig = getWechatMchConfig();
+        WechatPayConfig wechatMchConfig = getWechatMchConfig(dto);
         RhtQrcodePayApi qrcodePay = new RhtQrcodePayApi(wechatMchConfig.getMchId(), wechatMchConfig.getMchKey(), RHT_PAY_BASE_URL);
         RhtQrcodePayApi qrcodePay = new RhtQrcodePayApi(wechatMchConfig.getMchId(), wechatMchConfig.getMchKey(), RHT_PAY_BASE_URL);
         QrcodeOpenPayRequestBean openRequest = getQrcodeOpenPayRequestBean(dto, wechatMchConfig);
         QrcodeOpenPayRequestBean openRequest = getQrcodeOpenPayRequestBean(dto, wechatMchConfig);
 
 
@@ -183,7 +137,7 @@ public class NewPayServiceImpl implements NewPayService {
 
 
     @Override
     @Override
     public boolean wechatRefund(String orderNo) {
     public boolean wechatRefund(String orderNo) {
-        WechatPayConfig wechatMchConfig = getWechatMchConfig();
+        WechatPayConfig wechatMchConfig = getWechatMchConfig(null);
         RhtQrcodePayApi qrcodePay = new RhtQrcodePayApi(wechatMchConfig.getMchId(), wechatMchConfig.getMchKey(), RHT_PAY_BASE_URL);
         RhtQrcodePayApi qrcodePay = new RhtQrcodePayApi(wechatMchConfig.getMchId(), wechatMchConfig.getMchKey(), RHT_PAY_BASE_URL);
         QrcodeRefundRequestBean request = new QrcodeRefundRequestBean();
         QrcodeRefundRequestBean request = new QrcodeRefundRequestBean();
         // 商户流水号
         // 商户流水号
@@ -208,7 +162,7 @@ public class NewPayServiceImpl implements NewPayService {
 
 
     @Override
     @Override
     public void wechatSplitBill(String traceNo, String inMchId, BigDecimal amount) {
     public void wechatSplitBill(String traceNo, String inMchId, BigDecimal amount) {
-        WechatPayConfig wechatMchConfig = getWechatMchConfig();
+        WechatPayConfig wechatMchConfig = getWechatMchConfig(null);
         RhtSplitApi splitApi = new RhtSplitApi(wechatMchConfig.getMchId(), wechatMchConfig.getMchKey(), RHT_PAY_BASE_URL);
         RhtSplitApi splitApi = new RhtSplitApi(wechatMchConfig.getMchId(), wechatMchConfig.getMchKey(), RHT_PAY_BASE_URL);
 
 
         String outAmount = amount.toString();
         String outAmount = amount.toString();
@@ -303,9 +257,8 @@ public class NewPayServiceImpl implements NewPayService {
      * @param payDetails
      * @param payDetails
      */
      */
     private void handleVipPaySuccess(PayDetails payDetails) {
     private void handleVipPaySuccess(PayDetails payDetails) {
-        dataCentreService.presenterVip(payDetails.getUserId());
-
-        // 改动钱包明细??
+        VipService vipService = SpringContextUtils.getBean(VipService.class);
+        vipService.paySuccess(payDetails);
     }
     }
 
 
     /**
     /**
@@ -351,12 +304,22 @@ public class NewPayServiceImpl implements NewPayService {
      * 获取微信支付商户配置
      * 获取微信支付商户配置
      * @return 商户配置
      * @return 商户配置
      */
      */
-    private WechatPayConfig getWechatMchConfig() {
-        return WechatPayConfig.builder()
-                .appId(commonInfoService.findOne(45).getValue())
-                .mchId(commonInfoService.findOne(434).getValue())
+    private WechatPayConfig getWechatMchConfig(GetPayParamDTO dto) {
+        WechatPayConfig.WechatPayConfigBuilder builder = WechatPayConfig.builder();
+
+        // 保证金缴纳场景,使用商户端小程序appId
+        if (ObjectUtil.isNotNull(dto) && PaySceneEnum.BOND_PAY == dto.getPaySceneEnum()) {
+            builder.appId(commonInfoService.findOne(305).getValue());
+        }
+        // 其他支付场景,使用客户端appId
+        else {
+            builder.appId(commonInfoService.findOne(45).getValue());
+        }
+
+        builder.mchId(commonInfoService.findOne(434).getValue())
                 .mchKey(commonInfoService.findOne(435).getValue())
                 .mchKey(commonInfoService.findOne(435).getValue())
-                .h5Url(commonInfoService.findOne(19).getValue())
-                .build();
+                .h5Url(commonInfoService.findOne(19).getValue());
+
+        return builder.build();
     }
     }
-}
+}

+ 1 - 0
src/main/java/com/sqx/modules/pay/service/impl/PayDetailsServiceImpl.java

@@ -104,6 +104,7 @@ public class PayDetailsServiceImpl extends ServiceImpl<PayDetailsDao, PayDetails
         payDetails.setClassify(dto.getPaySceneEnum().getSceneCode());
         payDetails.setClassify(dto.getPaySceneEnum().getSceneCode());
         payDetails.setType(dto.getPayChannel().getCode());
         payDetails.setType(dto.getPayChannel().getCode());
         payDetails.setRemark(payParam);
         payDetails.setRemark(payParam);
+        payDetails.setExtra(dto.getExtra());
         payDetailsDao.insert(payDetails);
         payDetailsDao.insert(payDetails);
     }
     }
 
 

+ 28 - 25
src/main/java/com/sqx/modules/pay/service/impl/WxErrRiderServiceImpl.java

@@ -1,13 +1,16 @@
 package com.sqx.modules.pay.service.impl;
 package com.sqx.modules.pay.service.impl;
 
 
-import com.alibaba.fastjson.JSONObject;
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
 import com.github.wxpay.sdk.WXPay;
 import com.github.wxpay.sdk.WXPay;
 import com.github.wxpay.sdk.WXPayConstants;
 import com.github.wxpay.sdk.WXPayConstants;
 import com.github.wxpay.sdk.WXPayUtil;
 import com.github.wxpay.sdk.WXPayUtil;
+import com.sqx.common.exception.SqxException;
+import com.sqx.common.utils.Constant;
 import com.sqx.common.utils.Result;
 import com.sqx.common.utils.Result;
 import com.sqx.modules.app.dao.UserDao;
 import com.sqx.modules.app.dao.UserDao;
 import com.sqx.modules.app.entity.UserEntity;
 import com.sqx.modules.app.entity.UserEntity;
-import com.sqx.modules.app.entity.UserMoneyDetails;
 import com.sqx.modules.app.service.UserMoneyDetailsService;
 import com.sqx.modules.app.service.UserMoneyDetailsService;
 import com.sqx.modules.app.service.UserService;
 import com.sqx.modules.app.service.UserService;
 import com.sqx.modules.common.entity.CommonInfo;
 import com.sqx.modules.common.entity.CommonInfo;
@@ -17,6 +20,7 @@ import com.sqx.modules.errand.service.TbIndentService;
 import com.sqx.modules.pay.config.WXConfig;
 import com.sqx.modules.pay.config.WXConfig;
 import com.sqx.modules.pay.controller.app.AliPayController;
 import com.sqx.modules.pay.controller.app.AliPayController;
 import com.sqx.modules.pay.dao.PayDetailsDao;
 import com.sqx.modules.pay.dao.PayDetailsDao;
+import com.sqx.modules.pay.dto.RiderCertificationDTO;
 import com.sqx.modules.pay.entity.PayDetails;
 import com.sqx.modules.pay.entity.PayDetails;
 import com.sqx.modules.pay.service.WxErrRiderService;
 import com.sqx.modules.pay.service.WxErrRiderService;
 import com.sqx.modules.pay.service.WxService;
 import com.sqx.modules.pay.service.WxService;
@@ -104,36 +108,35 @@ public class WxErrRiderServiceImpl implements WxErrRiderService {
     }
     }
 
 
     @Override
     @Override
-    public Result wxPayJsApiRiderCertification(Long userId,Integer type, UserEntity userEntity, Integer userType) throws Exception {
+    public Result wxPayJsApiRiderCertification(Long userId, RiderCertificationDTO dto) {
+        UserEntity user = userService.getById(userId);
+        if(ObjectUtil.isNull(user)){
+            throw new SqxException("用户不存在!");
+        }
+
+        if (StrUtil.equals(Constant.YES, user.getCheckCertification())){
+            return Result.error("您已认证成功,无需重复认证!");
+        }
+
         CommonInfo isVerify = commonInfoService.findOne(260);
         CommonInfo isVerify = commonInfoService.findOne(260);
-        String generalOrder = getGeneralOrder();
         if("是".equals(isVerify.getValue())){
         if("是".equals(isVerify.getValue())){
-            String result = VerifyIdCardUtils.verifyIdCard(userEntity.getIdentityCardNumber(),userEntity.getUserName());
+            String result = VerifyIdCardUtils.verifyIdCard(dto.getIdentityCardNumber(),dto.getUserName());
             if(!"ok".equals(result)){
             if(!"ok".equals(result)){
                 return Result.error("您填写的信息有误,请检查后重试!");
                 return Result.error("您填写的信息有误,请检查后重试!");
             }
             }
         }
         }
-        userEntity.setUserId(userId);
-        userEntity.setCheckNumber(generalOrder);
-//        因为添加站点,所以需要更新tb_user表
-        userDao.updateById(userEntity);
 
 
-        CommonInfo one = commonInfoService.findOne(273);
-        double money = Double.parseDouble(one.getValue());
-        PayDetails payDetails = new PayDetails();
-        payDetails.setState(0);
-        payDetails.setCreateTime(sdf.format(new Date()));
-        payDetails.setOrderId(generalOrder);
-        payDetails.setUserId(userId);
-        payDetails.setMoney(money);
-        payDetails.setClassify(3);
-        payDetails.setType(type);
-        payDetails.setRemark(JSONObject.toJSONString(userEntity));
-        payDetailsDao.insert(payDetails);
-        if(type==4||type==5){
-            return aliPayController.aliRiderCertification(money, type, generalOrder);
-        }
-        return pay(money, type, userId, generalOrder,3, userType);
+        UserEntity newUser = new UserEntity();
+        BeanUtil.copyProperties(dto, newUser);
+        newUser.setUserId(userId);
+        // 2 骑手
+        newUser.setType(2);
+        // 设置为待审核状态
+        newUser.setCheckCertification(Constant.NO);
+        newUser.setCheckCertificationMessage("待审核");
+        userService.updateById(newUser);
+
+        return Result.success();
     }
     }
 
 
 
 

+ 8 - 62
src/main/java/com/sqx/modules/pay/service/impl/WxServiceImpl.java

@@ -179,8 +179,14 @@ public class WxServiceImpl implements WxService {
         if(userMoney.getMoney().doubleValue()<Double.valueOf(one.getValue())){
         if(userMoney.getMoney().doubleValue()<Double.valueOf(one.getValue())){
             return Result.error("余额不足!");
             return Result.error("余额不足!");
         }
         }
-        userMoneyService.updateMoney(2, userId, Double.valueOf(one.getValue()));
+
+        // 开通会员操作
         dataCentreService.presenterVip(userId);
         dataCentreService.presenterVip(userId);
+
+        // 扣除用户余额
+        userMoneyService.updateMoney(2, userId, Double.valueOf(one.getValue()));
+
+        // 添加用户余额记录
         UserMoneyDetails userMoneyDetails = new UserMoneyDetails();
         UserMoneyDetails userMoneyDetails = new UserMoneyDetails();
         userMoneyDetails.setUserId(userId);
         userMoneyDetails.setUserId(userId);
         userMoneyDetails.setTitle("用户开通会员");
         userMoneyDetails.setTitle("用户开通会员");
@@ -805,64 +811,6 @@ public class WxServiceImpl implements WxService {
         }
         }
     }
     }
 
 
-
-    /*@Override
-    public boolean refund(Orders orders) {
-        WXConfigUtil config = null;
-        try {
-            config = new WXConfigUtil();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        int commInfoId = 0;
-        Integer payWay = null;
-        //orders.getPayWay(); //支付方式(1app微信 2微信公众号 3微信小程序 4app支付宝 5H5支付宝 6零钱)
-        switch (payWay) {
-            case 1:
-                commInfoId = 5;
-                break; //appId
-            case 2:
-                commInfoId = 74;
-                break; //公众号id
-            case 3:
-                commInfoId = 45;
-                break; //小程序id
-        }
-        config.setAppId(commonInfoService.findOne(commInfoId).getValue());
-        config.setKey(commonInfoService.findOne(75).getValue());
-        config.setMchId(commonInfoService.findOne(76).getValue());
-        WXPay wxpay = new WXPay(config);
-        Map<String, String> data = new HashMap<>();
-        data.put("appid", config.getAppID());
-        data.put("mch_id", config.getMchID());
-        data.put("nonce_str", WXPayUtil.generateNonceStr());
-        try {
-            data.put("sign", WXPayUtil.generateSignature(data, config.getKey(), WXPayConstants.SignType.MD5));
-        } catch (Exception e) {
-            e.printStackTrace();
-            return false;
-        }
-        data.put("out_trade_no", orders.getOrdersNo()); //订单号,支付单号一致
-        data.put("out_refund_no", orders.getOrdersNo()); //退款单号,同一笔用不同的退款单号
-        double total_fee = 0.00;
-        data.put("total_fee", new Double(orders.getPayMoney().doubleValue() * 100).intValue() + ""); //1块等于微信支付传入100);
-        data.put("refund_fee", new Double(orders.getPayMoney().doubleValue() * 100).intValue() + ""); //1块等于微信支付传入100);
-        //使用官方API退款
-        try {
-            Map<String, String> response = wxpay.refund(data);
-            if ("SUCCESS".equals(response.get("return_code"))) {//主要返回以下5个参数
-                System.err.println("退款成功");
-                return true;
-            } else {
-                return false;
-            }
-        } catch (Exception e) {
-            log.info("返回");
-            e.printStackTrace();
-            return false;
-        }
-    }*/
-
     @Override
     @Override
     public boolean wxRefund(PayDetails payDetails){
     public boolean wxRefund(PayDetails payDetails){
         WXConfigUtil config = null;
         WXConfigUtil config = null;
@@ -913,6 +861,4 @@ public class WxServiceImpl implements WxService {
             return false;
             return false;
         }
         }
     }
     }
-
-
-}
+}

+ 2 - 0
src/main/java/com/sqx/modules/printInfo/entity/eOrderTypeExtra.java

@@ -55,6 +55,8 @@ public enum eOrderTypeExtra {
 
 
     public static String stringOf(Integer value) {
     public static String stringOf(Integer value) {
         switch (value) {
         switch (value) {
+            case 0:
+                return "到店堂食(不打包)";
             case 1:
             case 1:
                 return "到店取餐";
                 return "到店取餐";
             case 2:
             case 2:

+ 51 - 21
src/main/java/com/sqx/modules/shop/controller/app/ShopMoneyController.java

@@ -1,6 +1,9 @@
 package com.sqx.modules.shop.controller.app;
 package com.sqx.modules.shop.controller.app;
 
 
+import cn.hutool.core.bean.BeanUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.sqx.common.exception.SqxException;
 import com.sqx.common.utils.PageUtils;
 import com.sqx.common.utils.PageUtils;
 import com.sqx.common.utils.Result;
 import com.sqx.common.utils.Result;
 import com.sqx.modules.app.dao.UserDao;
 import com.sqx.modules.app.dao.UserDao;
@@ -14,14 +17,20 @@ import com.sqx.modules.goods.dao.GoodsShopDao;
 import com.sqx.modules.goods.entity.GoodsShop;
 import com.sqx.modules.goods.entity.GoodsShop;
 import com.sqx.modules.pay.controller.app.AliPayController;
 import com.sqx.modules.pay.controller.app.AliPayController;
 import com.sqx.modules.pay.controller.query.CashOutQueryDTO;
 import com.sqx.modules.pay.controller.query.CashOutQueryDTO;
+import com.sqx.modules.pay.dto.GetPayParamDTO;
+import com.sqx.modules.pay.enums.PayChannelEnum;
+import com.sqx.modules.pay.enums.PaySceneEnum;
 import com.sqx.modules.pay.service.CashOutService;
 import com.sqx.modules.pay.service.CashOutService;
+import com.sqx.modules.pay.service.NewPayService;
 import com.sqx.modules.pay.service.WxService;
 import com.sqx.modules.pay.service.WxService;
+import com.sqx.modules.pay.vo.WechatTransactionsParamVO;
 import com.sqx.modules.sys.controller.AbstractController;
 import com.sqx.modules.sys.controller.AbstractController;
 import com.sqx.modules.sys.dao.SysUserDao;
 import com.sqx.modules.sys.dao.SysUserDao;
 import com.sqx.modules.sys.entity.SysUserEntity;
 import com.sqx.modules.sys.entity.SysUserEntity;
+import icu.xuyijie.secureapi.annotation.DecryptParam;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -31,30 +40,24 @@ import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.bind.annotation.RestController;
 
 
 import java.math.BigDecimal;
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 
 
 @Api(tags={"商户端-商户钱包"})
 @Api(tags={"商户端-商户钱包"})
 @RestController
 @RestController
 @RequestMapping("/shop/shopmoney")
 @RequestMapping("/shop/shopmoney")
+@RequiredArgsConstructor
 public class ShopMoneyController extends AbstractController {
 public class ShopMoneyController extends AbstractController {
 
 
-    @Autowired
-    private UserMoneyService userMoneyService;
-    @Autowired
-    private UserMoneyDetailsService userMoneyDetailsService;
-    @Autowired
-    private UserDao userDao;
-    @Autowired
-    private CashOutService cashOutService;
-    @Autowired
-    private UserService userService;
-    @Autowired
-    private WxService wxService;
-    @Autowired
-    private SysUserDao sysUserDao;
-    @Autowired
-    private AliPayController aliPayController;
-    @Autowired
-    private GoodsShopDao goodsShopDao;
+    private final UserMoneyService userMoneyService;
+    private final UserMoneyDetailsService userMoneyDetailsService;
+    private final UserDao userDao;
+    private final CashOutService cashOutService;
+    private final UserService userService;
+    private final WxService wxService;
+    private final SysUserDao sysUserDao;
+    private final AliPayController aliPayController;
+    private final GoodsShopDao goodsShopDao;
+    private final NewPayService newPayService;
 
 
     @GetMapping("/selectShopMoney")
     @GetMapping("/selectShopMoney")
     @ApiOperation("商户钱包余额")
     @ApiOperation("商户钱包余额")
@@ -72,9 +75,36 @@ public class ShopMoneyController extends AbstractController {
         return Result.success().put("data", userMoneyService.selectUserMoneyByUserId(goodsShop.getUserId()));
         return Result.success().put("data", userMoneyService.selectUserMoneyByUserId(goodsShop.getUserId()));
     }
     }
 
 
-    @ApiOperation("商户缴纳保证金")
+    @ApiOperation("商户缴纳保证金(新)")
     @PostMapping(value = "shopCashDeposit")
     @PostMapping(value = "shopCashDeposit")
-    public Result shopCashDeposit(String openId, Double money,Integer type) throws Exception {
+    public Result shopCashDeposit(@DecryptParam(value = "openId") String openId, @DecryptParam(value = "money") BigDecimal money) {
+        SysUserEntity user = getUser();
+        Long adminUserId = user.getUserId();
+        SysUserShop sysUserShop = sysUserDao.selectUserShop(adminUserId);
+        GoodsShop goodsShop = goodsShopDao.selectById(sysUserShop.getShopId());
+        if(goodsShop.getStatus() != 1){
+            throw new SqxException("管理端审核成功后才能交保证金");
+        }
+
+        // 构建获取支付参数dto
+        GetPayParamDTO dto = GetPayParamDTO.builder()
+                .orderNo(IdWorker.getTimeId())
+                .orderDesc("墨轩商场-商户缴纳保证金")
+                .amount(money.setScale(2, RoundingMode.HALF_UP))
+                .shopId(goodsShop.getShopId())
+                .userThirdId(openId)
+                .payChannel(PayChannelEnum.WECHAT_JS_API)
+                .paySceneEnum(PaySceneEnum.BOND_PAY)
+                .build();
+
+        WechatTransactionsParamVO wechatTransactionsParamVO = newPayService.getWechatTransactionsParamVO(dto);
+
+        return Result.success(BeanUtil.beanToMap(wechatTransactionsParamVO, false, true));
+    }
+
+    @ApiOperation("商户缴纳保证金(废弃)")
+    @PostMapping(value = "shopCashDeposit-bak")
+    public Result shopCashDepositBak(String openId, Double money,Integer type) throws Exception {
         SysUserEntity user = getUser();
         SysUserEntity user = getUser();
         Long adminUserId = user.getUserId();
         Long adminUserId = user.getUserId();
         SysUserShop sysUserShop = sysUserDao.selectUserShop(adminUserId);
         SysUserShop sysUserShop = sysUserDao.selectUserShop(adminUserId);

+ 142 - 0
src/main/java/com/sqx/modules/utils/PromotionCodeUtil.java

@@ -0,0 +1,142 @@
+package com.sqx.modules.utils;
+
+/**
+ * 推荐码生成工具类
+ */
+public class PromotionCodeUtil {
+
+    /** 自定义进制字符集(避免使用易混淆的字符) */
+    private static final char[] r = new char[]{ 'M', 'J', 'U', 'D', 'Z', 'X', '9', 'C', '7', 'P',
+            'E', '8', '6', 'B', 'G', 'H', 'S', '2', '5', 'F',
+            'R', '4', 'Q', 'W', 'K', '3', 'V', 'Y', 'T', 'N'};
+
+    /** 进制长度 */
+    private static final int binLen = r.length;
+
+    /** 推荐码长度 */
+    private static final int codeLength = 6; // 8位长度
+
+    /** 用于生成唯一ID的锁对象 */
+    private static final Object lock = new Object();
+
+    /** 最后生成的时间戳,用于防止短时间内生成重复码 */
+    private static long lastTimestamp = -1L;
+
+    /** 序列号,用于同一毫秒内生成多个码时保证唯一性 */
+    private static long sequence = 0L;
+
+    /** 序列号最大值 */
+    private static final long MAX_SEQUENCE = 99999L;
+
+    /** 节点ID(在集群环境中非常重要) */
+    private static final int NODE_ID;
+
+    // 静态初始化块,初始化节点ID
+    static {
+        int nodeId1;
+        // 优先从环境变量获取节点ID
+        String nodeIdStr = System.getenv("NODE_ID");
+        if (nodeIdStr != null && !nodeIdStr.isEmpty()) {
+            try {
+                nodeId1 = Integer.parseInt(nodeIdStr) & 0x3F; // 限制在0-63之间
+            } catch (NumberFormatException e) {
+                nodeId1 = generateRandomNodeId();
+            }
+        } else {
+            // 如果没有配置,生成随机节点ID
+            nodeId1 = generateRandomNodeId();
+        }
+        NODE_ID = nodeId1;
+        System.out.println("当前服务器节点ID: " + NODE_ID);
+    }
+
+    /**
+     * 生成随机节点ID(当环境变量未配置时使用)
+     */
+    private static int generateRandomNodeId() {
+        // 使用服务器信息和当前时间生成相对唯一的节点ID
+        try {
+            String hostName = java.net.InetAddress.getLocalHost().getHostName();
+            int hashCode = hostName.hashCode();
+            // 结合当前时间戳的低8位,增加随机性
+            long timestamp = System.currentTimeMillis() & 0xFF;
+            return (Math.abs(hashCode) ^ (int)timestamp) & 0x3F; // 限制在0-63之间
+        } catch (Exception e) {
+            // 如果获取主机名失败,使用纯随机数
+            return (int)(Math.random() * 64);
+        }
+    }
+
+    /**
+     * 生成唯一推荐码(支持集群环境)
+     * @return 唯一的推荐码字符串
+     */
+    public static String generatePromotionCode() {
+        // 生成基础唯一数值
+        long uniqueValue = generateUniqueValue();
+
+        // 使用进制转换算法
+        StringBuilder sb = new StringBuilder();
+        while (uniqueValue > 0) {
+            int ind = (int) (uniqueValue % binLen);
+            sb.append(r[ind]);
+            uniqueValue = uniqueValue / binLen;
+        }
+
+        // 确保推荐码长度
+        String code = sb.toString();
+        if (code.length() < codeLength) {
+            // 使用随机字符填充前面
+            StringBuilder padding = new StringBuilder();
+            int paddingLength = codeLength - code.length();
+            for (int i = 0; i < paddingLength; i++) {
+                long randomSeed = System.nanoTime() + sequence;
+                int randomIndex = (int) (Math.abs(randomSeed) % binLen);
+                padding.append(r[randomIndex]);
+            }
+            code = padding.append(sb).toString();
+        } else if (code.length() > codeLength) {
+            // 如果超过长度,截取前codeLength位
+            code = code.substring(0, codeLength);
+        }
+
+        return code;
+    }
+
+    /**
+     * 生成唯一数值,结合时间戳、节点ID和序列号
+     * @return 唯一数值
+     */
+    private static long generateUniqueValue() {
+        synchronized (lock) {
+            long timestamp = System.currentTimeMillis();
+
+            // 如果是同一毫秒,序列号加1
+            if (timestamp == lastTimestamp) {
+                sequence++;
+                // 防止序列号溢出
+                if (sequence > MAX_SEQUENCE) {
+                    // 等待下一毫秒
+                    while (System.currentTimeMillis() <= timestamp) {
+                        Thread.yield();
+                    }
+                    timestamp = System.currentTimeMillis();
+                    sequence = 0L;
+                }
+            } else {
+                // 不同毫秒,序列号重置
+                sequence = 0L;
+            }
+
+            lastTimestamp = timestamp;
+
+            // 将节点ID纳入唯一性计算
+            // 格式:时间戳(41位) + 节点ID(6位) + 序列号(17位)
+            long result = (timestamp << 23);
+            result |= ((long)NODE_ID << 17);
+            result |= (sequence & 0x1FFFF); // 17位序列号
+
+            return Math.abs(result);
+        }
+    }
+}

+ 108 - 0
src/main/java/com/sqx/modules/utils/VipExpirationUtil.java

@@ -0,0 +1,108 @@
+package com.sqx.modules.utils;
+
+import com.sqx.common.exception.SqxException;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.time.temporal.ChronoUnit;
+
+/**
+ * VIP有效期校验工具类
+ * 提供VIP过期状态检查、剩余天数计算等功能
+ */
+public class VipExpirationUtil {
+    
+    /**
+     * VIP过期时间格式(yyyy-MM-dd HH:mm:ss)
+     */
+    public static final String VIP_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
+    
+    /**
+     * 日期时间格式化器
+     */
+    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(VIP_DATE_FORMAT);
+    
+    /**
+     * 检查VIP是否已过期
+     * @param vipExpirationTime VIP过期时间字符串(yyyy-MM-dd HH:mm:ss格式)
+     * @return 如果已过期返回true,否则返回false
+     * @throws SqxException 当时间格式错误时抛出
+     */
+    public static boolean isVipExpired(String vipExpirationTime) {
+        if (vipExpirationTime == null || vipExpirationTime.trim().isEmpty()) {
+            return true; // 空值视为已过期
+        }
+        try {
+            // 过期时间
+            LocalDateTime expirationDateTime = LocalDateTime.parse(vipExpirationTime, FORMATTER);
+            
+            return LocalDateTime.now().isAfter(expirationDateTime);
+        } catch (DateTimeParseException e) {
+            throw new SqxException("VIP过期时间格式错误,应为:" + VIP_DATE_FORMAT, e);
+        }
+    }
+    
+    /**
+     * 检查VIP是否在有效期内
+     * @param vipExpirationTime VIP过期时间字符串(yyyy-MM-dd HH:mm:ss格式)
+     * @return 如果在有效期内返回true,否则返回false
+     */
+    public static boolean isVipValid(String vipExpirationTime) {
+        return !isVipExpired(vipExpirationTime);
+    }
+    
+    /**
+     * 计算VIP剩余天数
+     * @param vipExpirationTime VIP过期时间字符串(yyyy-MM-dd HH:mm:ss格式)
+     * @return VIP剩余天数,如果已过期则返回负数
+     * @throws IllegalArgumentException 当时间格式错误时抛出
+     */
+    public static long getRemainingDays(String vipExpirationTime) {
+        if (vipExpirationTime == null || vipExpirationTime.trim().isEmpty()) {
+            return -1; // 空值视为已过期
+        }
+        
+        try {
+            // 过期时间
+            LocalDateTime expirationDateTime = LocalDateTime.parse(vipExpirationTime, FORMATTER);
+            
+            // 计算剩余天数
+            return ChronoUnit.DAYS.between(LocalDateTime.now(), expirationDateTime);
+            
+        } catch (DateTimeParseException e) {
+            throw new SqxException("VIP过期时间格式错误,应为:" + VIP_DATE_FORMAT, e);
+        }
+    }
+    
+    /**
+     * 格式化当前时间为VIP日期格式
+     * @return 格式化后的当前时间字符串
+     */
+    public static String formatCurrentTime() {
+        return FORMATTER.format(LocalDateTime.now());
+    }
+    
+    /**
+     * 格式化指定时间为VIP日期格式
+     * @param dateTime 要格式化的时间
+     * @return 格式化后的时间字符串
+     */
+    public static String formatDateTime(LocalDateTime dateTime) {
+        if (dateTime == null) {
+            return null;
+        }
+        return FORMATTER.format(dateTime);
+    }
+    
+    /**
+     * 获取指定天数后的时间并格式化为VIP日期格式
+     * 用于计算VIP有效期延长
+     * @param days 天数
+     * @return 格式化后的未来时间字符串
+     */
+    public static String getFutureTimeWithDays(int days) {
+        LocalDateTime futureDateTime = LocalDateTime.now().plusDays(days);
+        return FORMATTER.format(futureDateTime);
+    }
+}

+ 19 - 7
src/main/java/com/sqx/modules/utils/fieYun/FeiYunUtils.java

@@ -1,27 +1,35 @@
 package com.sqx.modules.utils.fieYun;
 package com.sqx.modules.utils.fieYun;
 
 
+import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.sqx.common.utils.Constant;
 import com.sqx.common.utils.Result;
 import com.sqx.common.utils.Result;
 import com.sqx.modules.activity.service.ActivityService;
 import com.sqx.modules.activity.service.ActivityService;
 import com.sqx.modules.activity.vo.ActivityOrderVO;
 import com.sqx.modules.activity.vo.ActivityOrderVO;
-import com.sqx.modules.activity.vo.ActivityVO;
 import com.sqx.modules.app.entity.UserEntity;
 import com.sqx.modules.app.entity.UserEntity;
 import com.sqx.modules.app.service.UserService;
 import com.sqx.modules.app.service.UserService;
 import com.sqx.modules.common.service.CommonInfoService;
 import com.sqx.modules.common.service.CommonInfoService;
 import com.sqx.modules.coupon.entity.TbCoupon;
 import com.sqx.modules.coupon.entity.TbCoupon;
-import com.sqx.modules.coupon.entity.TbCouponUser;
 import com.sqx.modules.coupon.service.TbCouponService;
 import com.sqx.modules.coupon.service.TbCouponService;
 import com.sqx.modules.goods.entity.GoodsShop;
 import com.sqx.modules.goods.entity.GoodsShop;
 import com.sqx.modules.goods.service.GoodsShopService;
 import com.sqx.modules.goods.service.GoodsShopService;
 import com.sqx.modules.order.entity.OrderGoods;
 import com.sqx.modules.order.entity.OrderGoods;
 import com.sqx.modules.order.entity.TbOrder;
 import com.sqx.modules.order.entity.TbOrder;
 import com.sqx.modules.order.service.AppOrderService;
 import com.sqx.modules.order.service.AppOrderService;
-import com.sqx.modules.printInfo.entity.*;
+import com.sqx.modules.printInfo.entity.PrintInfo;
+import com.sqx.modules.printInfo.entity.PrintInfoDetail;
+import com.sqx.modules.printInfo.entity.PrintInfoShop;
+import com.sqx.modules.printInfo.entity.PrintModelDetailResult;
+import com.sqx.modules.printInfo.entity.PrintModelResult;
+import com.sqx.modules.printInfo.entity.PrintModelTypeResult;
+import com.sqx.modules.printInfo.entity.eOrderStatus;
+import com.sqx.modules.printInfo.entity.eOrderTypeExtra;
+import com.sqx.modules.printInfo.entity.ePrintStatu;
+import com.sqx.modules.printInfo.entity.eWordSize;
 import com.sqx.modules.printInfo.service.PrintInfoDetailService;
 import com.sqx.modules.printInfo.service.PrintInfoDetailService;
 import com.sqx.modules.printInfo.service.PrintInfoService;
 import com.sqx.modules.printInfo.service.PrintInfoService;
 import com.sqx.modules.printInfo.service.PrintInfoShopService;
 import com.sqx.modules.printInfo.service.PrintInfoShopService;
-import com.sqx.modules.utils.fieYun.model.OrderForm;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.StringUtils;
@@ -990,12 +998,10 @@ public class FeiYunUtils {
                 stringBuilder.append("<BR>");
                 stringBuilder.append("<BR>");
 
 
                 stringBuilder.append("--------------------------------<BR>");
                 stringBuilder.append("--------------------------------<BR>");
-                BigDecimal packMoney = BigDecimal.ZERO;
+                BigDecimal packMoney = tbOrder.getPackMoney();
                 BigDecimal goodsMoney = BigDecimal.ZERO;
                 BigDecimal goodsMoney = BigDecimal.ZERO;
                 for (OrderGoods orderGoods : orderGoodsList) {
                 for (OrderGoods orderGoods : orderGoodsList) {
                     BigDecimal sumMoney = orderGoods.getGoodsPrice().multiply(BigDecimal.valueOf(orderGoods.getGoodsNum()));
                     BigDecimal sumMoney = orderGoods.getGoodsPrice().multiply(BigDecimal.valueOf(orderGoods.getGoodsNum()));
-                    BigDecimal sumPack = orderGoods.getGoodsPack().multiply(BigDecimal.valueOf(orderGoods.getGoodsNum()));
-                    packMoney = packMoney.add(sumPack);
                     goodsMoney = goodsMoney.add(sumMoney);
                     goodsMoney = goodsMoney.add(sumMoney);
                     String name;
                     String name;
                     if (StringUtils.isNotEmpty(orderGoods.getSkuMessage())) {
                     if (StringUtils.isNotEmpty(orderGoods.getSkuMessage())) {
@@ -1279,6 +1285,12 @@ public class FeiYunUtils {
                 stringBuilder.append(errand_money_start).append("跑腿费:").append(errandMoneyT).append("元").append(errand_money_end + "<BR>");
                 stringBuilder.append(errand_money_start).append("跑腿费:").append(errandMoneyT).append("元").append(errand_money_end + "<BR>");
                 //从这个表里拿优惠活动 activity_part_record 活动参与记录表
                 //从这个表里拿优惠活动 activity_part_record 活动参与记录表
                 stringBuilder.append(activity_title_start).append("优惠活动:").append(activity == null ? "" : activity.getTitle()).append(activity_title_end + "<BR>");
                 stringBuilder.append(activity_title_start).append("优惠活动:").append(activity == null ? "" : activity.getTitle()).append(activity_title_end + "<BR>");
+
+                // 会员优惠
+                if (StrUtil.equals(tbOrder.getVipPromotion(), Constant.YES)) {
+                    stringBuilder.append(activity_title_start).append("会员优惠:").append("-" + commonInfoService.findOne(444).getValue()).append("元").append(activity_title_end + "<BR>");
+                }
+
                 BigDecimal patMoney = tbOrder.getPayMoney().setScale(2, BigDecimal.ROUND_HALF_UP);
                 BigDecimal patMoney = tbOrder.getPayMoney().setScale(2, BigDecimal.ROUND_HALF_UP);
                 stringBuilder.append(pay_money_start).append("合计:").append(patMoney).append("元").append(pay_money_end + "<BR>");
                 stringBuilder.append(pay_money_start).append("合计:").append(patMoney).append("元").append(pay_money_end + "<BR>");
                 stringBuilder.append(payStringBuilder.toString());
                 stringBuilder.append(payStringBuilder.toString());

+ 5 - 0
src/main/java/com/sqx/scheduler/config/SchedulerLock.java

@@ -47,4 +47,9 @@ public interface SchedulerLock {
      * 用户优惠券自动过期锁
      * 用户优惠券自动过期锁
      */
      */
     String INTEGRAL_OF_USER_EXPIRATION_LOCK = "wm:lock:integral:exp";
     String INTEGRAL_OF_USER_EXPIRATION_LOCK = "wm:lock:integral:exp";
+
+    /**
+     * 更新店铺销量锁
+     */
+    String UPDATE_SHOP_SALES_LOCK = "wm:lock:shop:sales:update";
 }
 }

+ 107 - 11
src/main/java/com/sqx/scheduler/export/ExportScheduler.java

@@ -1,9 +1,10 @@
 package com.sqx.scheduler.export;
 package com.sqx.scheduler.export;
 
 
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
-import com.sqx.common.utils.Constant;
-import com.sqx.common.utils.Result;
+import com.sqx.common.utils.PageUtils;
 import com.sqx.common.utils.SftpUtil;
 import com.sqx.common.utils.SftpUtil;
 import com.sqx.modules.address.query.InsideAddressQuery;
 import com.sqx.modules.address.query.InsideAddressQuery;
 import com.sqx.modules.address.service.InsideAddressService;
 import com.sqx.modules.address.service.InsideAddressService;
@@ -18,6 +19,15 @@ import com.sqx.modules.datacentre.service.DataCentreService;
 import com.sqx.modules.exportExecl.dto.AccountEntry;
 import com.sqx.modules.exportExecl.dto.AccountEntry;
 import com.sqx.modules.exportExecl.model.ExportJob;
 import com.sqx.modules.exportExecl.model.ExportJob;
 import com.sqx.modules.exportExecl.service.ExportJobService;
 import com.sqx.modules.exportExecl.service.ExportJobService;
+import com.sqx.modules.member.query.SpecialFavorStudentQuery;
+import com.sqx.modules.member.query.VipPromoCodeQuery;
+import com.sqx.modules.member.query.VipPromoRecordQuery;
+import com.sqx.modules.member.service.SpecialFavorStudentService;
+import com.sqx.modules.member.service.VipPromoCodeService;
+import com.sqx.modules.member.service.VipPromoRecordService;
+import com.sqx.modules.member.vo.SpecialFavorStudentVO;
+import com.sqx.modules.member.vo.VipPromoCodeVO;
+import com.sqx.modules.member.vo.VipPromoRecordVO;
 import com.sqx.modules.order.dto.OrderQueryDto;
 import com.sqx.modules.order.dto.OrderQueryDto;
 import com.sqx.modules.order.service.AppOrderService;
 import com.sqx.modules.order.service.AppOrderService;
 import com.sqx.modules.pay.controller.query.CashOutQueryDTO;
 import com.sqx.modules.pay.controller.query.CashOutQueryDTO;
@@ -28,7 +38,6 @@ import com.sqx.modules.reconciliation.service.PlatformBillService;
 import com.sqx.modules.utils.excel.ExcelData;
 import com.sqx.modules.utils.excel.ExcelData;
 import com.sqx.modules.utils.excel.ExportExcelUtils;
 import com.sqx.modules.utils.excel.ExportExcelUtils;
 import com.sqx.scheduler.config.SchedulerLock;
 import com.sqx.scheduler.config.SchedulerLock;
-import io.swagger.annotations.ApiOperation;
 import lombok.RequiredArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.NotNull;
@@ -39,7 +48,6 @@ import org.springframework.scheduling.annotation.Async;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 import org.springframework.util.StringUtils;
 import org.springframework.util.StringUtils;
-import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayInputStream;
@@ -49,11 +57,14 @@ import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
 import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.time.ZoneId;
+import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.Date;
 import java.util.List;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 
 /**
 /**
  * 优惠券定时任务
  * 优惠券定时任务
@@ -78,9 +89,12 @@ public class ExportScheduler {
     private final UserMoneyDetailsService userMoneyDetailsService;
     private final UserMoneyDetailsService userMoneyDetailsService;
     private final DataCentreService dataCentreService;
     private final DataCentreService dataCentreService;
     private final PlatformBillService platformBillService;
     private final PlatformBillService platformBillService;
-
     private final InsideAddressService insideAddressService;
     private final InsideAddressService insideAddressService;
+    private final SpecialFavorStudentService specialFavorStudentService;
+    private final VipPromoRecordService vipPromoRecordService;
+    private final VipPromoCodeService vipPromoCodeService;
 
 
+    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
 
 
     /**
     /**
      * 将所有超过失效时间的优惠券改为失效状态
      * 将所有超过失效时间的优惠券改为失效状态
@@ -123,7 +137,8 @@ public class ExportScheduler {
                 InputStream inputStream=null;
                 InputStream inputStream=null;
                 ByteArrayOutputStream os = new ByteArrayOutputStream();
                 ByteArrayOutputStream os = new ByteArrayOutputStream();
                 try {
                 try {
-                    ExcelData excelData=new ExcelData();
+                    new ExcelData();
+                    ExcelData excelData;
                     if("order".equals(fileType)){
                     if("order".equals(fileType)){
                         excelData=getOrderExcelData(exportJob);
                         excelData=getOrderExcelData(exportJob);
                     }else if("recharge".equals(fileType)){
                     }else if("recharge".equals(fileType)){
@@ -146,7 +161,13 @@ public class ExportScheduler {
                         excelData=getPlatformBillExcelData(exportJob);
                         excelData=getPlatformBillExcelData(exportJob);
                     }else if ("shippingAddress".equals(fileType)){
                     }else if ("shippingAddress".equals(fileType)){
                         excelData=getShippingAddressExcelData(exportJob);
                         excelData=getShippingAddressExcelData(exportJob);
-                    }else{
+                    } else if("specialFavorStudent".equals(fileType)){
+                        excelData = getSpecialFavorStudentExcelData(exportJob);
+                    }else if("vipPromoRecord".equals(fileType)){
+                        excelData = getVipPromoRecordExcelData(exportJob);
+                    } else if ("vipPromoCode".equals(fileType)){
+                        excelData = getVipPromoCodeExcelData(exportJob);
+                    } else{
                         continue;
                         continue;
                     }
                     }
                     String value=commonInfoService.findOne(430).getValue();
                     String value=commonInfoService.findOne(430).getValue();
@@ -190,8 +211,83 @@ public class ExportScheduler {
         }
         }
     }
     }
 
 
+    private ExcelData getVipPromoCodeExcelData(ExportJob exportJob) {
+        VipPromoCodeQuery query = JSONUtil.toBean(exportJob.getConditions(), VipPromoCodeQuery.class);
+
+        ExcelData excelData = new ExcelData();
+        excelData.setName("会员推广码列表");
+        excelData.setTitles(Arrays.asList("推广人名称", "推广码", "推广人身份证号码", "推广人手机号码", "推广人次", "创建时间"));
+
+        PageUtils page = vipPromoCodeService.pages(query);
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        List<List<Object>> rows = page.getList().stream().map(e -> {
+            VipPromoCodeVO vo = (VipPromoCodeVO) e;
+            List<Object> row = new ArrayList<>();
+            row.add(vo.getUserName());
+            row.add(vo.getPromoCode());
+            row.add(vo.getIdCard());
+            row.add(vo.getPhone());
+            row.add(vo.getPromoCount());
+            row.add(ObjectUtils.isNull(vo.getCreateTime()) ? "" : sdf.format(vo.getCreateTime()));
+            return row;
+        }).collect(Collectors.toList());
+
+        excelData.setRows(rows);
+        return excelData;
+    }
+
+    private ExcelData getVipPromoRecordExcelData(ExportJob exportJob) {
+        VipPromoRecordQuery query = JSONUtil.toBean(exportJob.getConditions(), VipPromoRecordQuery.class);
+
+        ExcelData data = new ExcelData();
+        data.setName("特殊照顾学生列表");
+        data.setTitles(Arrays.asList("推广码id", "用户id", "用户名称", "用户手机号", "创建时间", "支付类型", "支付金额", "会员过期时间"));
+
+        PageUtils pages = vipPromoRecordService.pages(query);
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        List<List<Object>> rows = pages.getList().stream().map(e -> {
+            VipPromoRecordVO vo = (VipPromoRecordVO) e;
+            List<Object> row = new ArrayList<>();
+            row.add(vo.getPromoCodeId());
+            row.add(vo.getUserId());
+            row.add(vo.getUserName());
+            row.add(vo.getUserPhone());
+            row.add(ObjectUtils.isNull(vo.getCreateTime()) ? "" : sdf.format(vo.getCreateTime()));
+            row.add(StrUtil.equals(vo.getPayType(), "1") ? "微信支付" : (StrUtil.equals(vo.getPayType(), "2") ? "余额支付" : "暖心照顾"));
+            row.add(vo.getPayAmount());
+            row.add(ObjectUtils.isNull(vo.getExpireTime()) ? "" : sdf.format(vo.getExpireTime()));
+            return row;
+        }).collect(Collectors.toList());
+        data.setRows(rows);
+
+        return data;
+    }
+
+    private ExcelData getSpecialFavorStudentExcelData(ExportJob exportJob) {
+        SpecialFavorStudentQuery query = JSONUtil.toBean(exportJob.getConditions(), SpecialFavorStudentQuery.class);
+        ExcelData data = new ExcelData();
+        data.setName("特殊照顾学生列表");
+        data.setTitles(Arrays.asList("姓名", "学号", "验证状态", "创建时间", "验证用户名", "验证手机号", "验证时间"));
+        PageUtils pages = specialFavorStudentService.pages(query);
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        List<List<Object>> rows = pages.getList().stream().map(e -> {
+            SpecialFavorStudentVO vo = (SpecialFavorStudentVO) e;
+            List<Object> row = new ArrayList<>();
+            row.add(vo.getName());
+            row.add(vo.getStudentNumber());
+            row.add(StrUtil.equals(vo.getVerifyStatus(), "0") ? "未认证" : "已认证");
+            row.add(ObjectUtils.isNull(vo.getCreateTime()) ? "" : sdf.format(vo.getCreateTime()));
+            row.add(vo.getVerifyUserName());
+            row.add(vo.getVerifyUserPhone());
+            row.add(ObjectUtils.isNull(vo.getLastVerifyTime()) ? "" : sdf.format(vo.getLastVerifyTime()));
+            return row;
+        }).collect(Collectors.toList());
+        data.setRows(rows);
+
+        return data;
+    }
+
     private ExcelData getShippingAddressExcelData(ExportJob exportJob) {
     private ExcelData getShippingAddressExcelData(ExportJob exportJob) {
-        DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
         String[] conditions=exportJob.getConditions().split(",",-1);
         String[] conditions=exportJob.getConditions().split(",",-1);
         InsideAddressQuery query = new InsideAddressQuery();
         InsideAddressQuery query = new InsideAddressQuery();
         query.setAddressDetail(conditions[1]);
         query.setAddressDetail(conditions[1]);
@@ -200,12 +296,12 @@ public class ExportScheduler {
             query.setStationId(Long.valueOf(conditions[3]));
             query.setStationId(Long.valueOf(conditions[3]));
         }
         }
         if(!"".equals(conditions[4])){
         if(!"".equals(conditions[4])){
-            Date start = Date.from(LocalDateTime.parse(conditions[4], dateTimeFormatter1).atZone(ZoneId.systemDefault()).toInstant());
+            Date start = Date.from(LocalDateTime.parse(conditions[4], dateTimeFormatter).atZone(ZoneId.systemDefault()).toInstant());
             log.info("start:"+start);
             log.info("start:"+start);
             query.setStartTime(start);
             query.setStartTime(start);
         }
         }
         if(!"".equals(conditions[5])){
         if(!"".equals(conditions[5])){
-            Date end = Date.from(LocalDateTime.parse(conditions[5], dateTimeFormatter1).atZone(ZoneId.systemDefault()).toInstant());
+            Date end = Date.from(LocalDateTime.parse(conditions[5], dateTimeFormatter).atZone(ZoneId.systemDefault()).toInstant());
             query.setEndTime(end);
             query.setEndTime(end);
             log.info("end:"+end);
             log.info("end:"+end);
         }
         }
@@ -253,7 +349,7 @@ public class ExportScheduler {
             String start="";
             String start="";
             if (ObjectUtils.isNotEmpty(createTime)) {
             if (ObjectUtils.isNotEmpty(createTime)) {
                 LocalDateTime localDateTime = LocalDateTime.ofInstant(createTime.toInstant(), ZoneId.systemDefault());
                 LocalDateTime localDateTime = LocalDateTime.ofInstant(createTime.toInstant(), ZoneId.systemDefault());
-                start = localDateTime.format(dateTimeFormatter1);
+                start = localDateTime.format(dateTimeFormatter);
             }
             }
             row.add(start);
             row.add(start);
             rows.add(row);
             rows.add(row);

+ 30 - 5
src/main/java/com/sqx/scheduler/order/OrderScheduler.java

@@ -2,8 +2,6 @@ package com.sqx.scheduler.order;
 
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.ObjectUtil;
-import com.baomidou.mybatisplus.core.conditions.Wrapper;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.ekyong.www.pay.pay.qrcode.api.RhtQrcodePayApi;
 import com.ekyong.www.pay.pay.qrcode.api.RhtQrcodePayApi;
@@ -24,7 +22,6 @@ import com.sqx.modules.pay.service.PayDetailsService;
 import com.sqx.modules.shop.entity.ShopType;
 import com.sqx.modules.shop.entity.ShopType;
 import com.sqx.modules.shop.service.ShopTypeService;
 import com.sqx.modules.shop.service.ShopTypeService;
 import com.sqx.scheduler.config.SchedulerLock;
 import com.sqx.scheduler.config.SchedulerLock;
-import io.swagger.models.auth.In;
 import lombok.RequiredArgsConstructor;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.redisson.api.RLock;
 import org.redisson.api.RLock;
@@ -41,6 +38,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
 /**
 /**
@@ -58,9 +56,7 @@ public class OrderScheduler {
     private final AppOrderService orderService;
     private final AppOrderService orderService;
     private final CommonInfoService commonInfoService;
     private final CommonInfoService commonInfoService;
     private final PayDetailsService payDetailsService;
     private final PayDetailsService payDetailsService;
-
     private final ShopTypeService shopTypeService;
     private final ShopTypeService shopTypeService;
-
     private final GoodsShopService goodsShopService;
     private final GoodsShopService goodsShopService;
 
 
     private final static String RHT_PAY_BASE_URL = "https://api.ekbuyclub.com";
     private final static String RHT_PAY_BASE_URL = "https://api.ekbuyclub.com";
@@ -309,4 +305,33 @@ public class OrderScheduler {
             lock.unlock();
             lock.unlock();
         }
         }
     }
     }
+
+    /**
+     * 更新店铺销量
+     *  每天1点、10点、13点、22点执行
+     */
+    @Async
+    @Scheduled(cron = "0 0 1,10,13,22 * * ?")
+    public void updateShopSales() {
+        RLock lock = null;
+        try {
+            // 尝试获取锁,最多等待0秒(即立即返回),锁的过期时间为2分钟
+            lock = redissonClient.getLock(SchedulerLock.UPDATE_SHOP_SALES_LOCK);
+            boolean isLocked = lock.tryLock(0, 2, TimeUnit.MINUTES);
+            if (!isLocked) {
+                log.info("更新店铺销量任务:当前有其他服务实例正在执行,本次跳过");
+                return;
+            }
+            log.info("更新店铺销量任务开始运行");
+            Map<Long, Integer> shopSalesMap = orderService.countFinishByShopIdWithLast30Days();
+            goodsShopService.updateShopSales(shopSalesMap);
+            log.info("更新店铺销量任务运行成功");
+        } catch (Exception e) {
+            log.error("更新店铺销量任务运行失败,失败原因:{}", e.getMessage());
+        } finally {
+            if (lock != null && lock.isHeldByCurrentThread()) {
+                lock.unlock();
+            }
+        }
+    }
 }
 }

+ 7 - 1
src/main/resources/mapper/goods/GoodsShopMapper.xml

@@ -26,6 +26,9 @@
                 and gs.activity_id is not null
                 and gs.activity_id is not null
             </if>
             </if>
         </if>
         </if>
+        <if test="vipPromotion != null and vipPromotion != ''">
+            and gs.vip_promotion = #{vipPromotion}
+        </if>
         order by create_time desc
         order by create_time desc
     </select>
     </select>
 
 
@@ -249,10 +252,13 @@
                 <if test="shopTypeId!=null">
                 <if test="shopTypeId!=null">
                     and FIND_IN_SET(#{shopTypeId},gs.shop_type_id)
                     and FIND_IN_SET(#{shopTypeId},gs.shop_type_id)
                 </if>
                 </if>
+                <if test="vipPromotion !=null and vipPromotion != ''">
+                    and gs.vip_promotion = #{vipPromotion}
+                </if>
                 order by
                 order by
                     gs.is_recommend desc
                     gs.is_recommend desc
                 <if test="screen == 1">
                 <if test="screen == 1">
-                    ,gs.sort,gs.shop_score desc, distance asc
+                    ,gs.sort,gs.shop_score desc, gs.shop_sales desc, gs.create_time desc
                 </if>
                 </if>
                 <if test="screen == 2">
                 <if test="screen == 2">
                     ,gs.shop_score desc
                     ,gs.shop_score desc

+ 40 - 0
src/main/resources/mapper/member/SpecialFavorStudentMapper.xml

@@ -0,0 +1,40 @@
+<?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="com.sqx.modules.member.dao.SpecialFavorStudentDao">
+
+    <select id="pages" resultType="com.sqx.modules.member.vo.SpecialFavorStudentVO">
+        select
+            sfs.id,
+            sfs.name,
+            sfs.student_number,
+            sfs.verify_status,
+            sfs.create_time,
+            sfs.verify_user_id,
+            tu.user_name as verify_user_name,
+            tu.phone as verify_user_phone,
+            sfs.last_verify_time
+        from
+            special_favor_student sfs
+            left join
+                tb_user tu on sfs.verify_user_id = tu.user_id
+        <where>
+            and sfs.del_flag = 0
+            <if test="query.name != null and query.name != ''">
+                and sfs.name like concat('%', #{query.name}, '%')
+            </if>
+            <if test="query.studentNumber != null and query.studentNumber != ''">
+                and sfs.student_number like concat('%', #{query.studentNumber}, '%')
+            </if>
+            <if test="query.verifyStatus != null and query.verifyStatus != ''">
+                and sfs.verify_status = #{query.verifyStatus}
+            </if>
+            <if test="query.startTime != null">
+                and sfs.create_time >= #{query.startTime}
+            </if>
+            <if test="query.endTime != null">
+                and sfs.create_time <![CDATA[<=]]> #{query.endTime}
+            </if>
+        </where>
+        order by sfs.create_time desc
+    </select>
+</mapper>

+ 8 - 0
src/main/resources/mapper/member/VipPromoCodeMapper.xml

@@ -0,0 +1,8 @@
+<?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="com.sqx.modules.member.dao.VipPromoCodeDao">
+
+    <select id="incrementPromoCountById">
+        UPDATE vip_promo_code SET promo_count = promo_count + 1 WHERE id = #{promoCodeId}
+    </select>
+</mapper>

+ 49 - 0
src/main/resources/mapper/member/VipPromoRecordMapper.xml

@@ -0,0 +1,49 @@
+<?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="com.sqx.modules.member.dao.VipPromoRecordDao">
+
+    <select id="pages" resultType="com.sqx.modules.member.vo.VipPromoRecordVO">
+        select
+            vpr.id,
+            vpr.promo_code_id,
+            vpc.promo_code,
+            vpr.user_id,
+            vpr.user_name,
+            vpr.user_phone,
+            vpr.create_time,
+            vpr.create_time,
+            vpr.pay_type,
+            vpr.pay_amount,
+            t.vip_expiration_time expire_time
+        from
+            vip_promo_record vpr
+            left join vip_promo_code vpc on vpc.id = vpr.promo_code_id
+            left join tb_user t on vpr.user_id = t.user_id
+        <where>
+            and vpr.del_flag = 0
+            <if test="query.promoCodeId != null">
+                and vpr.promo_code_id = #{query.promoCodeId}
+            </if>
+            <if test="query.userPhone != null and query.userPhone != ''">
+                and vpr.user_phone like concat('%', #{query.userPhone}, '%')
+            </if>
+<!--            <if test="query.payType != null and query.payType != ''">-->
+<!--                and vpr.pay_type = #{query.payType}-->
+<!--            </if>-->
+            <!-- 是否暖心照顾 -->
+            <if test="query.specialFlag != null and query.specialFlag == '1'.toString()">
+                and vpr.pay_type = '3'
+            </if>
+            <if test="query.specialFlag != null and query.specialFlag != '1'.toString()">
+                and vpr.pay_type != '3'
+            </if>
+            <if test="query.startTime != null">
+                and vpr.create_time >= #{query.startTime}
+            </if>
+            <if test="query.endTime != null">
+                and vpr.create_time <![CDATA[<=]]>  #{query.endTime}
+            </if>
+        </where>
+        order by vpr.create_time desc
+    </select>
+</mapper>

+ 13 - 0
src/main/resources/mapper/order/OrderMapper.xml

@@ -812,4 +812,17 @@
 
 
     </select>
     </select>
 
 
+    <select id="countFinishByShopIdWithLast30Days" resultType="java.util.Map">
+        SELECT
+            shop_id,
+            COUNT(*) AS order_count
+        FROM
+            tb_order
+        WHERE
+            status in (3, 4, 6)
+            AND pay_time >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
+        GROUP BY
+            shop_id
+    </select>
+
 </mapper>
 </mapper>

+ 4 - 128
src/test/java/OrderTest.java

@@ -80,136 +80,12 @@ public class OrderTest {
     @Autowired
     @Autowired
     private AppOrderDao appOrderDao;
     private AppOrderDao appOrderDao;
 
 
+    @Autowired
+    private AppOrderService orderService;
+
     @Test
     @Test
     public void test() {
     public void test() {
-        List<TbOrder> orderList = appOrderDao.temp();
-        for (TbOrder tbOrder : orderList) {
-            QueryWrapper<UserMoneyDetails> queryWrapper = new QueryWrapper<>();
-            queryWrapper.eq("title", "商户订单收入,订单号:" + tbOrder.getOrderNumber());
-            if (userMoneyDetailsService.count(queryWrapper) > 0) {
-                log.info("订单id【{}】,商户用户钱包收入记录已存在,跳过", tbOrder.getOrderId());
-                continue;
-            }
-
-            log.info("订单id【{}】,开始计算商户用户钱包收入记录", tbOrder.getOrderId());
-
-
-            GoodsShop goodsShop = shopMessageService.selectShopId(tbOrder.getShopId());
-
-            // 计算商户应得金额
-            BigDecimal shopRate = goodsShop.getShopRate();
-            BigDecimal sumMoney = tbOrder.getPayMoney();
-            BigDecimal couponMoney = BigDecimal.ZERO;
-            Long shopIds = -1L;
-            if (tbOrder.getCouponId() != null) {
-                TbCouponUser tbCouponUser = tbCouponUserDao.selectById(tbOrder.getCouponId());
-                sumMoney = tbOrder.getPayMoney().add(tbCouponUser.getMoney());
-                couponMoney = tbCouponUser.getMoney();
-                shopIds = tbCouponUser.getShopId();
-            }
-
-            BigDecimal errandMoney = BigDecimal.ZERO;
-            if (tbOrder.getOrderType() != 1) {
-                //判断是否达到商家满减  如果达到商家满减 跑腿费让商家承担
-                if (tbOrder.getAutoSendOrder() != null && tbOrder.getAutoSendOrder() == 0) {
-                    errandMoney = tbOrder.getErrandMoney();
-                    sumMoney = sumMoney.subtract(tbOrder.getErrandMoney());
-                } else {
-                    sumMoney = sumMoney.subtract(tbOrder.getErrandMoney());
-                    errandMoney = tbOrder.getErrandMoney();
-                }
-            }
-
-            // 再减去校内配送费
-            sumMoney = sumMoney.subtract(tbOrder.getInsideDeliveryFee());
-
-            // 店铺收入
-            BigDecimal shopMoney = sumMoney.multiply(shopRate);
-            shopMoney = shopMoney.setScale(2, BigDecimal.ROUND_DOWN);
-            BigDecimal pingRate = sumMoney.subtract(shopMoney);
-
-            // 商家配送短信服务费 为0
-            BigDecimal smsSendMoney = BigDecimal.ZERO;
-
-            // 这里再判断 是否是商家优惠券  如果是商家优惠券  这笔钱商家承担
-            if (shopIds != -1 && shopIds != 0) {
-                shopMoney = shopMoney.subtract(couponMoney);
-            }
-
-            // 判断订单是否参与活动,如果参与活动,则优惠金额由商家承担
-            ActivityPartRecord activityPartRecord = activityPartRecordService.getByOrderId(tbOrder.getOrderId());
-            BigDecimal activityDiscountAmount = BigDecimal.ZERO;
-            if (ObjectUtil.isNotNull(activityPartRecord)) {
-                activityDiscountAmount = activityPartRecord.getDiscountAmount();
-            }
-
-            if (tbOrder.getAutoSendOrder() != null && tbOrder.getAutoSendOrder() == 1) {
-                //如果达到商家满减 则商家不加上配送费
-                if (!"本单已达到商家满减金额,跑腿费由商家承担".equals(tbOrder.getErrandMoneyIsShop())) {
-                    shopMoney = shopMoney.add(tbOrder.getErrandMoney());
-                }
-            }
-
-            StringBuffer contentBuffer = new StringBuffer();
-            BigDecimal rider = new BigDecimal(0);
-            if (ObjectUtils.isNotEmpty(tbOrder.getOrderTypeExtra())&&tbOrder.getOrderTypeExtra()==2) {
-                //        获取骑手额外配送费
-                CommonInfo commonInfo = commonInfoService.findOne(443);
-                if (ObjectUtils.isNotEmpty(commonInfo)) {
-                    rider =rider.add(new BigDecimal(commonInfo.getValue()));
-                    shopMoney=shopMoney.subtract(rider);
-                }
-                log.info("订单id【{}】,骑手额外配送费【{}】", tbOrder.getOrderId(), rider);
-            }
-
-            // 添加商户用户钱包收入记录
-            UserMoneyDetails userMoneyDetails1 = new UserMoneyDetails();
-            userMoneyDetails1.setShopId(goodsShop.getShopId());
-            userMoneyDetails1.setTitle("商户订单收入,订单号:" + tbOrder.getOrderNumber());
-
-            // 订单金额
-            BigDecimal orderAmount = tbOrder.getPayMoney().add(couponMoney).add(activityDiscountAmount);
-            contentBuffer.append("订单金额:").append(orderAmount.setScale(2, BigDecimal.ROUND_DOWN));
-            if (!couponMoney.equals(BigDecimal.ZERO)) {
-                contentBuffer.append(",优惠券金额:").append(couponMoney.setScale(2, BigDecimal.ROUND_DOWN));
-            }
-            if (!activityDiscountAmount.equals(BigDecimal.ZERO)) {
-                contentBuffer.append(",活动优惠金额:").append(activityDiscountAmount.setScale(2, BigDecimal.ROUND_DOWN));
-            }
-
-            contentBuffer.append(",用户实付金额:").append(tbOrder.getPayMoney()).append(",其中");
-            if (tbOrder.getOrderType() != 1) {
-                contentBuffer.append("跑腿费:").append(errandMoney.setScale(2, BigDecimal.ROUND_DOWN)).append("(").append(tbOrder.getErrandMoneyIsShop()).append(")").append(",");
-            }
-
-            contentBuffer.append("特殊地址跑腿费:").append(tbOrder.getInsideDeliveryFee().setScale(2, BigDecimal.ROUND_DOWN)).append(",");
-            contentBuffer.append("平台服务费:").append(pingRate.setScale(2, BigDecimal.ROUND_DOWN)).append(",");
-            contentBuffer.append("短信服务费:").append(smsSendMoney.setScale(2, BigDecimal.ROUND_DOWN)).append(",");
-            if (ObjectUtils.isNotEmpty(tbOrder.getOrderTypeExtra())&&tbOrder.getOrderTypeExtra()==2) {
-                contentBuffer.append("骑手额外配送费:").append(rider.setScale(2, BigDecimal.ROUND_DOWN)).append(",");
-            }
-            contentBuffer.append("到账金额:").append(shopMoney.setScale(2, BigDecimal.ROUND_DOWN));
-
-            if (shopIds == 0) {
-                contentBuffer.append("(本单为平台优惠券,平台补贴)");
-            } else if (shopIds != -1) {
-                contentBuffer.append("(本单为商家优惠券,商家补贴)");
-            }
-
-            userMoneyDetails1.setContent(contentBuffer.toString());
-
-            userMoneyDetails1.setType(1);
-            userMoneyDetails1.setClassify(3);
-            userMoneyDetails1.setMoney(shopMoney);
-            DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-            userMoneyDetails1.setCreateTime(LocalDateTime.now().format(dateTimeFormatter1));
-            userMoneyDetails1.setState(2);
-            userMoneyDetailsDao.insert(userMoneyDetails1);
-            log.info("订单id【{}】,商户用户钱包收入记录新增成功", tbOrder.getOrderId());
-
-            //将用户支付的金额转入商户用户钱包
-            userMoneyService.updateMoney(1, goodsShop.getUserId(), shopMoney.doubleValue());
-        }
+        orderService.accomplishOrder(1521747L, 2);
     }
     }
 
 
     @Test
     @Test