Browse Source

Merge branch 'master' of http://1.14.104.71:10880/root/ylrz_his_scrm_java into openIm

# Conflicts:
#	fs-company/src/main/resources/application.yml
#	fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreCartScrmMapper.java
#	fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreProductScrmMapper.java
#	fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreAfterSalesScrmServiceImpl.java
#	fs-service/src/main/resources/mapper/hisStore/FsStoreProductScrmMapper.xml
#	fs-user-app/src/main/java/com/fs/app/controller/course/CourseFsUserController.java
#	fs-user-app/src/main/resources/application.yml
15376779826 3 weeks ago
parent
commit
5469d7ab1f
100 changed files with 2282 additions and 401 deletions
  1. 18 0
      fs-ad-api/src/main/java/com/fs/framework/config/RedisConfig.java
  2. 5 5
      fs-admin/src/main/java/com/fs/company/controller/CompanyController.java
  3. 81 0
      fs-admin/src/main/java/com/fs/company/controller/CompanyStatisticsController.java
  4. 2 2
      fs-admin/src/main/java/com/fs/course/controller/FsCoursePlaySourceConfigController.java
  5. 44 0
      fs-admin/src/main/java/com/fs/course/controller/FsUserCourseCategoryController.java
  6. 3 3
      fs-admin/src/main/java/com/fs/his/controller/FsCompanyController.java
  7. 0 1
      fs-admin/src/main/java/com/fs/his/controller/FsTestTempItemController.java
  8. 2 2
      fs-admin/src/main/java/com/fs/qw/controller/QwCompanyController.java
  9. 26 3
      fs-admin/src/main/java/com/fs/web/controller/system/SysUserController.java
  10. 17 0
      fs-common-api/src/main/java/com/fs/framework/config/RedisConfig.java
  11. 11 0
      fs-common/src/main/java/com/fs/common/core/domain/entity/SysUser.java
  12. 19 0
      fs-company-app/src/main/java/com/fs/core/config/RedisConfig.java
  13. 14 5
      fs-company/src/main/java/com/fs/company/controller/course/FsCourseAnswerLogsController.java
  14. 14 4
      fs-company/src/main/java/com/fs/company/controller/course/FsCourseRedPacketLogController.java
  15. 19 0
      fs-company/src/main/java/com/fs/framework/config/RedisConfig.java
  16. 129 0
      fs-company/src/main/java/com/fs/hisStore/controller/FsIntegralGoodsController.java
  17. 191 0
      fs-company/src/main/java/com/fs/hisStore/controller/FsIntegralOrderController.java
  18. 18 0
      fs-doctor-app/src/main/java/com/fs/framework/config/RedisConfig.java
  19. 18 0
      fs-framework/src/main/java/com/fs/framework/config/RedisConfig.java
  20. 17 0
      fs-hospital/src/main/java/com/fs/framework/config/RedisConfig.java
  21. 18 0
      fs-ipad-task/src/main/java/com/fs/framework/config/RedisConfig.java
  22. 18 0
      fs-live-app/src/main/java/com/fs/framework/config/RedisConfig.java
  23. 18 0
      fs-qw-api-msg/src/main/java/com/fs/framework/config/RedisConfig.java
  24. 18 0
      fs-qw-api/src/main/java/com/fs/framework/config/RedisConfig.java
  25. 19 0
      fs-qw-mq/src/main/java/com/fs/framework/config/RedisConfig.java
  26. 19 0
      fs-qw-task/src/main/java/com/fs/framework/config/RedisConfig.java
  27. 18 0
      fs-qw-voice/src/main/java/com/fs/framework/config/RedisConfig.java
  28. 18 0
      fs-qwhook-msg/src/main/java/com/fs/framework/config/RedisConfig.java
  29. 18 0
      fs-qwhook-sop/src/main/java/com/fs/framework/config/RedisConfig.java
  30. 19 0
      fs-qwhook/src/main/java/com/fs/framework/config/RedisConfig.java
  31. 18 0
      fs-redis/src/main/java/com/fs/framework/config/RedisConfig.java
  32. 17 0
      fs-repeat-api/src/main/java/com/fs/framework/config/RedisConfig.java
  33. 1 35
      fs-service/src/main/java/com/fs/company/mapper/CompanyUserMapper.java
  34. 2 0
      fs-service/src/main/java/com/fs/company/vo/CompanyUserQwListVO.java
  35. 2 1
      fs-service/src/main/java/com/fs/company/vo/FsStoreOrderStatisticsVO.java
  36. 6 1
      fs-service/src/main/java/com/fs/core/config/RedissonConfig.java
  37. 2 0
      fs-service/src/main/java/com/fs/course/domain/FsUserCourseCategory.java
  38. 3 0
      fs-service/src/main/java/com/fs/course/mapper/FsUserCourseCategoryMapper.java
  39. 1 0
      fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigCreateParam.java
  40. 1 0
      fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigEditParam.java
  41. 2 1
      fs-service/src/main/java/com/fs/course/service/IFsUserCompanyUserService.java
  42. 1 0
      fs-service/src/main/java/com/fs/course/service/IFsUserCourseCategoryService.java
  43. 1 0
      fs-service/src/main/java/com/fs/course/service/impl/FsCourseRedPacketLogServiceImpl.java
  44. 10 1
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCompanyUserServiceImpl.java
  45. 4 1
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseCategoryServiceImpl.java
  46. 74 166
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  47. 1 0
      fs-service/src/main/java/com/fs/course/vo/FsCoursePlaySourceConfigVO.java
  48. 100 0
      fs-service/src/main/java/com/fs/his/domain/RedPacketLog.java
  49. 5 1
      fs-service/src/main/java/com/fs/his/mapper/FsInquiryOrderMapper.java
  50. 5 1
      fs-service/src/main/java/com/fs/his/mapper/FsInquiryOrderReportMapper.java
  51. 1 1
      fs-service/src/main/java/com/fs/his/mapper/FsIntegralGoodsMapper.java
  52. 11 3
      fs-service/src/main/java/com/fs/his/mapper/FsPackageOrderMapper.java
  53. 56 0
      fs-service/src/main/java/com/fs/his/mapper/FsStoreAfterSalesMapper.java
  54. 3 7
      fs-service/src/main/java/com/fs/his/mapper/FsStoreOrderMapper.java
  55. 13 2
      fs-service/src/main/java/com/fs/his/mapper/FsStorePaymentMapper.java
  56. 88 0
      fs-service/src/main/java/com/fs/his/mapper/RedPacketLogMapper.java
  57. 2 1
      fs-service/src/main/java/com/fs/his/param/FsInquiryOrderParam.java
  58. 2 0
      fs-service/src/main/java/com/fs/his/param/FsInquiryOrderReportParam.java
  59. 1 0
      fs-service/src/main/java/com/fs/his/param/FsIntegralOrderCreateParam.java
  60. 2 0
      fs-service/src/main/java/com/fs/his/param/FsPackageOrderParam.java
  61. 2 0
      fs-service/src/main/java/com/fs/his/param/FsStorePaymentParam.java
  62. 8 0
      fs-service/src/main/java/com/fs/his/service/IFsStoreAfterSalesService.java
  63. 21 4
      fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderServiceImpl.java
  64. 4 0
      fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java
  65. 25 12
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreAfterSalesServiceImpl.java
  66. 194 35
      fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java
  67. 3 1
      fs-service/src/main/java/com/fs/his/vo/FsInquiryOrderListVO.java
  68. 2 0
      fs-service/src/main/java/com/fs/his/vo/FsInquiryOrderReportListVO.java
  69. 1 0
      fs-service/src/main/java/com/fs/his/vo/FsIntegralGoodsListVO.java
  70. 2 0
      fs-service/src/main/java/com/fs/his/vo/FsPackageOrderExcelVO.java
  71. 3 0
      fs-service/src/main/java/com/fs/his/vo/FsPackageOrderListVO.java
  72. 8 0
      fs-service/src/main/java/com/fs/his/vo/FsStorePaymentExcelVO.java
  73. 4 2
      fs-service/src/main/java/com/fs/his/vo/FsStorePaymentVO.java
  74. 2 0
      fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreCartScrmMapper.java
  75. 11 46
      fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreProductScrmMapper.java
  76. 3 0
      fs-service/src/main/java/com/fs/hisStore/param/FsStoreProductQueryParam.java
  77. 13 10
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreAfterSalesScrmServiceImpl.java
  78. 11 2
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java
  79. 11 3
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreProductScrmServiceImpl.java
  80. 1 0
      fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java
  81. 64 18
      fs-service/src/main/java/com/fs/qw/mapper/QwFriendWelcomeMapper.java
  82. 1 0
      fs-service/src/main/java/com/fs/qw/param/QwExternalContactParam.java
  83. 5 0
      fs-service/src/main/java/com/fs/statis/domain/FsStatisSalerWatch.java
  84. 6 0
      fs-service/src/main/java/com/fs/system/mapper/SysUserMapper.java
  85. 9 0
      fs-service/src/main/java/com/fs/system/service/ISysUserService.java
  86. 22 0
      fs-service/src/main/java/com/fs/system/service/impl/SysUserServiceImpl.java
  87. 1 0
      fs-service/src/main/resources/application-config-bly.yml
  88. 1 0
      fs-service/src/main/resources/application-config-dev.yml
  89. 5 3
      fs-service/src/main/resources/application-config-druid-czt.yml
  90. 4 4
      fs-service/src/main/resources/application-config-druid-hst.yml
  91. 1 0
      fs-service/src/main/resources/application-config-druid-jnmy.yml
  92. 5 5
      fs-service/src/main/resources/application-config-druid-knt.yml
  93. 153 0
      fs-service/src/main/resources/application-druid-bnkc-test.yml
  94. 4 1
      fs-service/src/main/resources/application-druid-hst.yml
  95. 162 0
      fs-service/src/main/resources/application-druid-knt-test.yml
  96. 1 1
      fs-service/src/main/resources/application-druid-kyt.yml
  97. 155 0
      fs-service/src/main/resources/application-druid-nmgyt-test.yml
  98. 2 0
      fs-service/src/main/resources/application-druid-qdtst.yml
  99. 1 1
      fs-service/src/main/resources/mapper/company/CompanyMapper.xml
  100. 85 6
      fs-service/src/main/resources/mapper/company/CompanyUserMapper.xml

+ 18 - 0
fs-ad-api/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -67,6 +67,24 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         return template;
     }
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
 
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })

+ 5 - 5
fs-admin/src/main/java/com/fs/company/controller/CompanyController.java

@@ -71,7 +71,7 @@ public class CompanyController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
             param.setDeptId(loginUser.getDeptId());
         }
         List<CompanyVO> list = companyService.selectCompanyVOList(param);
@@ -89,7 +89,7 @@ public class CompanyController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
             company.setDeptId(loginUser.getDeptId());
         }
         List<CompanyVO> list = companyService.selectCompanyVOList(company);
@@ -178,7 +178,7 @@ public class CompanyController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
             map.setDeptId(loginUser.getDeptId());
         }
         List<Company> list = companyService.selectCompanyList(map);
@@ -194,7 +194,7 @@ public class CompanyController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
             param.setDeptId(loginUser.getDeptId());
         }
         List<CompanyCrmVO> list = companyService.selectCompanyCrmDayCountList(param);
@@ -276,7 +276,7 @@ public class CompanyController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
             deptId = loginUser.getDeptId();
         }
         List<OptionsVO> list = companyService.selectAllCompanyList(deptId);

+ 81 - 0
fs-admin/src/main/java/com/fs/company/controller/CompanyStatisticsController.java

@@ -19,6 +19,7 @@ import com.fs.crm.service.ICrmCustomerService;
 import com.fs.crm.service.ICrmCustomerVisitService;
 import com.fs.crm.vo.CrmCustomerStatisticsVO;
 import com.fs.crm.vo.CrmCustomerVisitStatisticsVO;
+import com.fs.his.service.IFsStoreAfterSalesService;
 import com.fs.his.service.IFsStoreOrderService;
 import com.fs.his.service.IFsStorePaymentService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -31,6 +32,7 @@ import org.springframework.web.bind.annotation.RestController;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
@@ -49,6 +51,10 @@ public class CompanyStatisticsController extends BaseController
 
     @Autowired
     private IFsStoreOrderService storeOrderService;
+
+    @Autowired
+    private IFsStoreAfterSalesService storeAfterSalesService;
+
     @Autowired
     private IFsStorePaymentService storePaymentService;
     @Autowired
@@ -146,6 +152,55 @@ public class CompanyStatisticsController extends BaseController
         }
     }
 
+    @GetMapping("/afterSalesOrder")
+    public R afterSalesOrder(FsStoreStatisticsParam param)
+    {
+        if(StringUtils.isNotEmpty(param.getUserIds())){
+            String[] userIds=param.getUserIds().split(",");
+            Long[] ids=new Long[userIds.length];
+            for(int i=0;i<ids.length; i++){
+                ids[i]=Long.parseLong(userIds[i]);
+            }
+            param.setUsers(ids);
+        }
+        else{
+            //获取部门下的所有用户
+            CompanyUser usermap=new CompanyUser();
+            usermap.setDeptId(param.getDeptId());
+            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
+            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
+            param.setUsers(userIds.toArray(new Long[userIds.size()]));
+        }
+        if(param.getUsers()!=null&&param.getUsers().length>0){
+            List<FsStoreOrderStatisticsVO> list= storeAfterSalesService.selectFsStoreAfterSalesServiceStatisticsList(param);
+
+            TimeUtils.TimeEntity timeEntity= TimeUtils.parseTime(param.getType().toString(),param.getStartTime(),param.getEndTime());
+            timeEntity.setUserIds(param.getUsers());
+            Integer cycleNum = timeEntity.getCycleNum();
+            Integer beginTime = timeEntity.getBeginTime();
+            List<Integer> timeList = new ArrayList<>();
+            for (int i = 1; i <= cycleNum; i++) {
+                timeList.add(beginTime);
+                beginTime = TimeUtils.formatTime(beginTime);
+            }
+            Map<String, Object> map = timeEntity.toMap();
+            if (StringUtils.isNotBlank(param.getStartTime())){
+                map.put("startTime",param.getStartTime());
+            }
+            if (StringUtils.isNotBlank(param.getEndTime())){
+                map.put("endTime",param.getEndTime());
+            }
+            List<JSONObject> jsonObjectList = storeAfterSalesService.selectFsStoreAfterSales(map);
+            List<String> dates = jsonObjectList.stream().map(jsonObject -> jsonObject.getString("type")).collect(Collectors.toList());
+            List<Integer> orderCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("orderCount")).collect(Collectors.toList());
+            List<BigDecimal> payPrice = jsonObjectList.stream().map(jsonObject -> jsonObject.getBigDecimal("payPrice")).collect(Collectors.toList());
+            return R.ok().put("list",list).put("dates",dates).put("orderCount",orderCount).put("payPrice",payPrice);
+        }
+        else {
+            return R.ok("未查找到数据");
+        }
+    }
+
 
     @GetMapping("/inquiryOrder")
     public R storeInquiryOrder(FsStoreStatisticsParam param)
@@ -244,6 +299,32 @@ public class CompanyStatisticsController extends BaseController
         return util.exportExcel(list, "orderLogs");
     }
 
+    @GetMapping("/exportAfterSalesOrder")
+    public AjaxResult exportAfterSalesOrder(FsStoreStatisticsParam param)
+    {
+        if(StringUtils.isNotEmpty(param.getUserIds())){
+            String[] userIds=param.getUserIds().split(",");
+            Long[] ids=new Long[userIds.length];
+            for(int i=0;i<ids.length; i++){
+                ids[i]=Long.parseLong(userIds[i]);
+            }
+            param.setUsers(ids);
+        }
+        else{
+            //获取所有员工
+            CompanyUser usermap=new CompanyUser();
+            usermap.setDeptId(param.getDeptId());
+            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
+            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
+            param.setUsers(userIds.toArray(new Long[userIds.size()]));
+        }
+
+        List<FsStoreOrderStatisticsVO> list= storeAfterSalesService.selectFsStoreAfterSalesServiceStatisticsList(param);
+
+        ExcelUtil<FsStoreOrderStatisticsVO> util = new ExcelUtil<FsStoreOrderStatisticsVO>(FsStoreOrderStatisticsVO.class);
+        return util.exportExcel(list, "orderLogs");
+    }
+
 
     @GetMapping("/exportInquiryOrder")
     public AjaxResult exportInquiryOrder(FsStoreStatisticsParam param)

+ 2 - 2
fs-admin/src/main/java/com/fs/course/controller/FsCoursePlaySourceConfigController.java

@@ -58,7 +58,7 @@ public class FsCoursePlaySourceConfigController extends BaseController {
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
         Long userId = null;
         Long deptId = null;
-        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
             deptId = loginUser.getDeptId();
             if(config.getDept() == null || !config.getDept()){
                 userId = loginUser.getUserId();
@@ -148,7 +148,7 @@ public class FsCoursePlaySourceConfigController extends BaseController {
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
         QueryWrapper<FsCoursePlaySourceConfig> queryWrapper = new QueryWrapper<FsCoursePlaySourceConfig>().eq("is_del", 0);
-        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
             queryWrapper.eq("create_user_id", loginUser.getUserId()).eq(config.getDept() == null || !config.getDept(), "create_dept_id", loginUser.getDeptId());
         }
         if(companyId != null){

+ 44 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseCategoryController.java

@@ -3,9 +3,18 @@ package com.fs.course.controller;
 import java.util.List;
 
 import com.fs.common.core.domain.R;
+import com.fs.common.core.domain.model.LoginUser;
+import com.fs.common.utils.ServletUtils;
+import com.fs.framework.web.service.TokenService;
 import com.fs.his.domain.FsStoreProductCategory;
 import com.fs.his.vo.FsStoreProductCategoryVO;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONUtil;
+import com.fs.course.config.CourseConfig;
+
 import com.fs.his.vo.OptionsVO;
+import com.fs.system.service.ISysConfigService;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -38,6 +47,12 @@ public class FsUserCourseCategoryController extends BaseController
     @Autowired
     private IFsUserCourseCategoryService fsUserCourseCategoryService;
 
+    @Autowired
+    private TokenService tokenService;
+
+    @Autowired
+    private ISysConfigService configService;
+
     /**
      * 查询课堂分类列表
      */
@@ -45,6 +60,13 @@ public class FsUserCourseCategoryController extends BaseController
     @GetMapping("/list")
     public AjaxResult list(FsUserCourseCategory fsUserCourseCategory)
     {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsUserCourseCategory.setUserId(userId);
+        }
         List<FsUserCourseCategory> list = fsUserCourseCategoryService.selectFsUserCourseCategoryList(fsUserCourseCategory);
         return AjaxResult.success(list);
     }
@@ -57,6 +79,13 @@ public class FsUserCourseCategoryController extends BaseController
     @GetMapping("/export")
     public AjaxResult export(FsUserCourseCategory fsUserCourseCategory)
     {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsUserCourseCategory.setUserId(userId);
+        }
         List<FsUserCourseCategory> list = fsUserCourseCategoryService.selectFsUserCourseCategoryList(fsUserCourseCategory);
         ExcelUtil<FsUserCourseCategory> util = new ExcelUtil<FsUserCourseCategory>(FsUserCourseCategory.class);
         return util.exportExcel(list, "课堂分类数据");
@@ -80,6 +109,13 @@ public class FsUserCourseCategoryController extends BaseController
     @PostMapping
     public AjaxResult add(@RequestBody FsUserCourseCategory fsUserCourseCategory)
     {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsUserCourseCategory.setUserId(userId);
+        }
         return toAjax(fsUserCourseCategoryService.insertFsUserCourseCategory(fsUserCourseCategory));
     }
 
@@ -119,6 +155,14 @@ public class FsUserCourseCategoryController extends BaseController
     @GetMapping("/getCatePidList")
     public R getCatePidList()
     {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            List<OptionsVO> list = fsUserCourseCategoryService.selectFsUserCourseCategoryPidList(userId);
+            return R.ok().put("data", list);
+        }
         List<OptionsVO> list = fsUserCourseCategoryService.selectFsUserCourseCategoryPidList();
         return R.ok().put("data", list);
     }

+ 3 - 3
fs-admin/src/main/java/com/fs/his/controller/FsCompanyController.java

@@ -81,7 +81,7 @@ public class FsCompanyController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
             company.setDeptId(loginUser.getDeptId());
         }
         List<CompanyVO> list = companyService.selectCompanyListVO(company);
@@ -96,7 +96,7 @@ public class FsCompanyController extends BaseController
         Long depId = null;
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
             depId = loginUser.getDeptId();
         }
         List<OptionsVO> list = companyService.selectAllCompanyList(depId);
@@ -152,7 +152,7 @@ public class FsCompanyController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
             company.setDeptId(loginUser.getDeptId());
         }
         return companyService.insertCompany(company);

+ 0 - 1
fs-admin/src/main/java/com/fs/his/controller/FsTestTempItemController.java

@@ -4,7 +4,6 @@ import java.util.List;
 
 import com.fs.his.param.FsTestTempItemParam;
 import com.fs.his.vo.FsTestTempItemListVO;
-import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;

+ 2 - 2
fs-admin/src/main/java/com/fs/qw/controller/QwCompanyController.java

@@ -57,7 +57,7 @@ public class QwCompanyController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
             qwCompany.setCreateDeptId(loginUser.getDeptId());
             qwCompany.setCreateUserId(loginUser.getUserId());
         }
@@ -74,7 +74,7 @@ public class QwCompanyController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        if(!loginUser.isAdmin() && config.getIsBound() != null && config.getIsBound()){
+        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
             deptId = loginUser.getDeptId();
             if(config.getDept() == null || !config.getDept()){
                 userId = loginUser.getUserId();

+ 26 - 3
fs-admin/src/main/java/com/fs/web/controller/system/SysUserController.java

@@ -1,10 +1,14 @@
 package com.fs.web.controller.system;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 
+import com.fs.common.constant.HttpStatus;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.model.LoginUser;
+import com.fs.common.core.page.PageDomain;
+import com.fs.common.core.page.TableSupport;
 import com.fs.common.utils.ServletUtils;
 import org.apache.commons.lang3.ArrayUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -59,9 +63,28 @@ public class SysUserController extends BaseController
     @GetMapping("/list")
     public TableDataInfo list(SysUser user)
     {
-        startPage();
-        List<SysUser> list = userService.selectUserList(user);
-        return getDataTable(list);
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Integer pageNum = pageDomain.getPageNum();
+        Integer pageSize = pageDomain.getPageSize();
+
+
+        long total = userService.selectUserCount(user);
+
+
+        List<Long> userIds = userService.selectUserIdsWithPage(user, pageNum, pageSize);
+
+        List<SysUser> list = new ArrayList<>();
+        if (!userIds.isEmpty()) {
+
+            list = userService.selectUserListByIds(userIds);
+        }
+
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(HttpStatus.SUCCESS);
+        rspData.setMsg("查询成功");
+        rspData.setRows(list);
+        rspData.setTotal(total);
+        return rspData;
     }
 
     @Log(title = "用户管理", businessType = BusinessType.EXPORT)

+ 17 - 0
fs-common-api/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -67,7 +67,24 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         return template;
     }
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
 
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })
     public RedisTemplate<String, Object> redisTemplateForObject(RedisConnectionFactory connectionFactory) {

+ 11 - 0
fs-common/src/main/java/com/fs/common/core/domain/entity/SysUser.java

@@ -95,11 +95,22 @@ public class SysUser extends BaseEntity
     /** 角色ID */
     private Long roleId;
 
+    @Excel(name = "角色名称")
+    private List<String> roleName;
+
     public SysUser()
     {
 
     }
 
+    public List<String> getRoleName() {
+        return roleName;
+    }
+
+    public void setRoleName(List<String> roleName) {
+        this.roleName = roleName;
+    }
+
     public SysUser(Long userId)
     {
         this.userId = userId;

+ 19 - 0
fs-company-app/src/main/java/com/fs/core/config/RedisConfig.java

@@ -68,6 +68,25 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
     }
 
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
+
     @Bean
     public RedisTemplate<String, BigDecimal> redisTemplateForBigDecimal(RedisConnectionFactory connectionFactory) {
         RedisTemplate<String, BigDecimal> template = new RedisTemplate<>();

+ 14 - 5
fs-company/src/main/java/com/fs/company/controller/course/FsCourseAnswerLogsController.java

@@ -1,5 +1,7 @@
 package com.fs.company.controller.course;
 
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONUtil;
 import com.fs.common.annotation.Log;
 import com.fs.common.constant.HttpStatus;
 import com.fs.common.core.controller.BaseController;
@@ -8,11 +10,13 @@ import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.config.CourseConfig;
 import com.fs.course.param.FsCourseAnswerLogsParam;
 import com.fs.course.service.IFsCourseAnswerLogsService;
 import com.fs.course.vo.FsCourseAnswerLogsListVO;
 import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
+import com.fs.system.service.ISysConfigService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -38,6 +42,9 @@ public class FsCourseAnswerLogsController extends BaseController
 
     @Autowired
     private TokenService tokenService;
+
+    @Autowired
+    private ISysConfigService configService;
     /**
      * 查询答题日志列表
      */
@@ -48,11 +55,13 @@ public class FsCourseAnswerLogsController extends BaseController
         if (param.getPhoneMk() != null && param.getPhoneMk() != "") {
             param.setPhone(param.getPhoneMk());
         }
-
-//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        // 如果他可以看两个销售公司就会查不出来
-//        param.setCompanyId( loginUser.getCompany().getCompanyId());
-
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            param.setCompanyId( loginUser.getCompany().getCompanyId());
+        }
         List<FsCourseAnswerLogsListVO> list = fsCourseAnswerLogsService.selectFsCourseAnswerLogsListVONew(param);
         TableDataInfo rspData = new TableDataInfo();
         rspData.setCode(HttpStatus.SUCCESS);

+ 14 - 4
fs-company/src/main/java/com/fs/company/controller/course/FsCourseRedPacketLogController.java

@@ -1,5 +1,7 @@
 package com.fs.company.controller.course;
 
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONUtil;
 import com.fs.common.annotation.Log;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.controller.BaseController;
@@ -9,6 +11,7 @@ import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsCourseRedPacketLog;
 import com.fs.course.mapper.FsUserCourseMapper;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
@@ -19,6 +22,7 @@ import com.fs.framework.security.LoginUser;
 import com.fs.framework.service.TokenService;
 import com.fs.his.utils.PhoneUtil;
 import com.fs.his.vo.OptionsVO;
+import com.fs.system.service.ISysConfigService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
@@ -45,7 +49,8 @@ public class FsCourseRedPacketLogController extends BaseController
     FsUserCourseVideoMapper fsUserCourseVideoMapper;
     @Autowired
     private TokenService tokenService;
-
+    @Autowired
+    private ISysConfigService configService;
     /**
      * 查询短链课程看课记录列表
      */
@@ -57,9 +62,14 @@ public class FsCourseRedPacketLogController extends BaseController
         if (fsCourseRedPacketLog.getPhoneMk() != null && fsCourseRedPacketLog.getPhoneMk() != "") {
             fsCourseRedPacketLog.setPhone(encryptPhone(fsCourseRedPacketLog.getPhoneMk()));
         }
-//        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        // 如果他可以看两个销售公司就会查不出来
-//        fsCourseRedPacketLog.setCompanyId( loginUser.getCompany().getCompanyId());
+
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long userId = loginUser.getUser().getUserId();
+        String json = configService.selectConfigByKey("course.config");
+        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
+        if (ObjectUtil.isNotEmpty(config.getIsBound())&&config.getIsBound()){
+            fsCourseRedPacketLog.setCompanyId( loginUser.getCompany().getCompanyId());
+        }
 
         List<FsCourseRedPacketLogListPVO> list = fsCourseRedPacketLogService.selectFsCourseRedPacketLogListVO(fsCourseRedPacketLog);
         for (FsCourseRedPacketLogListPVO fsCourseRedPacketLogListPVO : list) {

+ 19 - 0
fs-company/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -56,6 +56,25 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         return template;
     }
+
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
     @Bean
     public RedisTemplate<String, Boolean> redisTemplateForBoolean(RedisConnectionFactory connectionFactory) {
         RedisTemplate<String, Boolean> template = new RedisTemplate<>();

+ 129 - 0
fs-company/src/main/java/com/fs/hisStore/controller/FsIntegralGoodsController.java

@@ -0,0 +1,129 @@
+package com.fs.hisStore.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.his.domain.FsIntegralGoods;
+import com.fs.his.service.IFsIntegralGoodsService;
+import com.fs.his.utils.RedisCacheUtil;
+import com.fs.his.vo.FsIntegralGoodsListVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+/**
+ * 积分商品Controller
+ *
+ * @author fs
+ * @date 2023-11-02
+ */
+@RestController
+@RequestMapping("/his/integralGoods")
+public class FsIntegralGoodsController extends BaseController
+{
+    @Autowired
+    private IFsIntegralGoodsService fsIntegralGoodsService;
+    @Autowired
+    RedisCacheUtil redisCacheUtil;
+    /**
+     * 查询积分商品列表
+     */
+//    @PreAuthorize("@ss.hasPermi('his:integralGoods:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsIntegralGoods fsIntegralGoods)
+    {
+        startPage();
+        List<FsIntegralGoodsListVO> list = fsIntegralGoodsService.selectFsIntegralGoodsListVO(fsIntegralGoods);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出积分商品列表
+     */
+//    @PreAuthorize("@ss.hasPermi('his:integralGoods:export')")
+    @Log(title = "积分商品", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsIntegralGoods fsIntegralGoods)
+    {
+        List<FsIntegralGoods> list = fsIntegralGoodsService.selectFsIntegralGoodsList(fsIntegralGoods);
+        ExcelUtil<FsIntegralGoods> util = new ExcelUtil<FsIntegralGoods>(FsIntegralGoods.class);
+        return util.exportExcel(list, "积分商品数据");
+    }
+
+    /**
+     * 获取积分商品详细信息
+     */
+//    @PreAuthorize("@ss.hasPermi('his:integralGoods:query')")
+    @GetMapping(value = "/{goodsId}")
+    public AjaxResult getInfo(@PathVariable("goodsId") Long goodsId)
+    {
+        return AjaxResult.success(fsIntegralGoodsService.selectFsIntegralGoodsByGoodsId(goodsId));
+    }
+
+
+    @Log(title = "商品导入", businessType = BusinessType.IMPORT)
+    @PostMapping("/importData")
+    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
+    {
+        redisCacheUtil.delRedisKey("getIntegralGoodsList");
+        redisCacheUtil.delRedisKey("getIntegralGoodsById");
+        ExcelUtil<FsIntegralGoods> util = new ExcelUtil<>(FsIntegralGoods.class);
+        List<FsIntegralGoods> list = util.importExcel(file.getInputStream());
+        String message = fsIntegralGoodsService.importIntegralGoodsService(list);
+        return AjaxResult.success(message);
+    }
+
+    @GetMapping("/importTemplate")
+    public AjaxResult importTemplate()
+    {
+        ExcelUtil<FsIntegralGoods> util = new ExcelUtil<>(FsIntegralGoods.class);
+        return util.importTemplateExcel("商品数据");
+    }
+
+
+    /**
+     * 新增积分商品
+     */
+//    @PreAuthorize("@ss.hasPermi('his:integralGoods:add')")
+    @Log(title = "积分商品", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsIntegralGoods fsIntegralGoods)
+    {
+        redisCacheUtil.delRedisKey("getIntegralGoodsList");
+        redisCacheUtil.delRedisKey("getIntegralGoodsById");
+        return toAjax(fsIntegralGoodsService.insertFsIntegralGoods(fsIntegralGoods));
+    }
+
+    /**
+     * 修改积分商品
+     */
+//    @PreAuthorize("@ss.hasPermi('his:integralGoods:edit')")
+    @Log(title = "积分商品", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsIntegralGoods fsIntegralGoods)
+    {
+
+        redisCacheUtil.delRedisKey("getIntegralGoodsList");
+        redisCacheUtil.delRedisKey("getIntegralGoodsById");
+        return toAjax(fsIntegralGoodsService.updateFsIntegralGoods(fsIntegralGoods));
+    }
+
+    /**
+     * 删除积分商品
+     */
+//    @PreAuthorize("@ss.hasPermi('his:integralGoods:remove')")
+    @Log(title = "积分商品", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{goodsIds}")
+    public AjaxResult remove(@PathVariable Long[] goodsIds)
+    {
+        redisCacheUtil.delRedisKey("getIntegralGoodsList");
+        redisCacheUtil.delRedisKey("getIntegralGoodsById");
+        return toAjax(fsIntegralGoodsService.deleteFsIntegralGoodsByGoodsIds(goodsIds));
+    }
+}

+ 191 - 0
fs-company/src/main/java/com/fs/hisStore/controller/FsIntegralOrderController.java

@@ -0,0 +1,191 @@
+package com.fs.hisStore.controller;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.his.domain.FsIntegralOrder;
+import com.fs.his.dto.ExpressInfoDTO;
+import com.fs.his.enums.ShipperCodeEnum;
+import com.fs.his.param.FsIntegralOrderCreateParam;
+import com.fs.his.param.FsIntegralOrderParam;
+import com.fs.his.service.IFsExpressService;
+import com.fs.his.service.IFsIntegralOrderService;
+import com.fs.his.utils.PhoneUtil;
+import com.fs.his.vo.FsIntegralOrderListVO;
+import com.fs.his.vo.FsIntegralOrderPVO;
+import com.fs.his.vo.FsStoreProductDeliverExcelVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+import static com.fs.his.utils.PhoneUtil.decryptAutoPhoneMk;
+import static com.fs.his.utils.PhoneUtil.decryptPhone;
+
+/**
+ * 积分商品订单Controller
+ *
+ * @author fs
+ * @date 2023-11-02
+ */
+@RestController
+@RequestMapping("/his/integralOrder")
+public class FsIntegralOrderController extends BaseController
+{
+    @Autowired
+    private IFsIntegralOrderService fsIntegralOrderService;
+    @Autowired
+    private IFsExpressService expressService;
+    /**
+     * 查询积分商品订单列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:integralOrder:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsIntegralOrderParam fsIntegralOrder)
+    {
+        startPage();
+        List<FsIntegralOrderListVO> list = fsIntegralOrderService.selectFsIntegralOrderListVO(fsIntegralOrder);
+        for (FsIntegralOrderListVO vo : list) {
+            vo.setUserPhone(decryptAutoPhoneMk(vo.getUserPhone()));
+        }
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出积分商品订单列表
+     */
+    @PreAuthorize("@ss.hasPermi('his:integralOrder:export')")
+    @Log(title = "积分商品订单", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsIntegralOrder fsIntegralOrder)
+    {
+        List<FsIntegralOrder> list = fsIntegralOrderService.selectFsIntegralOrderList(fsIntegralOrder);
+        for (FsIntegralOrder vo : list) {
+            //商品名称以及原价赋值
+            String itemJson = vo.getItemJson();
+            if(StringUtils.isNotBlank(itemJson)){
+                JSONObject jsonObject = JSONObject.parseObject(itemJson);
+                vo.setGoodsName(jsonObject.getString("goodsName"));
+                vo.setOtPrice(jsonObject.getBigDecimal("otPrice"));
+            }
+            if (vo.getUserPhone()!=null&&!vo.getUserPhone().equals("")){
+                if(vo.getUserPhone().chars().allMatch(Character::isDigit)){continue;}
+//                vo.setUserPhone(vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
+                vo.setUserPhone(PhoneUtil.decryptPhone(vo.getUserPhone()));
+            }
+        }
+        ExcelUtil<FsIntegralOrder> util = new ExcelUtil<FsIntegralOrder>(FsIntegralOrder.class);
+        return util.exportExcel(list, "积分商品订单数据");
+    }
+    /**
+     * 发货
+     */
+//    @PreAuthorize("@ss.hasPermi('his:integralOrder:sendGoods')")
+    @PutMapping("/sendGoods")
+    public AjaxResult sendGoods(@RequestBody FsIntegralOrder fsIntegralOrder)
+    {
+        return toAjax(fsIntegralOrderService.sendGoods(fsIntegralOrder));
+    }
+
+    @GetMapping("/importTemplate")
+    public AjaxResult sendExport()
+    {
+        ExcelUtil<FsStoreProductDeliverExcelVO> util = new ExcelUtil<>(FsStoreProductDeliverExcelVO.class);
+        return util.importTemplateExcel("导入运单号");
+    }
+    @Log(title = "导入运单号", businessType = BusinessType.IMPORT)
+    @PostMapping("/importData")
+    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
+    {
+        ExcelUtil<FsStoreProductDeliverExcelVO> util = new ExcelUtil<>(FsStoreProductDeliverExcelVO.class);
+        List<FsStoreProductDeliverExcelVO> list = util.importExcel(file.getInputStream());
+        String message = fsIntegralOrderService.importProductDeliver(list);
+        return AjaxResult.success(message);
+    }
+//    @PreAuthorize("@ss.hasPermi('his:integralOrder:express')")
+    @GetMapping(value = "/getExpress/{id}")
+    public R getExpress(@PathVariable("id") Long id)
+    {
+        FsIntegralOrder fsIntegralOrder = fsIntegralOrderService.selectFsIntegralOrderByOrderId(id);
+        ExpressInfoDTO expressInfoDTO=null;
+        if(StringUtils.isNotEmpty(fsIntegralOrder.getDeliverySn())){
+            String lastFourNumber = "";
+            if (fsIntegralOrder.getDeliveryCode().equals(ShipperCodeEnum.SF.getValue())) {
+
+                lastFourNumber = fsIntegralOrder.getUserPhone();
+                if (lastFourNumber.length() == 11) {
+                    lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
+                }
+            }
+            expressInfoDTO=expressService.getExpressInfo(fsIntegralOrder.getOrderCode(),fsIntegralOrder.getDeliveryCode(),fsIntegralOrder.getDeliverySn(),lastFourNumber);
+        }
+        return R.ok().put("data",expressInfoDTO);
+    }
+    /**
+     * 获取积分商品订单详细信息
+     */
+//    @PreAuthorize("@ss.hasPermi('his:integralOrder:query')")
+    @GetMapping(value = "/{orderId}")
+    public AjaxResult getInfo(@PathVariable("orderId") Long orderId)
+    {
+        FsIntegralOrderPVO order = fsIntegralOrderService.selectFsIntegralOrderPVO(orderId);
+
+        order.setUserPhone(decryptAutoPhoneMk(order.getUserPhone()));
+        return AjaxResult.success(order);
+    }
+
+    @GetMapping(value = "/queryPhone/{orderId}")
+    @Log(title = "积分订单电话", businessType = BusinessType.GRANT)
+    @PreAuthorize("@ss.hasPermi('his:integralOrder:queryPhone')")
+    public R getPhone(@PathVariable("orderId") Long orderId)
+    {
+        FsIntegralOrderPVO order = fsIntegralOrderService.selectFsIntegralOrderPVO(orderId);
+        String userPhone = order.getUserPhone();
+        if (userPhone.length()>11){
+            userPhone = decryptPhone(userPhone);
+        }
+        return R.ok().put("userPhone",userPhone);
+    }
+
+    /**
+     * 新增积分商品订单
+     */
+//    @PreAuthorize("@ss.hasPermi('his:integralOrder:add')")
+    @Log(title = "积分商品订单", businessType = BusinessType.INSERT)
+    @PostMapping
+    public R add(@RequestBody FsIntegralOrderCreateParam param)
+    {
+        return fsIntegralOrderService.createOrder(param);
+    }
+
+    /**
+     * 修改积分商品订单
+     */
+//    @PreAuthorize("@ss.hasPermi('his:integralOrder:edit')")
+    @Log(title = "积分商品订单", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsIntegralOrder fsIntegralOrder)
+    {
+        return toAjax(fsIntegralOrderService.updateFsIntegralOrder(fsIntegralOrder));
+    }
+
+    /**
+     * 删除积分商品订单
+     */
+//    @PreAuthorize("@ss.hasPermi('his:integralOrder:remove')")
+    @Log(title = "积分商品订单", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{orderIds}")
+    public AjaxResult remove(@PathVariable Long[] orderIds)
+    {
+        return toAjax(fsIntegralOrderService.deleteFsIntegralOrderByOrderIds(orderIds));
+    }
+}

+ 18 - 0
fs-doctor-app/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -68,6 +68,24 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         return template;
     }
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
 
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })

+ 18 - 0
fs-framework/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -68,6 +68,24 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         return template;
     }
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
 
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })

+ 17 - 0
fs-hospital/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -69,7 +69,24 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         return template;
     }
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
 
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })
     public RedisTemplate<String, Object> redisTemplateForObject(RedisConnectionFactory connectionFactory) {

+ 18 - 0
fs-ipad-task/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -68,6 +68,24 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
     }
 
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })
     public RedisTemplate<String, Object> redisTemplateForObject(RedisConnectionFactory connectionFactory) {

+ 18 - 0
fs-live-app/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -67,6 +67,24 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         return template;
     }
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
 
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })

+ 18 - 0
fs-qw-api-msg/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -68,6 +68,24 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
     }
 
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
     @Bean
     public RedisTemplate<String, BigDecimal> redisTemplateForBigDecimal(RedisConnectionFactory connectionFactory) {
         RedisTemplate<String, BigDecimal> template = new RedisTemplate<>();

+ 18 - 0
fs-qw-api/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -92,6 +92,24 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         return template;
     }
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
 
     @Bean
     public RedisTemplate<String, BigDecimal> redisTemplateForBigDecimal(RedisConnectionFactory connectionFactory) {

+ 19 - 0
fs-qw-mq/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -68,6 +68,25 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
     }
 
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
+
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })
     public RedisTemplate<String, Object> redisTemplateForObject(RedisConnectionFactory connectionFactory) {

+ 19 - 0
fs-qw-task/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -68,6 +68,25 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
     }
 
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
+
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })
     public RedisTemplate<String, Object> redisTemplateForObject(RedisConnectionFactory connectionFactory) {

+ 18 - 0
fs-qw-voice/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -67,6 +67,24 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         return template;
     }
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
 
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })

+ 18 - 0
fs-qwhook-msg/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -68,6 +68,24 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
     }
 
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })
     public RedisTemplate<String, Object> redisTemplateForObject(RedisConnectionFactory connectionFactory) {

+ 18 - 0
fs-qwhook-sop/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -67,6 +67,24 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         return template;
     }
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
 
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })

+ 19 - 0
fs-qwhook/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -68,6 +68,25 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
     }
 
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
+
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })
     public RedisTemplate<String, Object> redisTemplateForObject(RedisConnectionFactory connectionFactory) {

+ 18 - 0
fs-redis/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -68,6 +68,24 @@ public class RedisConfig extends CachingConfigurerSupport
         return template;
     }
 
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
     @Bean
     @SuppressWarnings(value = { "unchecked", "rawtypes" })
     public RedisTemplate<String, Object> redisTemplateForObject(RedisConnectionFactory connectionFactory) {

+ 17 - 0
fs-repeat-api/src/main/java/com/fs/framework/config/RedisConfig.java

@@ -92,7 +92,24 @@ public class RedisConfig extends CachingConfigurerSupport
         template.afterPropertiesSet();
         return template;
     }
+    @Bean
+    public RedisTemplate<String, Integer> redisTemplateForInteger(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Integer> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用StringRedisSerializer来序列化和反序列化redis的key值
+        template.setKeySerializer(new StringRedisSerializer());
+
+        // 使用GenericToStringSerializer保证BigDecimal精度不丢失
+        template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
 
+        // Hash的key也采用StringRedisSerializer的序列化方式
+        template.setHashKeySerializer(new StringRedisSerializer());
+        template.setHashValueSerializer(new GenericToStringSerializer<>(Integer.class));
+
+        template.afterPropertiesSet();
+        return template;
+    }
     @Bean
     public RedisTemplate<String, BigDecimal> redisTemplateForBigDecimal(RedisConnectionFactory connectionFactory) {
         RedisTemplate<String, BigDecimal> template = new RedisTemplate<>();

+ 1 - 35
fs-service/src/main/java/com/fs/company/mapper/CompanyUserMapper.java

@@ -151,41 +151,7 @@ public interface CompanyUserMapper
     @Select("select * from  qw_user  where corp_id=#{corpId} and company_id=#{companyId}")
     List<QwUserVO> selectCompanyQwUserList(@Param("corpId") String corpId,@Param("companyId")Long companyId);
 
-    @Select({"<script> " +
-            "select u.*, d.dept_name, d.leader from company_user u\n" +
-            "        left join company_dept d on u.dept_id = d.dept_id\n" +
-            "        where u.del_flag = '0'\n" +
-            "        <if test=\"userName != null and userName != ''\">\n" +
-            "            AND u.user_name like concat('%', #{userName}, '%')\n" +
-            "        </if>\n" +
-            "\n" +
-            "        <if test=\"nickName != null and nickName != ''\">\n" +
-            "            AND u.nick_name like concat( #{nickName}, '%')\n" +
-            "        </if>\n" +
-            "        <if test=\"companyId != null and companyId != ''\">\n" +
-            "            AND u.company_id = #{companyId}\n" +
-            "        </if>\n" +
-            "        <if test=\"status != null and status != ''\">\n" +
-            "            AND u.status = #{status}\n" +
-            "        </if>\n" +
-            "        <if test=\"qwStatus != null \">\n" +
-            "            AND u.qw_status = #{qwStatus} \n" +
-            "        </if>\n" +
-            "        <if test=\"phonenumber != null and phonenumber != ''\">\n" +
-            "            AND u.phonenumber like concat('%', #{phonenumber}, '%')\n" +
-            "        </if>\n" +
-            "        <if test=\"beginTime != null and beginTime != ''\"><!-- 开始时间检索 -->\n" +
-            "            AND date_format(u.create_time,'%y%m%d') &gt;= date_format(#{beginTime},'%y%m%d')\n" +
-            "        </if>\n" +
-            "        <if test=\"endTime != null and endTime != ''\"><!-- 结束时间检索 -->\n" +
-            "            AND date_format(u.create_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')\n" +
-            "        </if>\n" +
-            "        <if test=\"deptId != null and deptId != 0\">\n" +
-            "            AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM company_dept t WHERE find_in_set(#{deptId}, ancestors) ))\n" +
-            "        </if>\n" +
-            "        <!-- 数据范围过滤 -->\n" +
-            "        ${params.dataScope}"+
-            "</script>"})
+
     List<CompanyUserQwListVO> selectCompanyUserQwListVO(CompanyUserQwParam user);
 
 

+ 2 - 0
fs-service/src/main/java/com/fs/company/vo/CompanyUserQwListVO.java

@@ -93,6 +93,8 @@ public class CompanyUserQwListVO extends BaseEntity {
     /** 角色对象 */
     private List<CompanyRole> roles;
 
+    /** 角色名称 */
+    private List<String> roleNames;
     /** 角色组 */
     private Long[] roleIds;
 

+ 2 - 1
fs-service/src/main/java/com/fs/company/vo/FsStoreOrderStatisticsVO.java

@@ -4,6 +4,7 @@ import com.fs.common.annotation.Excel;
 import lombok.Data;
 
 import java.io.Serializable;
+import java.math.BigDecimal;
 
 @Data
 public class FsStoreOrderStatisticsVO implements Serializable
@@ -13,7 +14,7 @@ public class FsStoreOrderStatisticsVO implements Serializable
     @Excel(name = "订单数")
     Integer orderCount;
     @Excel(name = "订单金额")
-    Integer payPrice;
+    BigDecimal payPrice;
 
 
 

+ 6 - 1
fs-service/src/main/java/com/fs/core/config/RedissonConfig.java

@@ -19,6 +19,9 @@ public class RedissonConfig {
     @Value("${spring.redis.host}")
     private String host;
 
+    @Value("${spring.redis.database}")
+    private int database;
+
     @Bean(destroyMethod = "shutdown")
     public RedissonClient redissonClient() {
         String address = "redis://" + host + ":" + port;
@@ -26,7 +29,9 @@ public class RedissonConfig {
         config.useSingleServer()
                 .setAddress(address) // 设置连接地址
                 .setConnectionMinimumIdleSize(10) // 最小空闲连接数
-                .setConnectionPoolSize(64); // 最大连接数
+                .setConnectionPoolSize(64) // 最大连接数
+                .setDatabase(database); //数据库
+
         if (null!=password&&!"".equals(password)) {
             config.useSingleServer().setPassword(password);
         }

+ 2 - 0
fs-service/src/main/java/com/fs/course/domain/FsUserCourseCategory.java

@@ -40,4 +40,6 @@ public class FsUserCourseCategory extends BaseEntity
 
     private String pic;
 
+
+    private Long userId;
 }

+ 3 - 0
fs-service/src/main/java/com/fs/course/mapper/FsUserCourseCategoryMapper.java

@@ -71,6 +71,9 @@ public interface FsUserCourseCategoryMapper
     @Select("select cate_id dict_value, cate_name dict_label  from fs_user_course_category WHERE pid = 0 and is_del=0 ")
     List<OptionsVO> selectFsUserCourseCategoryPidList();
 
+    @Select("select cate_id dict_value, cate_name dict_label  from fs_user_course_category WHERE pid = 0 and is_del=0 and user_id = #{userId}")
+    List<OptionsVO> selectFsUserCourseCategoryPidListByUserId(Long userId);
+
     @Select("select cate_id dict_value, cate_name dict_label  from fs_user_course_category WHERE pid =#{pid} and is_del=0 ")
     List<OptionsVO> selectCateListByPid(Long pid);
 

+ 1 - 0
fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigCreateParam.java

@@ -48,4 +48,5 @@ public class FsCoursePlaySourceConfigCreateParam {
 
     @ApiModelProperty("是否是互医/商城小程序")
     private Integer isMall;
+    private Long createDeptId;
 }

+ 1 - 0
fs-service/src/main/java/com/fs/course/param/FsCoursePlaySourceConfigEditParam.java

@@ -45,4 +45,5 @@ public class FsCoursePlaySourceConfigEditParam {
 
     @ApiModelProperty("是否是互医/商城小程序")
     private Integer isMall;
+    private Long createDeptId;
 }

+ 2 - 1
fs-service/src/main/java/com/fs/course/service/IFsUserCompanyUserService.java

@@ -9,7 +9,7 @@ import java.util.Map;
 
 /**
  * 微信用户和销售关系Service接口
- * 
+ *
  * @author fs
  * @date 2025-05-09
  */
@@ -75,6 +75,7 @@ public interface IFsUserCompanyUserService extends IService<FsUserCompanyUser>{
      * @param projectId   项目ID
      * @return FsUserCompanyUser
      */
+    FsUserCompanyUser selectByUserIdAndProjectId(Long userId, Long projectId,Long companyUserId);
     FsUserCompanyUser selectByUserIdAndProjectId(Long userId, Long projectId);
 
     /**

+ 1 - 0
fs-service/src/main/java/com/fs/course/service/IFsUserCourseCategoryService.java

@@ -64,6 +64,7 @@ public interface IFsUserCourseCategoryService
     List<OptionsVO> selectFsUserCoursePidList();
 
     List<OptionsVO> selectFsUserCourseCategoryPidList();
+    List<OptionsVO> selectFsUserCourseCategoryPidList(Long userId);
 
     List<OptionsVO> selectCateListByPid(Long pid);
 }

+ 1 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsCourseRedPacketLogServiceImpl.java

@@ -215,6 +215,7 @@ public class FsCourseRedPacketLogServiceImpl implements IFsCourseRedPacketLogSer
                 packetParam.setSource(2);
                 packetParam.setRedPacketMode(1);
                 packetParam.setCompanyId(param.getCompanyId());
+                packetParam.setUser(user);
                 R sendRedPacket = paymentService.sendRedPacket(packetParam);
                 if (sendRedPacket.get("code").equals(200)) {
                     FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();

+ 10 - 1
fs-service/src/main/java/com/fs/course/service/impl/FsUserCompanyUserServiceImpl.java

@@ -17,7 +17,7 @@ import java.util.Objects;
 
 /**
  * 微信用户和销售关系Service业务层处理
- * 
+ *
  * @author fs
  * @date 2025-05-09
  */
@@ -111,6 +111,15 @@ public class FsUserCompanyUserServiceImpl extends ServiceImpl<FsUserCompanyUserM
      * @param projectId   项目ID
      * @return FsUserCompanyUser
      */
+    @Override
+    public FsUserCompanyUser selectByUserIdAndProjectId(Long userId, Long projectId,Long companyUserId) {
+        LambdaQueryWrapper<FsUserCompanyUser> queryWrapper = Wrappers.<FsUserCompanyUser>lambdaQuery()
+                .eq(FsUserCompanyUser::getUserId, userId)
+                .eq(FsUserCompanyUser::getProjectId, projectId)
+                .eq(FsUserCompanyUser::getCompanyUserId, companyUserId);
+        return getOne(queryWrapper);
+    }
+
     @Override
     public FsUserCompanyUser selectByUserIdAndProjectId(Long userId, Long projectId) {
         LambdaQueryWrapper<FsUserCompanyUser> queryWrapper = Wrappers.<FsUserCompanyUser>lambdaQuery()

+ 4 - 1
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseCategoryServiceImpl.java

@@ -105,7 +105,10 @@ public class FsUserCourseCategoryServiceImpl implements IFsUserCourseCategorySer
         return fsUserCourseCategoryMapper.selectFsUserCourseCategoryPidList();
     }
 
-
+    @Override
+    public List<OptionsVO> selectFsUserCourseCategoryPidList(Long userId) {
+        return fsUserCourseCategoryMapper.selectFsUserCourseCategoryPidListByUserId(userId);
+    }
     @Override
     public List<OptionsVO> selectCateListByPid(Long pid) {
         return fsUserCourseCategoryMapper.selectCateListByPid(pid);

+ 74 - 166
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -89,6 +89,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.text.SimpleDateFormat;
 import java.time.*;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
@@ -115,27 +116,6 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     private Boolean isNewWxMerchant;
     private static final Logger logger = LoggerFactory.getLogger(FsUserCourseVideoServiceImpl.class);
 
-    /**
-     * 红包账户锁
-     */
-    private static final String REDPACKET_POOL_LOCK = "redpacket_pool_lock";
-
-    /**
-     * 公司红包金额
-     */
-    private static final String REDPACKET_COMPANY_MONEY = "redpacket_money";
-
-    /**
-     * 红包改变记录
-     */
-    private static final String REDPACKET_COMPANY_MONEY_CHANGE = "redpacket_money_change";
-
-    /**
-     * 是否开启红包账户扣减
-     */
-    @Value("${enableRedPackAccount:0}")
-    private String ENABLE_RED_PACK_ACCOUNT;
-
     private static final String miniappRealLink = "/pages_course/video.html?course=";
     private static final String REAL_LINK_PREFIX = "/courseH5/pages/course/learning?course=";
     private static final String SHORT_LINK_PREFIX = "/courseH5/pages/course/learning?s=";
@@ -252,8 +232,6 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     @Autowired
     ConfigUtil configUtil;
 
-    @Autowired
-    private RedisTemplate<String,BigDecimal> redisTemplate;
 
 
     /**
@@ -1024,6 +1002,9 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         if (log == null) {
             return R.error("无记录");
         }
+        if (log.getLogType() != 2) {
+            return R.error("未完课");
+        }
         if (log.getRewardType() != null) {
             FsCourseRedPacketLog packetLog = redPacketLogMapper.selectFsCourseRedPacketLogByTemporary(param.getVideoId(), param.getUserId());
             if(packetLog != null && packetLog.getStatus() == 1) {
@@ -1165,23 +1146,46 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
         // 准备发送红包参数
         WxSendRedPacketParam packetParam = new WxSendRedPacketParam();
-        packetParam.setOpenId(user.getMpOpenId());
-        // 来源是小程序切换openId
-        if (param.getSource() == 2) {
-            //处理多小程序问题
+
+        if (user.getMpOpenId()!=null&&!isNewWxMerchant){
+            packetParam.setOpenId(user.getMpOpenId());
+        }else {
+            //修复数据
             FsUserWx fsUserWx = fsUserWxService.selectByAppIdAndUserId(param.getAppId(),user.getUserId(),1);
             if (fsUserWx ==null){
+                if (user.getCourseMaOpenId()==null){
+                    logger.error(" 【转账openId参数错误】:{}", user.getUserId());
+                    return R.error("openId参数错误,请清理缓存后重新授权!");
+                }
+                packetParam.setOpenId(user.getCourseMaOpenId());
                 try {
                     handleFsUserWx(user,param.getAppId());
                 }catch (Exception e){
-                    logger.error("【更新或插入用户与小程序的绑定关系失败】:{}", user.getUserId());
+                    logger.error(" 【更新或插入用户与小程序的绑定关系失败】:{}", user.getUserId(),e);
                 }
+
             }else {
                 packetParam.setOpenId(fsUserWx.getOpenId());
             }
-            //查出公司绑定openid并赋值
         }
 
+//        packetParam.setOpenId(user.getMpOpenId());
+//        // 来源是小程序切换openId
+//        if (param.getSource() == 2) {
+//            //处理多小程序问题
+//            FsUserWx fsUserWx = fsUserWxService.selectByAppIdAndUserId(param.getAppId(),user.getUserId(),1);
+//            if (fsUserWx ==null){
+//                try {
+//                    handleFsUserWx(user,param.getAppId());
+//                }catch (Exception e){
+//                    logger.error("【更新或插入用户与小程序的绑定关系失败】:{}", user.getUserId());
+//                }
+//            }else {
+//                packetParam.setOpenId(fsUserWx.getOpenId());
+//            }
+//            //查出公司绑定openid并赋值
+//        }
+
         //判断服务号配置是否存在
         if (StringUtils.isNotEmpty(config.getMpAppId())){
             packetParam.setMpAppId(config.getMpAppId());
@@ -1196,28 +1200,8 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         logger.info("红包金额 {},红包商户号 {}",amount,packetParam);
         //2025.6.19 红包金额为0的时候
         if (amount.compareTo(BigDecimal.ZERO)>0){
-
-            //---------------发红包前先判断润天账户余额是否足够---------
-            RLock lock = redissonClient.getLock(REDPACKET_POOL_LOCK);
-            try{
-                boolean locked = lock.tryLock(3, 10, TimeUnit.SECONDS);
-
-                if (!locked) {
-                    logger.error("获取锁失败");
-                    return R.error("[红包领取] 系统繁忙,请重试!");
-                }
-
-                // 发送红包
-                return sendRedPacketRewardToUser(param, log, config, packetParam, amount);
-
-            }catch (Exception e){
-                logger.error("领取红包失败原因:{}", ExceptionUtils.getFullStackTrace(e),e);
-                throw new RuntimeException(e);
-            }finally {
-                if (lock.isHeldByCurrentThread()) {
-                    lock.unlock();
-                }
-            }
+            // 发送红包
+            return sendRedPacketRewardToUser(param, log, config, packetParam, amount);
         } else {
             FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
             // 添加红包记录
@@ -1245,25 +1229,6 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
 
     private R sendRedPacketRewardToUser(FsCourseSendRewardUParam param, FsCourseWatchLog log, CourseConfig config, WxSendRedPacketParam packetParam, BigDecimal amount) {
 
-        BigDecimal companyMoney = null;
-        if(StringUtils.equals(ENABLE_RED_PACK_ACCOUNT,"1")) {
-            companyMoney = redisTemplate.opsForValue().get(REDPACKET_COMPANY_MONEY);
-
-            if(ObjectUtils.isNull(companyMoney)){
-                SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("company.money");
-                if(ObjectUtils.isNull(sysConfig)){
-                    throw new IllegalArgumentException("润天公司账户余额不能为空!请检查配置!");
-                }
-                String configValue = sysConfig.getConfigValue();
-                companyMoney = new BigDecimal(configValue);
-                logger.info("缓存公司余额为空,从数据库读取 companyMoney: {}",companyMoney);
-            }
-
-            if (companyMoney.compareTo(BigDecimal.ZERO) <= 0) {
-                logger.info("润天账户余额: {} 不足!", companyMoney);
-                return R.error("[红包领取] 账户余额不足,请联系管理员!");
-            }
-        }
 
         // 发送红包
         R sendRedPacket = paymentService.sendRedPacket(packetParam);
@@ -1289,23 +1254,12 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             redPacketLog.setAmount(amount);
             redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
             redPacketLog.setPeriodId(param.getPeriodId());
-            if(StringUtils.equals(ENABLE_RED_PACK_ACCOUNT,"1")) {
-                redPacketLog.setAccBalanceBefore(companyMoney);
-                redPacketLog.setAccBalanceAfter(companyMoney.subtract(amount));
-            }
 
             redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
             // 更新观看记录的奖励类型
             log.setRewardType(config.getRewardType());
             courseWatchLogMapper.updateFsCourseWatchLog(log);
 
-            if(StringUtils.equals(ENABLE_RED_PACK_ACCOUNT,"1")) {
-                // 更新账户余额
-                logger.info("[更新账户余额] 当前余额{} 更新后余额{}",companyMoney.toPlainString(),companyMoney.subtract(amount).toPlainString());
-
-                companyMoney = companyMoney.subtract(amount);
-                redisTemplate.opsForValue().set(REDPACKET_COMPANY_MONEY,companyMoney);
-            }
             return sendRedPacket;
         } else {
             return R.error("奖励发送失败,请联系客服");
@@ -1313,6 +1267,8 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     }
 
 
+
+
     private void handleFsUserWx(FsUser user, String appId) {
         FsUserWx fsUserWx = new FsUserWx();
         fsUserWx.setType(1);
@@ -1417,92 +1373,43 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
                 return R.error("服务商余额不足,请联系群主服务器充值!");
             }
 
-            //---------------发红包前先判断润天账户余额是否足够---------
-            RLock lock = redissonClient.getLock(REDPACKET_POOL_LOCK);
-            try{
-                boolean locked = lock.tryLock(3, 10, TimeUnit.SECONDS);
-
-                if (!locked) {
-                    logger.error("获取锁失败");
-                    return R.error("[红包领取] 系统繁忙,请重试!");
-                }
-
-                BigDecimal companyMoney = null;
-                if(StringUtils.equals(ENABLE_RED_PACK_ACCOUNT,"1")) {
-                    companyMoney = redisTemplate.opsForValue().get(REDPACKET_COMPANY_MONEY);
-                    if(ObjectUtils.isNull(companyMoney)){
-                        SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("company.money");
-                        if(ObjectUtils.isNull(sysConfig)){
-                            throw new IllegalArgumentException("润天公司账户余额不能为空!请检查配置!");
-                        }
-                        String configValue = sysConfig.getConfigValue();
-                        companyMoney = new BigDecimal(configValue);
-                        logger.info("缓存公司余额为空,从数据库读取 companyMoney: {}",companyMoney);
-                    }
-
-                    if (companyMoney.compareTo(BigDecimal.ZERO) <= 0) {
-                        logger.info("润天账户余额: {} 不足!", companyMoney);
-                        return R.error("[红包领取] 账户余额不足,请联系管理员!");
-                    }
-                }
-                // 发送红包
-                R sendRedPacket = paymentService.sendRedPacket(packetParam);
-                if (sendRedPacket.get("code").equals(200)) {
-                    FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
-                    TransferBillsResult transferBillsResult;
-                    if (sendRedPacket.get("isNew").equals(1)){
-                        transferBillsResult = (TransferBillsResult)sendRedPacket.get("data");
-                        redPacketLog.setResult(JSON.toJSONString(sendRedPacket));
-                        redPacketLog.setOutBatchNo(transferBillsResult.getOutBillNo());
-                    }else {
-                        redPacketLog.setOutBatchNo(sendRedPacket.get("orderCode").toString());
-                        redPacketLog.setBatchId(sendRedPacket.get("batchId").toString());
-                    }
-                    // 添加红包记录
-                    redPacketLog.setCourseId(param.getCourseId());
-                    redPacketLog.setCompanyId(param.getCompanyId());
-                    redPacketLog.setUserId(param.getUserId());
-                    redPacketLog.setVideoId(param.getVideoId());
-                    redPacketLog.setStatus(0);
-                    redPacketLog.setQwUserId(param.getQwUserId() != null ? param.getQwUserId() : null);
-                    redPacketLog.setCompanyUserId(param.getCompanyUserId());
-                    redPacketLog.setCreateTime(new Date());
-                    redPacketLog.setAmount(amount);
-                    redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
-                    redPacketLog.setPeriodId(param.getPeriodId());
-                    redPacketLog.setAppId(param.getAppId());
-                    if(StringUtils.equals(ENABLE_RED_PACK_ACCOUNT,"1")) {
-                        redPacketLog.setAccBalanceBefore(companyMoney);
-                        redPacketLog.setAccBalanceAfter(companyMoney.subtract(amount));
-                    }
-                    redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
-
-                    // 更新观看记录的奖励类型
-                    log.setRewardType(config.getRewardType());
-                    courseWatchLogMapper.updateFsCourseWatchLog(log);
-
-
-                    if(StringUtils.equals(ENABLE_RED_PACK_ACCOUNT,"1")) {
-                        // 更新账户余额
-                        logger.info("[更新账户余额] 当前余额{} 更新后余额{}",companyMoney.toPlainString(),companyMoney.subtract(amount).toPlainString());
-
-                        companyMoney = companyMoney.subtract(amount);
-                        redisTemplate.opsForValue().set(REDPACKET_COMPANY_MONEY,companyMoney);
-                    }
-
-                    return sendRedPacket;
-                } else {
-                    return R.error("奖励发送失败,请联系客服");
-                }
-            }catch (Exception e){
-                logger.error("领取红包失败原因:{}", ExceptionUtils.getFullStackTrace(e),e);
-                throw new RuntimeException(e);
-            }finally {
-                if (lock.isHeldByCurrentThread()) {
-                    lock.unlock();
+            // 发送红包
+            R sendRedPacket = paymentService.sendRedPacket(packetParam);
+            if (sendRedPacket.get("code").equals(200)) {
+                FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
+                TransferBillsResult transferBillsResult;
+                if (sendRedPacket.get("isNew").equals(1)){
+                    transferBillsResult = (TransferBillsResult)sendRedPacket.get("data");
+                    redPacketLog.setResult(JSON.toJSONString(sendRedPacket));
+                    redPacketLog.setOutBatchNo(transferBillsResult.getOutBillNo());
+                }else {
+                    redPacketLog.setOutBatchNo(sendRedPacket.get("orderCode").toString());
+                    redPacketLog.setBatchId(sendRedPacket.get("batchId").toString());
                 }
+                // 添加红包记录
+                redPacketLog.setCourseId(param.getCourseId());
+                redPacketLog.setCompanyId(param.getCompanyId());
+                redPacketLog.setUserId(param.getUserId());
+                redPacketLog.setVideoId(param.getVideoId());
+                redPacketLog.setStatus(0);
+                redPacketLog.setQwUserId(param.getQwUserId() != null ? param.getQwUserId() : null);
+                redPacketLog.setCompanyUserId(param.getCompanyUserId());
+                redPacketLog.setCreateTime(new Date());
+                redPacketLog.setAmount(amount);
+                redPacketLog.setWatchLogId(log.getLogId() != null ? log.getLogId() : null);
+                redPacketLog.setPeriodId(param.getPeriodId());
+                redPacketLog.setAppId(param.getAppId());
+
+                redPacketLogMapper.insertFsCourseRedPacketLog(redPacketLog);
+
+                // 更新观看记录的奖励类型
+                log.setRewardType(config.getRewardType());
+                courseWatchLogMapper.updateFsCourseWatchLog(log);
+
+                return sendRedPacket;
+            } else {
+                return R.error("奖励发送失败,请联系客服");
             }
-
         } else {
             FsCourseRedPacketLog redPacketLog = new FsCourseRedPacketLog();
             // 添加红包记录
@@ -1802,7 +1709,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         }
 
         // 查询【用户-项目】关系
-        FsUserCompanyUser userCompanyUser = userCompanyUserService.selectByUserIdAndProjectId(fsUser.getUserId(), courseProject);
+        FsUserCompanyUser userCompanyUser = userCompanyUserService.selectByUserIdAndProjectId(fsUser.getUserId(), courseProject,companyUser.getUserId());
 
         // 添加逻辑:如果存在fs_user表数据,但是又不存在fs_user_company_user表,则表示是以前企微看课的,需要手动绑定
         if(Objects.isNull(userCompanyUser)) {
@@ -2861,3 +2768,4 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     }
 
 }
+

+ 1 - 0
fs-service/src/main/java/com/fs/course/vo/FsCoursePlaySourceConfigVO.java

@@ -54,4 +54,5 @@ public class FsCoursePlaySourceConfigVO {
      * 是否是互医/商城小程序
      */
     private Integer isMall;
+    private Long createDeptId;
 }

+ 100 - 0
fs-service/src/main/java/com/fs/his/domain/RedPacketLog.java

@@ -0,0 +1,100 @@
+package com.fs.his.domain;
+
+import lombok.Data;
+import lombok.Builder;
+import lombok.NoArgsConstructor;
+import lombok.AllArgsConstructor;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+/**
+ * 红包发放日志表
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RedPacketLog {
+
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 用户ID
+     */
+    private Long userId;
+
+    /**
+     * 红包金额
+     */
+    private BigDecimal amount;
+
+    /**
+     * 公司ID
+     */
+    private Long companyId;
+
+    /**
+     * 来源 1:h5 2:看课小程序
+     */
+    private Integer source;
+
+    /**
+     * 红包模式
+     */
+    private Integer redPacketMode;
+
+    /**
+     * 应用ID
+     */
+    private String appId;
+
+    /**
+     * 扣减前余额
+     */
+    private BigDecimal accBalanceBefore;
+
+    /**
+     * 扣减后余额
+     */
+    private BigDecimal accBalanceAfter;
+
+    /**
+     * 状态:0-处理中 1-成功 2-失败
+     */
+    private Integer status;
+
+    /**
+     * 错误信息
+     */
+    private String errorMsg;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+    /**
+     * 创建人
+     */
+    private String createBy;
+
+    /**
+     * 更新人
+     */
+    private String updateBy;
+
+    /**
+     * 备注
+     */
+    private String remark;
+}

+ 5 - 1
fs-service/src/main/java/com/fs/his/mapper/FsInquiryOrderMapper.java

@@ -69,10 +69,14 @@ public interface FsInquiryOrderMapper
     public int deleteFsInquiryOrderByOrderIds(Long[] orderIds);
 
     @Select({"<script> " +
-            "select io.*,dc.doctor_name,dc.account as doctor_account,det.dept_name,c.company_name,cu.nick_name company_user_name ,io.patient_json->>'$.patientName'as  patient_name,syu.nick_name user_name from fs_inquiry_order io  LEFT JOIN fs_doctor dc ON io.doctor_id =dc.doctor_id LEFT JOIN fs_department det ON det.dept_id =io.department_id  LEFT JOIN sys_user syu ON syu.user_id =io.audit_user_id  LEFT JOIN company c ON c.company_id= io.company_id LEFT JOIN company_user cu ON cu.user_id=io.company_user_id  "+
+            "select io.*,dc.doctor_name,dc.account as doctor_account,det.dept_name,c.company_name,cu.nick_name company_user_name ,io.patient_json->>'$.patientName'as  patient_name,syu.nick_name user_name,csc.name miniProgramName from fs_inquiry_order io  LEFT JOIN fs_doctor dc ON io.doctor_id =dc.doctor_id LEFT JOIN fs_department det ON det.dept_id =io.department_id  LEFT JOIN sys_user syu ON syu.user_id =io.audit_user_id  LEFT JOIN company c ON c.company_id= io.company_id LEFT JOIN company_user cu ON cu.user_id=io.company_user_id  "+
             "            <if test=\"maps.phone != null  and maps.phone != ''\"> LEFT JOIN fs_user fu ON fu.user_id=io.user_id</if>\n" +
+            "LEFT JOIN (SELECT sp.*,ROW_NUMBER() OVER (PARTITION BY sp.pay_code ORDER BY sp.create_time DESC) as rn\n" +
+            "        FROM fs_store_payment sp) sp_latest ON sp_latest.business_code = io.order_sn AND sp_latest.rn = 1\n" +
+            "        LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp_latest.app_id" +
             " where 1=1 " +
             "            <if test=\"maps.orderSn != null  and maps.orderSn != ''\"> and io.order_sn = #{maps.orderSn}</if>\n" +
+            "            <if test=\"maps.coursePlaySourceConfigId != null\"> and csc.id = #{maps.coursePlaySourceConfigId}</if>\n" +
             "            <if test=\"maps.title != null  and maps.title != ''\"> and io.title = #{maps.title}</if>\n" +
             "            <if test=\"maps.userId != null \"> and io.user_id = #{maps.userId}</if>\n" +
             "            <if test=\"maps.doctorName != null \">  and dc.doctor_name like concat('%', #{maps.doctorName}, '%')</if>\n" +

+ 5 - 1
fs-service/src/main/java/com/fs/his/mapper/FsInquiryOrderReportMapper.java

@@ -65,7 +65,7 @@ public interface FsInquiryOrderReportMapper
      */
     public int deleteFsInquiryOrderReportByReportIds(Long[] reportIds);
     @Select({"<script> " +
-            "select ior.*,ior.patient_json->>'$.patientName' as  patient_name,u.nick_name,u.phone,d.doctor_name,su.nick_name user_name,send.nick_name send_name,fio.status inquiry_status,fio.inquiry_sub_type,fio.order_sn,c.company_name,cuu.nick_name company_user_name,fz.nick_name fz_name  FROM fs_inquiry_order_report ior  " +
+            "select ior.*,ior.patient_json->>'$.patientName' as  patient_name,u.nick_name,u.phone,d.doctor_name,su.nick_name user_name,send.nick_name send_name,fio.status inquiry_status,fio.inquiry_sub_type,fio.order_sn,c.company_name,cuu.nick_name company_user_name,fz.nick_name fz_name,csc.name miniProgramName  FROM fs_inquiry_order_report ior  " +
             " LEFT JOIN fs_user u ON u.user_id=ior.user_id " +
             " LEFT JOIN fs_doctor d ON d.doctor_id=ior.doctor_id " +
             " LEFT JOIN sys_user su ON su.user_id=ior.audit_user_id " +
@@ -76,8 +76,12 @@ public interface FsInquiryOrderReportMapper
             " LEFT JOIN company_user cuu ON cuu.user_id=fio.company_user_id " +
             " LEFT JOIN company_user fz ON fz.user_id=ior.triage_user_id " +
             " LEFT join fs_patient fp on ior.patient_id = fp.patient_id " +
+            "LEFT JOIN (SELECT sp.*,ROW_NUMBER() OVER (PARTITION BY sp.pay_code ORDER BY sp.create_time DESC) as rn\n" +
+            "        FROM fs_store_payment sp) sp_latest ON sp_latest.business_code = fio.order_sn AND sp_latest.rn = 1\n" +
+            "        LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp_latest.app_id" +
             " WHERE fio.`status`!=1 and fio.inquiry_sub_type!=3"+
             "            <if test=\"maps.orderId != null \"> and fio.order_sn = #{maps.orderId}</if>\n" +
+            "            <if test=\"maps.coursePlaySourceConfigId != null\"> and csc.id = #{maps.coursePlaySourceConfigId}</if>\n" +
             "            <if test=\"maps.doctorName != null \"> and d.doctor_name = #{maps.doctorName}</if>\n" +
             "            <if test=\"maps.reportSn != null  and maps.reportSn != ''\"> and ior.report_sn = #{maps.reportSn}</if>\n" +
             "            <if test=\"maps.sTime != null \">  and DATE(ior.create_time) &gt;= DATE(#{maps.sTime})</if>\n" +

+ 1 - 1
fs-service/src/main/java/com/fs/his/mapper/FsIntegralGoodsMapper.java

@@ -66,7 +66,7 @@ public interface FsIntegralGoodsMapper
      */
     public int deleteFsIntegralGoodsByGoodsIds(Long[] goodsIds);
 
-    @Select({"<script> select goods_id, img_url, images, goods_name, ot_price, goods_type, status, integral, cash, sort, stock, descs, create_time from fs_integral_goods" +
+    @Select({"<script> select goods_id,bar_code, img_url, images, goods_name, ot_price, goods_type, status, integral, cash, sort, stock, descs, create_time from fs_integral_goods" +
             "<where>  \n" +
             "            <if test=\"goodsName != null  and goodsName != ''\"> and goods_name like concat('%', #{goodsName}, '%')</if>\n" +
             "            <if test=\"goodsType != null \"> and goods_type = #{goodsType}</if>\n" +

+ 11 - 3
fs-service/src/main/java/com/fs/his/mapper/FsPackageOrderMapper.java

@@ -78,16 +78,20 @@ public interface FsPackageOrderMapper
     @Select({"<script> " +
             "select o.order_id,o.package_second_name,o.source,o.order_sn,o.package_name,o.pay_time,o.is_pay, o.days,o.pay_price, " +
             "o.pay_money,o.pay_type,o.`status`,o.package_sub_type,o.create_time,o.start_time,o.finish_time      " +
-            ",d.doctor_name,u.nick_name,u.phone,c.company_name,cu.nick_name company_user_name, " +
-            "patient_json->>'$.patientName' as patientName,fso.delivery_status,fso.delivery_pay_status  " +
+            ",d.doctor_name,u.nick_name,u.phone,c.company_name,cu.nick_name company_user_name,csc.name miniProgramName," +
+            "JSON_UNQUOTE(JSON_EXTRACT(o.patient_json, '$.patientName')) AS patientName,fso.delivery_status,fso.delivery_pay_status  " +
             "from fs_package_order o " +
             "LEFT JOIN fs_doctor d ON d.doctor_id=o.doctor_id " +
             "LEFT JOIN fs_user u ON u.user_id=o.user_id " +
             "LEFT JOIN company c on c.company_id =o.company_id " +
             "LEFT JOIN company_user cu on cu.user_id=o.company_user_id " +
             "LEFT JOIN fs_store_order fso ON fso.order_id= o.store_order_id "+
+            "LEFT JOIN (SELECT sp.*,ROW_NUMBER() OVER (PARTITION BY sp.business_code ORDER BY sp.create_time DESC) as rn\n" +
+            "        FROM fs_store_payment sp) sp_latest ON sp_latest.business_code = o.order_sn AND sp_latest.rn = 1\n" +
+            "        LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp_latest.app_id" +
             " where 1 = 1 \n" +
             "            <if test=\"maps.orderSn != null  and maps.orderSn != ''\"> and o.order_sn = #{maps.orderSn}</if>\n" +
+            "            <if test=\"maps.coursePlaySourceConfigId != null\"> and csc.id = #{maps.coursePlaySourceConfigId}</if>\n" +
             "            <if test=\"maps.phone != null and maps.phone != '' \">and u.phone = #{maps.phone} </if>\n" +
             "            <if test=\"maps.doctorName != null \">and d.doctor_name like concat('%', #{maps.doctorName}, '%')</if>\n" +
             "            <if test=\"maps.packageName != null  and maps.packageName != ''\"> and o.package_name like concat('%', #{maps.packageName}, '%')</if>\n" +
@@ -146,9 +150,13 @@ public interface FsPackageOrderMapper
     @Select("SELECT * FROM fs_store_payment where business_id=#{orderId} and status=1 and business_type=3")
     List<FsStorePayment> selectFsPackagePaymentByOrderId(Long orderId);
     @Select({"<script> " +
-            "select o.order_id,o.order_sn,o.package_name,o.source,o.pay_time,o.follow_rate,o.cycle,o.follow_num,o.inquiry_cost_price,o.product_cost_price,o.total_cost_price,o.cost_discount_money,o.total_price,o.discount_money,o.pay_delivery,o.is_pay,o.remark, o.days,o.pay_price,o.pay_money,o.pay_type,o.`status`,o.package_sub_type,o.create_time,o.start_time,o.refund_status,o.finish_time,d.doctor_name,u.nick_name,u.phone,c.company_name,cu.nick_name company_user_name,patient_json->>'$.patientName' as patientName,fso.delivery_status,fso.delivery_pay_status from fs_package_order o LEFT JOIN fs_doctor d ON d.doctor_id=o.doctor_id LEFT JOIN fs_user u ON u.user_id=o.user_id LEFT JOIN company c on c.company_id =o.company_id LEFT JOIN company_user cu on cu.user_id=o.company_user_id LEFT JOIN fs_store_order fso ON fso.order_id= o.store_order_id "+
+            "select o.order_id,o.order_sn,o.package_name,o.source,o.pay_time,o.follow_rate,o.cycle,o.follow_num,o.inquiry_cost_price,o.product_cost_price,o.total_cost_price,o.cost_discount_money,o.total_price,o.discount_money,o.pay_delivery,o.is_pay,o.remark, o.days,o.pay_price,o.pay_money,o.pay_type,o.`status`,o.package_sub_type,o.create_time,o.start_time,o.refund_status,o.finish_time,d.doctor_name,u.nick_name,u.phone,c.company_name,cu.nick_name company_user_name,patient_json->>'$.patientName' as patientName,fso.delivery_status,fso.delivery_pay_status ,csc.name miniProgramName from fs_package_order o LEFT JOIN fs_doctor d ON d.doctor_id=o.doctor_id LEFT JOIN fs_user u ON u.user_id=o.user_id LEFT JOIN company c on c.company_id =o.company_id LEFT JOIN company_user cu on cu.user_id=o.company_user_id LEFT JOIN fs_store_order fso ON fso.order_id= o.store_order_id "+
+            "LEFT JOIN (SELECT sp.*,ROW_NUMBER() OVER (PARTITION BY sp.business_code ORDER BY sp.create_time DESC) as rn\n" +
+            "        FROM fs_store_payment sp) sp_latest ON sp_latest.business_code = o.order_sn AND sp_latest.rn = 1\n" +
+            "        LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp_latest.app_id" +
             "  <where>  \n" +
             "            <if test=\"orderSn != null  and orderSn != ''\"> and o.order_sn =#{orderSn}</if>\n" +
+            "            <if test=\"coursePlaySourceConfigId != null\"> and csc.id = #{coursePlaySourceConfigId}</if>\n" +
             "            <if test=\"phone != null \">and u.phone like concat( #{phone}, '%')</if>\n" +
             "            <if test=\"doctorName != null \">and d.doctor_name like concat(#{doctorName}, '%')</if>\n" +
             "            <if test=\"packageName != null  and packageName != ''\"> and o.package_name like concat('%', #{packageName}, '%')</if>\n" +

+ 56 - 0
fs-service/src/main/java/com/fs/his/mapper/FsStoreAfterSalesMapper.java

@@ -1,6 +1,11 @@
 package com.fs.his.mapper;
 
 import java.util.List;
+import java.util.Map;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fs.company.param.FsStoreStatisticsParam;
+import com.fs.company.vo.FsStoreOrderStatisticsVO;
 import com.fs.his.domain.FsStoreAfterSales;
 import com.fs.his.domain.FsStoreAfterSalesItem;
 import com.fs.his.domain.FsStoreAfterSalesLogs;
@@ -238,4 +243,55 @@ public interface FsStoreAfterSalesMapper
             " order by so.id desc "+
             "</script>"})
     Long selectFsStoreAfterSalesExcelListVOCount(@Param("maps") FsStoreAfterSalesParam fsStoreAfterSales);
+
+    @Select({"<script> " +
+            "select u.nick_name, count(o.order_id) as order_count,sum(IFNULL(o.refund_amount,0)) as pay_price  " +
+            "from  fs_store_after_sales o " +
+            "left join company_user u on o.company_user_id=u.user_id  " +
+            "left join fs_store_order so on so.order_id=o.order_id  " +
+            "where o.status &gt; 1 " +
+            "and o.status = 4 and o.sales_status = 3" + //退款完成的订单
+            "<if test = 'maps.type != null and maps.type ==1 '> " +
+            "and TO_DAYS(o.create_time) = TO_DAYS(NOW()) " +
+            "</if>" +
+            "<if test = 'maps.type != null and maps.type ==2 '> " +
+            "and TO_DAYS(NOW()) - TO_DAYS(o.create_time) &lt;= 1 " +
+            "</if>" +
+            "<if test = 'maps.type != null and maps.type ==3 '> " +
+            "and YEARWEEK(DATE_FORMAT(o.create_time,'%Y-%m-%d')) = YEARWEEK(NOW()) " +
+            "</if>" +
+            "<if test = 'maps.type != null and maps.type ==4 '> " +
+            "and YEARWEEK(DATE_FORMAT(o.create_time,'%Y-%m-%d')) = YEARWEEK(NOW())-1 " +
+            "</if>" +
+            "<if test = 'maps.type != null and maps.type ==5 '> " +
+            "and DATE_FORMAT(o.create_time,'%Y%m') = DATE_FORMAT(CURDATE(),'%Y%m') " +
+            "</if>" +
+            "<if test = 'maps.type != null and maps.type ==6 '> " +
+            "and PERIOD_DIFF(DATE_FORMAT(NOW(),'%Y%m'),DATE_FORMAT(o.create_time,'%Y%m')) = 1 " +
+            "</if>" +
+            "<if test = 'maps.type != null and maps.type ==7 '> " +
+            "and QUARTER(o.create_time) = QUARTER(NOW()) " +
+            "</if>" +
+            "<if test = 'maps.type != null and maps.type ==8 '> " +
+            "and QUARTER(o.create_time) = QUARTER(DATE_SUB(NOW(),INTERVAL 1 QUARTER)) " +
+            "</if>" +
+            "<if test = 'maps.type != null and maps.type ==9 '> " +
+            "and YEAR(o.create_time)=YEAR(NOW()) " +
+            "</if>" +
+            "<if test = 'maps.type != null and maps.type ==10 '> " +
+            "and  YEAR(o.create_time) = YEAR(DATE_SUB(NOW(),INTERVAL 1 YEAR))" +
+            "</if>" +
+            "<if test = 'maps.startTime != null and maps.startTime != \"\" '> " +
+            "AND date_format(so.create_time,'%y%m%d') &gt;= date_format(#{maps.startTime},'%y%m%d')"+
+            "</if>" +
+            "<if test = 'maps.endTime != null and maps.endTime != \"\" '> " +
+            "AND date_format(so.create_time,'%y%m%d') &lt;= date_format(#{maps.endTime},'%y%m%d')"+
+            "</if>" +
+            "and  o.`company_user_id` IN " +
+            "<foreach  item='item' index='index' collection='maps.users' open='(' separator=',' close=')'> #{item}    </foreach>"+
+            " group by o.company_user_id "+
+            "</script>"})
+    List<FsStoreOrderStatisticsVO> selectFsPackageOrderStatisticsList(@Param("maps")FsStoreStatisticsParam param);
+
+    List<JSONObject> selectFsStoreAfterSales(Map<String, Object> map);
 }

+ 3 - 7
fs-service/src/main/java/com/fs/his/mapper/FsStoreOrderMapper.java

@@ -674,17 +674,13 @@ public interface FsStoreOrderMapper
             " left join company_user cu on cu.user_id=so.company_user_id " +
             " left join company_tcm_schedule cts on cts.id = so.schedule_id " +
             " left join fs_patient pat on pat.patient_id = p.patient_id " +
-            "LEFT JOIN (\n" +
-            "        SELECT\n" +
-            "        sp.*,\n" +
-            "        ROW_NUMBER() OVER (PARTITION BY sp.pay_code ORDER BY sp.create_time DESC) as rn\n" +
-            "        FROM fs_store_payment sp\n" +
-            "        ) sp_latest ON sp_latest.business_code = so.order_code AND sp_latest.rn = 1\n" +
+            "LEFT JOIN (SELECT sp.*,ROW_NUMBER() OVER (PARTITION BY sp.business_code ORDER BY sp.create_time DESC) as rn\n" +
+            "        FROM fs_store_payment sp) sp_latest ON sp_latest.business_code = so.order_code AND sp_latest.rn = 1\n" +
             "        LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp_latest.app_id" +
             " WHERE so.is_del=0 "+
             "            <if test=\"maps.packageSecondName != null and maps.packageSecondName != '' \"> and so.package_second_name like concat('%', #{maps.packageSecondName}, '%')</if>"+
             "            <if test=\"maps.storeId != null \"> and so.store_id = #{maps.storeId}</if>\n" +
-            "            <if test=\"maps.coursePlaySourceConfigId != null\"> and csc.id = #{maps.coursePlaySourceConfigId}</if>" +
+            "            <if test=\"maps.coursePlaySourceConfigId != null\"> and csc.id = #{maps.coursePlaySourceConfigId}</if>\n" +
             "            <if test=\"maps.source != null \"> and so.source = #{maps.source}</if>\n" +
             "            <if test=\"maps.orderCode != null  and maps.orderCode != ''\"> and so.order_code = #{maps.orderCode}</if>\n" +
             "            <if test=\"maps.prescribeCode != null  and maps.prescribeCode != ''\"> and p.prescribe_code = #{maps.prescribeCode}</if>\n" +

+ 13 - 2
fs-service/src/main/java/com/fs/his/mapper/FsStorePaymentMapper.java

@@ -70,12 +70,17 @@ public interface FsStorePaymentMapper
     public int deleteFsStorePaymentByPaymentIds(Long[] paymentIds);
 
     @Select({"<script> " +
-            "SELECT sp.*,u.nick_name,u.phone,s.store_name,c.company_name,cu.nick_name as company_user_nick_name FROM fs_store_payment sp " +
+            "SELECT sp.*,u.nick_name,u.phone,s.store_name,c.company_name,cu.nick_name as company_user_nick_name ,csc.name miniProgramName FROM fs_store_payment sp " +
             " LEFT JOIN  fs_user u ON u.user_id=sp.user_id LEFT JOIN fs_store s ON s.store_id=sp.store_id " +
             " left join company_user cu on sp.company_user_id=cu.user_id " +
             " left join company c on c.company_id=sp.company_id "+
+            "LEFT JOIN (SELECT t.* FROM ( SELECT sp2.*, ROW_NUMBER() OVER (PARTITION BY sp2.business_code ORDER BY sp2.create_time DESC, sp2.payment_id DESC) as rn " +
+            "FROM fs_store_payment sp2) t WHERE t.rn = 1) " +
+            "latest_sp ON latest_sp.business_code = sp.business_code "+
+            "LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp.app_id" +
             " where 1=1 " +
             "            <if test=\"maps.payCode != null  and maps.payCode != ''\"> and sp.pay_code = #{maps.payCode}</if>\n" +
+            "            <if test=\"maps.coursePlaySourceConfigId != null\"> and csc.id = #{maps.coursePlaySourceConfigId}</if>\n" +
             "            <if test=\"maps.payTypeCode != null  and maps.payTypeCode != ''\"> and sp.pay_type_code = #{maps.payTypeCode}</if>\n" +
             "            <if test=\"maps.businessCode != null  and maps.businessCode != ''\"> and sp.business_code = #{maps.businessCode}</if>\n" +
             "            <if test=\"maps.tradeNo != null  and maps.tradeNo != ''\"> and sp.trade_no = #{maps.tradeNo}</if>\n" +
@@ -176,7 +181,8 @@ public interface FsStorePaymentMapper
     @Select("select * from fs_store_payment where business_type=#{type} and  business_id=#{businessId} and (status=1 or starus=-1)")
     List<FsStorePayment> selectFsStorePaymentByPayOrRefund(int i, Long orderId);
     @Select({"<script> " +
-            " SELECT CONCAT('package-', sp.pay_code) AS pay_code,sp.*,u.nick_name,u.phone,s.store_name,c.company_name,cu.nick_name as companyUserName,fso.delivery_name,fso.package_name,fso.package_second_name FROM fs_store_payment sp " +
+            " SELECT CONCAT('package-', sp.pay_code) AS pay_code,sp.*,u.nick_name,u.phone,s.store_name,c.company_name,cu.nick_name as companyUserName,fso.delivery_name,fso.package_name,fso.package_second_name ,csc.name miniProgramName " +
+            " FROM fs_store_payment sp " +
             " LEFT JOIN  fs_user u ON u.user_id=sp.user_id " +
             " LEFT JOIN fs_store s ON s.store_id=sp.store_id " +
             " left join fs_store_order fso on fso.order_code = sp.business_code " +
@@ -187,9 +193,14 @@ public interface FsStorePaymentMapper
             "LEFT JOIN company_user cu ON \n" +
             "    ( cu.user_id = fso.company_user_id) OR\n" +
             "    (cu.user_id = fio.company_user_id) " +
+            "LEFT JOIN (SELECT t.* FROM ( SELECT sp2.*, ROW_NUMBER() OVER (PARTITION BY sp2.business_code ORDER BY sp2.create_time DESC, sp2.payment_id DESC) as rn " +
+            "FROM fs_store_payment sp2) t WHERE t.rn = 1) " +
+            "latest_sp ON latest_sp.business_code = sp.business_code "+
+            "LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp.app_id" +
             " where 1=1 " +
             "            <if test=\"maps.payCode != null  and maps.payCode != ''\"> and sp.pay_code = #{maps.payCode}</if>\n" +
             "            <if test=\"maps.payTypeCode != null  and maps.payTypeCode != ''\"> and sp.pay_type_code = #{maps.payTypeCode}</if>\n" +
+            "            <if test=\"maps.coursePlaySourceConfigId != null\"> and csc.id = #{maps.coursePlaySourceConfigId}</if>\n" +
             "            <if test=\"maps.businessCode != null  and maps.businessCode != ''\"> and sp.business_code = #{maps.businessCode}</if>\n" +
             "            <if test=\"maps.tradeNo != null  and maps.tradeNo != ''\"> and sp.trade_no = #{maps.tradeNo}</if>\n" +
             "            <if test=\"maps.userId != null \"> and sp.user_id = #{maps.userId}</if>\n" +

+ 88 - 0
fs-service/src/main/java/com/fs/his/mapper/RedPacketLogMapper.java

@@ -0,0 +1,88 @@
+package com.fs.his.mapper;
+
+import com.fs.his.domain.RedPacketLog;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+
+/**
+ * 红包发放日志表 Mapper接口
+ */
+@Mapper
+public interface RedPacketLogMapper {
+
+    /**
+     * 根据ID查询红包发放日志
+     *
+     * @param id 主键ID
+     * @return 红包发放日志
+     */
+    @Select("SELECT * FROM red_packet_log WHERE id = #{id}")
+    RedPacketLog selectById(Long id);
+
+    /**
+     * 查询用户红包发放日志列表
+     *
+     * @param userId 用户ID
+     * @return 红包发放日志列表
+     */
+    @Select("SELECT * FROM red_packet_log WHERE user_id = #{userId} ORDER BY create_time DESC")
+    List<RedPacketLog> selectByUserId(Long userId);
+
+    /**
+     * 查询公司红包发放日志列表
+     *
+     * @param companyId 公司ID
+     * @return 红包发放日志列表
+     */
+    @Select("SELECT * FROM red_packet_log WHERE company_id = #{companyId} ORDER BY create_time DESC")
+    List<RedPacketLog> selectByCompanyId(Long companyId);
+
+    /**
+     * 查询指定状态的红包发放日志列表
+     *
+     * @param status 状态
+     * @return 红包发放日志列表
+     */
+    @Select("SELECT * FROM red_packet_log WHERE status = #{status} ORDER BY create_time DESC")
+    List<RedPacketLog> selectByStatus(Integer status);
+
+    /**
+     * 插入红包发放日志
+     *
+     * @param redPacketLog 红包发放日志
+     * @return 影响行数
+     */
+    @Insert("INSERT INTO red_packet_log (user_id, amount, company_id, source, red_packet_mode, app_id, " +
+            "acc_balance_before, acc_balance_after, status, error_msg, create_by, update_by, remark) " +
+            "VALUES (#{userId}, #{amount}, #{companyId}, #{source}, #{redPacketMode}, #{appId}, " +
+            "#{accBalanceBefore}, #{accBalanceAfter}, #{status}, #{errorMsg}, #{createBy}, #{updateBy}, #{remark})")
+    @Options(useGeneratedKeys = true, keyProperty = "id")
+    int insert(RedPacketLog redPacketLog);
+
+    /**
+     * 更新红包发放日志
+     *
+     * @param redPacketLog 红包发放日志
+     * @return 影响行数
+     */
+    @Update("<script>" +
+            "UPDATE red_packet_log SET " +
+            "<if test='status != null'>status = #{status}, </if>" +
+            "<if test='errorMsg != null'>error_msg = #{errorMsg}, </if>" +
+            "<if test='updateBy != null'>update_by = #{updateBy}, </if>" +
+            "<if test='remark != null'>remark = #{remark}, </if>" +
+            "update_time = NOW() " +
+            "WHERE id = #{id}" +
+            "</script>")
+    int update(RedPacketLog redPacketLog);
+
+    /**
+     * 根据ID删除红包发放日志
+     *
+     * @param id 主键ID
+     * @return 影响行数
+     */
+    @Delete("DELETE FROM red_packet_log WHERE id = #{id}")
+    int deleteById(Long id);
+}

+ 2 - 1
fs-service/src/main/java/com/fs/his/param/FsInquiryOrderParam.java

@@ -129,7 +129,8 @@ public class FsInquiryOrderParam {
     private String payTimeRange;
 
     private String[] payTimeList;
-
+    //小程序id
+    private  Long coursePlaySourceConfigId;
     //部门id
     private Long deptId;
     //公司员工昵称

+ 2 - 0
fs-service/src/main/java/com/fs/his/param/FsInquiryOrderReportParam.java

@@ -46,4 +46,6 @@ public class FsInquiryOrderReportParam {
     private String patientMobile;
     private  String fzName;
     private Long taskId;//任务ID
+    // 小程序id
+    private Long coursePlaySourceConfigId;
 }

+ 1 - 0
fs-service/src/main/java/com/fs/his/param/FsIntegralOrderCreateParam.java

@@ -13,6 +13,7 @@ public class FsIntegralOrderCreateParam {
     private Long addressId;
 
     private Long goodsId;
+    private Long companyUserId;
 
 
 }

+ 2 - 0
fs-service/src/main/java/com/fs/his/param/FsPackageOrderParam.java

@@ -103,5 +103,7 @@ public class FsPackageOrderParam  extends BaseEntity{
 
     private String source;
 
+    //小程序id
+    private Long coursePlaySourceConfigId;
     private Long taskId;//任务ID
 }

+ 2 - 0
fs-service/src/main/java/com/fs/his/param/FsStorePaymentParam.java

@@ -116,6 +116,8 @@ public class FsStorePaymentParam extends BaseEntity {
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date createTime;
 
+    // 小程序ID
+    private Long coursePlaySourceConfigId;
     private String appId;
 
 }

+ 8 - 0
fs-service/src/main/java/com/fs/his/service/IFsStoreAfterSalesService.java

@@ -1,8 +1,12 @@
 package com.fs.his.service;
 
 import java.util.List;
+import java.util.Map;
 
+import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.domain.R;
+import com.fs.company.param.FsStoreStatisticsParam;
+import com.fs.company.vo.FsStoreOrderStatisticsVO;
 import com.fs.his.domain.FsStoreAfterSales;
 import com.fs.his.domain.FsStoreAfterSalesItem;
 import com.fs.his.domain.FsStoreAfterSalesLogs;
@@ -100,4 +104,8 @@ public interface IFsStoreAfterSalesService
     Long selectFsStoreAfterSalesExcelListVOCount(FsStoreAfterSalesParam fsStoreAfterSales);
 
     void exportData(FsStoreAfterSalesParam fsStoreAfterSales);
+
+    List<FsStoreOrderStatisticsVO> selectFsStoreAfterSalesServiceStatisticsList(FsStoreStatisticsParam param);
+
+    List<JSONObject> selectFsStoreAfterSales(Map<String, Object> map);
 }

+ 21 - 4
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderServiceImpl.java

@@ -2,6 +2,7 @@ package com.fs.his.service.impl;
 
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.lang.TypeReference;
+import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
@@ -15,6 +16,8 @@ import com.fs.common.exception.CustomException;
 import com.fs.common.exception.ServiceException;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.mapper.CompanyUserMapper;
 import com.fs.core.utils.OrderCodeUtils;
 import com.fs.his.domain.*;
 import com.fs.his.enums.BusinessTypeEnum;
@@ -37,6 +40,7 @@ import com.fs.ybPay.domain.OrderResult;
 import com.fs.ybPay.dto.OrderQueryDTO;
 import com.fs.ybPay.service.IPayService;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -73,6 +77,9 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
 
     @Autowired
     private QwUserMapper qwUserMapper;
+
+    @Autowired
+    private CompanyUserMapper companyUserMapper;
     @Autowired
     private IFsUserIntegralLogsService userIntegralLogsService;
     @Autowired
@@ -223,15 +230,20 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
         goodsItem.add(integralGoods);
 
         // 创建订单
-        return createOrder(user, address, integralGoods.getIntegral(),integralGoods.getCash(), goodsItem);
+        return createOrder(user, address, integralGoods.getIntegral(),integralGoods.getCash(), goodsItem,param.getCompanyUserId());
     }
 
     /**
      * 创建订单
      */
-    private R createOrder(FsUser user, FsUserAddress address, Long totalIntegral, BigDecimal totalCash, List<FsIntegralGoods> goodsItem) {
+    private R createOrder(FsUser user, FsUserAddress address, Long totalIntegral, BigDecimal totalCash, List<FsIntegralGoods> goodsItem, Long companyUserId) {
         FsIntegralOrder order = new FsIntegralOrder();
-        String orderSn = OrderCodeUtils.getOrderSn();
+        String orderSn = null;
+        try{
+            orderSn = OrderCodeUtils.getOrderSn();
+        }catch (Exception e){
+            orderSn = IdUtil.getSnowflake(0, 0).nextIdStr();
+        }
         if(StringUtils.isEmpty(orderSn)){
             throw new CustomException("订单生成失败,请重试");
         }
@@ -261,6 +273,11 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
         order.setUserAddress(address.getProvince()+address.getCity()+address.getDistrict()+address.getDetail());
         order.setUserPhone(address.getPhone());
         order.setCreateTime(new Date());
+        order.setCompanyUserId(companyUserId);
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserByCompanyUserId(companyUserId);
+        if (ObjectUtil.isNotEmpty(companyUser)){
+            order.setCompanyId(companyUser.getCompanyId());
+        }
 
         //判断当前用户是否有关联企微ID
         if(ObjectUtil.isNotNull(user.getQwUserId())){
@@ -364,7 +381,7 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
             goodsItem.add(integralGoods);
         }
 
-        return createOrder(user, address, totalIntegral, totalCash, goodsItem);
+        return createOrder(user, address, totalIntegral, totalCash, goodsItem, null);
     }
 
     @Override

+ 4 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsPackageOrderServiceImpl.java

@@ -1567,7 +1567,11 @@ public class FsPackageOrderServiceImpl implements IFsPackageOrderService
             CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                 FsStorePayment fsStorePayment = fsStorePaymentMapper.selectLastByBusinessCode(vo.getOrderSn());
                 if (fsStorePayment != null) {
+                    if (fsStorePayment.getStatus() == -1){
+                        vo.setBusinessCode("refund-" + fsStorePayment.getPayCode());
+                    }else {
                     vo.setBusinessCode("package-" + fsStorePayment.getPayCode());
+                    }
                 }
             });
             futures.add(future);

+ 25 - 12
fs-service/src/main/java/com/fs/his/service/impl/FsStoreAfterSalesServiceImpl.java

@@ -12,14 +12,17 @@ import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.company.param.FsStoreStatisticsParam;
 import com.fs.company.service.ICompanyService;
 import com.fs.company.service.impl.CompanyServiceImpl;
+import com.fs.company.vo.FsStoreOrderStatisticsVO;
 import com.fs.core.config.WxPayProperties;
 import com.fs.core.utils.OrderCodeUtils;
 import com.fs.his.config.FsSysConfig;
@@ -543,18 +546,18 @@ public class FsStoreAfterSalesServiceImpl implements IFsStoreAfterSalesService {
                 Map<String, Object> extendInfoMap = new HashMap<>();
                 extendInfoMap.put("org_req_seq_id", orderType + "-" + payment.getPayCode());
                 request.setExtendInfo(extendInfoMap);
-//                HuiFuRefundResult refund = huiFuService.refund(request);
-//                logger.info("订单退款返回结果:退款订单id:" + order.getOrderId() + refund);
-//                if ((refund.getResp_code().equals("00000000") || refund.getResp_code().equals("00000100")) && (refund.getTrans_stat().equals("S") || refund.getTrans_stat().equals("P"))) {
-//                    FsStorePayment paymentMap = new FsStorePayment();
-//                    paymentMap.setPaymentId(payment.getPaymentId());
-//                    paymentMap.setStatus(-1);
-//                    paymentMap.setRefundTime(DateUtils.getNowDate());
-//                    paymentMap.setRefundMoney(payment.getPayMoney());
-//                    fsStorePaymentMapper.updateFsStorePayment(paymentMap);
-//                } else {
-//                    throw new CustomException("退款请求失败" + refund.getResp_desc());
-//                }
+                HuiFuRefundResult refund = huiFuService.refund(request);
+                logger.info("订单退款返回结果:退款订单id:" + order.getOrderId() + refund);
+                if ((refund.getResp_code().equals("00000000") || refund.getResp_code().equals("00000100")) && (refund.getTrans_stat().equals("S") || refund.getTrans_stat().equals("P"))) {
+                    FsStorePayment paymentMap = new FsStorePayment();
+                    paymentMap.setPaymentId(payment.getPaymentId());
+                    paymentMap.setStatus(-1);
+                    paymentMap.setRefundTime(DateUtils.getNowDate());
+                    paymentMap.setRefundMoney(payment.getPayMoney());
+                    fsStorePaymentMapper.updateFsStorePayment(paymentMap);
+                } else {
+                    throw new CustomException("退款请求失败" + refund.getResp_desc());
+                }
             }
             //管易作废
             if (StringUtils.isNotEmpty(fsStoreOrder.getExtendOrderId())) {
@@ -951,4 +954,14 @@ public class FsStoreAfterSalesServiceImpl implements IFsStoreAfterSalesService {
         task.setFileUrl(result.get("msg").toString());
         fsExportTaskMapper.updateFsExportTask(task);
     }
+
+    @Override
+    public List<FsStoreOrderStatisticsVO> selectFsStoreAfterSalesServiceStatisticsList(FsStoreStatisticsParam param) {
+        return fsStoreAfterSalesMapper.selectFsPackageOrderStatisticsList(param);
+    }
+
+    @Override
+    public List<JSONObject> selectFsStoreAfterSales(Map<String, Object> map) {
+        return fsStoreAfterSalesMapper.selectFsStoreAfterSales(map);
+    }
 }

+ 194 - 35
fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java

@@ -3,7 +3,10 @@ package com.fs.his.service.impl;
 import java.lang.reflect.Field;
 import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
 import java.util.*;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
 
 import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.hutool.core.util.IdUtil;
@@ -11,6 +14,7 @@ import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.TypeReference;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.annotation.DataScope;
 import com.fs.common.annotation.Log;
@@ -45,10 +49,7 @@ import com.fs.erp.dto.ErpRefundUpdateRequest;
 import com.fs.his.domain.*;
 import com.fs.his.dto.PayConfigDTO;
 import com.fs.his.enums.PaymentMethodEnum;
-import com.fs.his.mapper.FsExportTaskMapper;
-import com.fs.his.mapper.FsStorePaymentMapper;
-import com.fs.his.mapper.FsUserMapper;
-import com.fs.his.mapper.FsUserWxMapper;
+import com.fs.his.mapper.*;
 import com.fs.his.param.FsStoreOrderParam;
 import com.fs.his.param.FsStorePaymentParam;
 import com.fs.his.param.PayOrderParam;
@@ -110,10 +111,16 @@ import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferRequ
 import me.chanjar.weixin.common.bean.WxJsapiSignature;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.mp.api.WxMpService;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.hc.core5.concurrent.CompletedFuture;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Propagation;
@@ -174,6 +181,40 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
     @Autowired
     private CloudHostProper cloudHostProper;
 
+    @Autowired
+    private RedisTemplate<String,BigDecimal> redisTemplate;
+
+    @Autowired
+    private RedisTemplate<String,Integer> redisTemplateInteger;
+    /**
+     * 红包领取数量限制 默认一个用户当天最多只能领取10个
+     */
+    @Value("${RED_PACKET_LIMIT_COUNT:10}")
+    private Integer RED_PACKET_LIMIT_COUNT;
+    @Autowired
+    private ISysConfigService sysConfigService;
+
+    /**
+     * 是否开启红包账户扣减
+     */
+    @Value("${enableRedPackAccount:0}")
+    private String ENABLE_RED_PACK_ACCOUNT;
+
+    /**
+     * 红包账户锁
+     */
+    private static final String REDPACKET_POOL_LOCK = "redpacket_pool_lock";
+
+    /**
+     * 公司红包金额
+     */
+    private static final String REDPACKET_COMPANY_MONEY = "redpacket_money";
+
+    /**
+     * 用户领取红包限制
+     */
+    private static final String REDPACKET_USER_LIMIT = "redpacket_user_limit:%s:%d";
+
     /**
      * 查询支付明细
      *
@@ -480,44 +521,162 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
     @Autowired
     private ICompanyConfigService companyConfigService;
 
+    @Autowired
+    private RedissonClient redissonClient;
+
+    @Autowired
+    private RedPacketLogMapper redPacketLogMapper;
     @Override
     @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
     public R sendRedPacket(WxSendRedPacketParam param) {
 
-        String json;
-        RedPacketConfig config = new RedPacketConfig();
-        // 根据红包模式获取配置
-        switch (param.getRedPacketMode()){
-            case 1:
-                json = configService.selectConfigByKey("redPacket.config");
-                config = JSONUtil.toBean(json, RedPacketConfig.class);
-                break;
-            case 2:
-                json = companyConfigService.selectRedPacketConfigByKey(param.getCompanyId());
-                config = JSONUtil.toBean(json, RedPacketConfig.class);
-                break;
-        }
-        //H5的用公众号的appid发,小程序的用小程序的appid来发
-        if (param.getSource()==2){
-            // 传参appId为空时,仍然使用配置里面的
-            String appId = StringUtils.isBlank(param.getAppId()) ? config.getMiniappId() : param.getAppId();
-            config.setAppId(appId);
-        }
-        logger.info("最终传参 {}",config);
-        //组合返回参数
-        R result = new R();
-        // 根据 isNew 判断使用哪种发红包方式
-        if (config.getIsNew() != null && config.getIsNew() == 1) {
-            result = sendRedPacketV3Internal(param, config);
-        } else {
-            result= sendRedPacketLegacyInternal(param, config);
+        //---------------发红包前先判断润天账户余额是否足够---------
+        RLock lock = redissonClient.getLock(REDPACKET_POOL_LOCK);
+        RedPacketLog redPacketLog = null;
+
+        try{
+            boolean locked = lock.tryLock(3, 10, TimeUnit.SECONDS);
+
+            if (!locked) {
+                logger.error("获取锁失败");
+                return R.error("[红包领取] 系统繁忙,请重试!");
+            }
+
+            FsUser user = param.getUser();
+            BigDecimal amount = param.getAmount();
+
+            if(user == null) {
+                throw new IllegalArgumentException("[发送红包] 用户id为必传参数!");
+            }
+            Long userId = user.getUserId();
+
+            // 判断当前用户是否限流
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
+            String today = sdf.format(new Date());
+            String userLimitKey = String.format(REDPACKET_USER_LIMIT, today, userId);
+            Integer userCount =  redisTemplateInteger.opsForValue().get(userLimitKey);
+
+
+            // 首次领取
+            if(userCount == null) {
+                userCount = 0;
+                long expireSeconds = getExpireSeconds();
+                redisTemplateInteger.opsForValue().set(userLimitKey, userCount, expireSeconds, TimeUnit.SECONDS);
+            }
+
+            if(userCount >= RED_PACKET_LIMIT_COUNT){
+                logger.info("[红包领取] 用户{} 领取红包已经达到最大限制!",userId);
+                return R.error("[红包领取] 当前用户当前已经领取红包已经达到限制!");
+            }
+
+
+            BigDecimal companyMoney = null;
+
+            if(StringUtils.equals(ENABLE_RED_PACK_ACCOUNT,"1")) {
+                companyMoney = redisTemplate.opsForValue().get(REDPACKET_COMPANY_MONEY);
+
+                if(ObjectUtils.isNull(companyMoney)){
+                    SysConfig sysConfig = sysConfigService.selectConfigByConfigKey("company.money");
+                    if(ObjectUtils.isNull(sysConfig)){
+                        throw new IllegalArgumentException("润天公司账户余额不能为空!请检查配置!");
+                    }
+                    String configValue = sysConfig.getConfigValue();
+                    companyMoney = new BigDecimal(configValue);
+                    logger.info("缓存公司余额为空,从数据库读取 companyMoney: {}",companyMoney);
+                }
+
+                if (companyMoney.compareTo(BigDecimal.ZERO) <= 0) {
+                    logger.info("润天账户余额: {} 不足!", companyMoney);
+                    return R.error("[红包领取] 账户余额不足,请联系管理员!");
+                }
+
+                redPacketLog = new RedPacketLog();
+                redPacketLog.setRedPacketMode(param.getRedPacketMode());
+                redPacketLog.setAmount(param.getAmount());
+                redPacketLog.setAppId(param.getAppId());
+                redPacketLog.setCompanyId(param.getCompanyId());
+                redPacketLog.setCreateTime(LocalDateTime.now());
+                redPacketLog.setUserId(userId);
+                redPacketLog.setAccBalanceBefore(companyMoney);
+                redPacketLog.setSource(param.getSource());
+            }
+
+            String json;
+            RedPacketConfig config = new RedPacketConfig();
+            // 根据红包模式获取配置
+            switch (param.getRedPacketMode()){
+                case 1:
+                    json = configService.selectConfigByKey("redPacket.config");
+                    config = JSONUtil.toBean(json, RedPacketConfig.class);
+                    break;
+                case 2:
+                    json = companyConfigService.selectRedPacketConfigByKey(param.getCompanyId());
+                    config = JSONUtil.toBean(json, RedPacketConfig.class);
+                    break;
+            }
+            //H5的用公众号的appid发,小程序的用小程序的appid来发
+            if (param.getSource()==2){
+                // 传参appId为空时,仍然使用配置里面的
+                String appId = StringUtils.isBlank(param.getAppId()) ? config.getMiniappId() : param.getAppId();
+                config.setAppId(appId);
+            }
+            logger.info("最终传参 {}",config);
+            //组合返回参数
+            R result = new R();
+            // 根据 isNew 判断使用哪种发红包方式
+            if (config.getIsNew() != null && config.getIsNew() == 1) {
+                result = sendRedPacketV3Internal(param, config);
+            } else {
+                result= sendRedPacketLegacyInternal(param, config);
+            }
+            result.put("mchId",config.getMchId()+"");
+            result.put("isNew",config.getIsNew());
+            logger.info("红包返回:{}",result);
+
+
+            if(StringUtils.equals(ENABLE_RED_PACK_ACCOUNT,"1")) {
+                // 更新账户余额
+                logger.info("[更新账户余额] 当前余额{} 更新后余额{}",companyMoney.toPlainString(),companyMoney.subtract(amount).toPlainString());
+
+                companyMoney = companyMoney.subtract(amount);
+                redisTemplate.opsForValue().set(REDPACKET_COMPANY_MONEY,companyMoney);
+
+
+                redPacketLog.setAccBalanceAfter(companyMoney);
+                redPacketLog.setUpdateTime(LocalDateTime.now());
+                redPacketLog.setStatus(1);
+            }
+
+            // 用户领取红包次数+1
+            redisTemplateInteger.opsForValue().increment(userLimitKey, 1);
+            return result;
+        }catch (Exception e){
+            logger.error("领取红包失败原因:{}", ExceptionUtils.getFullStackTrace(e),e);
+            if(redPacketLog != null) {
+                redPacketLog.setStatus(2);
+                redPacketLog.setErrorMsg(ExceptionUtils.getFullStackTrace(e));
+            }
+            throw new RuntimeException(e);
+        }finally {
+            if (lock.isHeldByCurrentThread()) {
+                lock.unlock();
+            }
+            if(redPacketLog != null) {
+                redPacketLogMapper.insert(redPacketLog);
+            }
         }
-        result.put("mchId",config.getMchId()+"");
-        result.put("isNew",config.getIsNew());
-        logger.info("红包返回:{}",result);
-        return result;
     }
 
+    private static long getExpireSeconds() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.add(Calendar.DAY_OF_YEAR, 1);
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        // 计算从现在到明天凌晨的秒数
+        return (calendar.getTimeInMillis() - System.currentTimeMillis()) / 1000;
+    }
     // 内部方法:处理新版本的发红包逻辑
     private R sendRedPacketV3Internal(WxSendRedPacketParam param, RedPacketConfig config) {
 

+ 3 - 1
fs-service/src/main/java/com/fs/his/vo/FsInquiryOrderListVO.java

@@ -107,7 +107,9 @@ public class FsInquiryOrderListVO {
     /** 问诊类型 */
     @Excel(name = "问诊类型")
     private Integer inquiryType;
-
+    //小程序名称
+    @Excel(name = "小程序名称")
+    private String miniProgramName;
     private Integer inquirySubType;
     /** 创建时间 */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")

+ 2 - 0
fs-service/src/main/java/com/fs/his/vo/FsInquiryOrderReportListVO.java

@@ -101,6 +101,8 @@ public class FsInquiryOrderReportListVO {
     private  String DiseaseName;
     @Excel(name = "分诊人名称")
     private  String fzName;
+    @Excel(name = "小程序姓名")
+    private String miniProgramName;
 
 
 }

+ 1 - 0
fs-service/src/main/java/com/fs/his/vo/FsIntegralGoodsListVO.java

@@ -22,6 +22,7 @@ public class FsIntegralGoodsListVO {
     /** 商品名称 */
     @Excel(name = "商品名称")
     private String goodsName;
+    private String barCode;
 
     /** 原价 */
     @Excel(name = "原价")

+ 2 - 0
fs-service/src/main/java/com/fs/his/vo/FsPackageOrderExcelVO.java

@@ -117,4 +117,6 @@ public class FsPackageOrderExcelVO {
     private Integer deliveryPayStatus;
     @Excel(name = "来源",dictType="sys_order_source")
     private Integer source;
+    @Excel(name = "微信小程序姓名")
+    private String miniProgramName;
 }

+ 3 - 0
fs-service/src/main/java/com/fs/his/vo/FsPackageOrderListVO.java

@@ -83,6 +83,9 @@ public class FsPackageOrderListVO {
     private Integer deliveryStatus;
     @Excel(name = "物流状态")
     private Integer deliveryPayStatus;
+    //小程序名称
+    @Excel(name = "小程序名称")
+    private String miniProgramName;
     private Integer packageSubType;
     private BigDecimal inquiryPrice;
     private BigDecimal productPrice;

+ 8 - 0
fs-service/src/main/java/com/fs/his/vo/FsStorePaymentExcelVO.java

@@ -84,4 +84,12 @@ public class FsStorePaymentExcelVO {
 
     @Excel(name = "套餐包别名")
     private String packageSecondName;
+
+    // 小程序名称
+    @Excel(name = "小程序名称")
+    private String miniProgramName;
+
+
+
+
 }

+ 4 - 2
fs-service/src/main/java/com/fs/his/vo/FsStorePaymentVO.java

@@ -85,8 +85,8 @@ public class FsStorePaymentVO {
     /** 创建时间 */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date createTime;
-
-
+   // 小程序id
+    private Long coursePlaySourceConfigId;
     /** 更新时间 */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date updateTime;
@@ -103,4 +103,6 @@ public class FsStorePaymentVO {
     private Integer shareStatus;
     private String shareCode;
     private BigDecimal shareMoney;
+    // 小程序名称
+    private String miniProgramName;
 }

+ 2 - 0
fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreCartScrmMapper.java

@@ -73,7 +73,9 @@ public interface FsStoreCartScrmMapper
             "v.price,v.sku as product_attr_name,v.image as product_attr_image,v.stock " +
             "from fs_store_cart_scrm c " +
             "inner join fs_store_product_scrm p on p.product_id=c.product_id " +
+            "<if test='config.isStores == \"1\"'>" +
             "inner join fs_store_scrm fs on fs.store_id = p.store_id " +
+            "</if>" +
             "<if test='config.isAudit == \"1\"'>" +
             "and fs.is_audit = 1 " +
             "</if>" +

+ 11 - 46
fs-service/src/main/java/com/fs/hisStore/mapper/FsStoreProductScrmMapper.java

@@ -1,6 +1,7 @@
 package com.fs.hisStore.mapper;
 
 import java.util.List;
+import java.util.Map;
 
 import com.fs.his.param.FsStoreProductListSParam;
 import com.fs.his.vo.FsStoreProductListSVO;
@@ -180,7 +181,9 @@ public interface FsStoreProductScrmMapper
     @Select({"<script> " +
             "select p.* from fs_store_product_scrm p  " +
             //新增审核状态及所属店铺审核状态
+            "<if test = 'maps.isStores != null and maps.isStores == 1   '>"+
             "inner join fs_store_scrm fs on fs.store_id = p.store_id and fs.is_audit = 1 " +
+            "</if>" +
             "where p.is_del=0 and p.is_show=1  and p.is_audit = '1'" +
             "<if test = 'maps.productName != null and  maps.productName !=\"\"    '> " +
             "and (p.product_name like CONCAT('%',#{maps.productName},'%')  or p.keyword like concat('%',#{maps.productName},'%') ) " +
@@ -242,58 +245,22 @@ public interface FsStoreProductScrmMapper
     @Update("update fs_store_product_scrm set stock=stock+#{num}, sales=sales-#{num}" +
             " where product_id=#{productId}")
     int incStockDecSales( @Param("num")Long num, @Param("productId")Long productId);
-    @Select({"<script> " +
-            "select p.* from fs_store_product_scrm p " +
+
+    List<FsStoreProductListQueryVO> selectFsStoreProductNewQuery(Map<String, Object> params);
+
+    List<FsStoreProductListQueryVO> selectFsStoreProductHotQuery(Map<String, Object> params);
+    @Select("select p.* from fs_store_product_scrm p " +
             //新增审核状态及所属店铺审核状态
             "<if test='config.isAudit == \"1\" '>" +
             "inner join fs_store_scrm fs on fs.store_id = p.store_id and fs.is_audit = 1 " +
             "</if>" +
-            " where p.is_del=0 and p.is_show=1 " +
+            "where p.is_del=0 and p.is_show=1 " +
             "<if test='config.isAudit == \"1\" '>" +
-            " and p.is_audit = '1'  " +
+            "and p.is_audit = '1'" +
             "</if>" +
-            " and  p.is_new=1 and p.is_display=1 order by p.sort desc limit #{count} " +
-            "</script>"})
-    List<FsStoreProductListQueryVO> selectFsStoreProductNewQuery(@Param("count")int count,@Param("config") MedicalMallConfig  config);
-    @Select({"<script> " +
-            "select p.* from fs_store_product_scrm p " +
-            //新增审核状态及所属店铺审核状态
-            "<if test='config.isAudit == \"1\" '>" +
-            " inner join fs_store_scrm fs on fs.store_id = p.store_id and fs.is_audit = 1 " +
-            "</if>" +
-            " where p.is_del=0 and p.is_show=1 " +
-            "<if test='config.isAudit == \"1\" '>" +
-            " and p.is_audit = '1' " +
-            "</if>" +
-            "and  p.is_hot=1 and p.is_display=1 order by p.sort desc limit #{count}" +
-            "</script>"})
-    List<FsStoreProductListQueryVO> selectFsStoreProductHotQuery(@Param("count") int count,@Param("config") MedicalMallConfig  config);
-    @Select({"<script> " +
-            "select p.* from fs_store_product_scrm p " +
-            //新增审核状态及所属店铺审核状态
-            "<if test='config.isAudit == \"1\" '>" +
-            " inner join fs_store_scrm fs on fs.store_id = p.store_id and fs.is_audit = 1 " +
-            "</if>" +
-            " where p.is_del=0 and p.is_show=1 " +
-            "<if test='config.isAudit == \"1\" '>" +
-            " and p.is_audit = '1' " +
-            "</if>" +
-            " and  p.is_good=1 and p.is_display=1 order by p.sort desc limit #{count}" +
-            "</script>"})
+            "and  p.is_good=1 and p.is_display=1 order by p.sort desc limit #{count}")
     List<FsStoreProductListQueryVO> selectFsStoreProductGoodQuery(int count,@Param("config") MedicalMallConfig  config);
     List<FsStoreProductListQueryVO> selectFsStoreProductTuiListQuery(@Param("config") MedicalMallConfig  config);
-    @Select({"<script> " +
-            "select p.* from fs_store_product_scrm p " +
-            //新增审核状态及所属店铺审核状态
-            "<if test='config.isAudit == \"1\" '>" +
-            " inner join fs_store_scrm fs on fs.store_id = p.store_id and fs.is_audit = 1 " +
-            "</if>" +
-            " where p.is_del=0 and p.is_show=1 " +
-            "<if test='config.isAudit == \"1\" '>" +
-            " and p.is_audit = '1' " +
-            "</if>" +
-            " and  p.is_good=1 and p.is_display=1 order by p.sort desc" +
-            "</script>"})
     List<FsStoreProductListQueryVO> selectFsStoreProductGoodListQuery(@Param("config") MedicalMallConfig  config);
     @Select({"<script> " +
             "select count(1) from fs_store_product_scrm  " +
@@ -408,6 +375,4 @@ public interface FsStoreProductScrmMapper
     List<FsStoreProductActivityListVO> selectFsStoreProductByIdsAudit(String productIds,@Param("config") MedicalMallConfig  config);
 
     List<FsStoreProductScrm> bulkCopyFsStoreProductByIds(Long[] productIds);
-
-    List<FsStoreProductScrm> getStoreProductInProductIds(List<Long> productIds);
 }

+ 3 - 0
fs-service/src/main/java/com/fs/hisStore/param/FsStoreProductQueryParam.java

@@ -32,4 +32,7 @@ public class FsStoreProductQueryParam extends BaseQueryParam implements Serializ
     private Integer isDrug;
     //店铺id
     private Long storeId;
+
+    //是否多店铺 1是
+    private Integer isStores;
 }

+ 13 - 10
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreAfterSalesScrmServiceImpl.java

@@ -11,6 +11,7 @@ import com.fs.common.annotation.DataScope;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
+import com.fs.common.utils.CloudHostUtils;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.spring.SpringUtils;
@@ -282,7 +283,8 @@ public class FsStoreAfterSalesScrmServiceImpl implements IFsStoreAfterSalesScrmS
             return R.error("未支付订单不能申请售后");
         }
         if("1".equals(configUtil.generateConfigByKey(SysConfigEnum.HIS_CONFIG.getKey()).getString("erpOpen"))
-                && StringUtils.isEmpty(order.getExtendOrderId())){
+                && StringUtils.isEmpty(order.getExtendOrderId())
+                && !CloudHostUtils.hasCloudHostName("康年堂")){
             logger.info("erpOpen:{}",configUtil.generateConfigByKey(SysConfigEnum.HIS_CONFIG.getKey()).getString("erpOpen"));
             return R.error("仓库未生成订单,暂时不能申请退款,请联系客服");
         }
@@ -388,16 +390,17 @@ public class FsStoreAfterSalesScrmServiceImpl implements IFsStoreAfterSalesScrmS
         request.setOid(order.getOrderCode());
         request.setRefund_state(1);
         request.setStoreAfterSalesId(storeAfterSales.getId());
-        request.setOrderStatus(orderStatus);
-        BaseResponse response=erpOrderService.refundUpdateScrm(request);
-        if(response.getSuccess()){
-            return R.ok("提交售后退款订单成功");
-        }
-        else{
-            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
-            return R.error(response.getErrorDesc());
+        if (StringUtils.isNotBlank(order.getExtendOrderId())){
+            BaseResponse response=erpOrderService.refundUpdateScrm(request);
+            if(response.getSuccess()){
+                return R.ok();
+            }
+            else{
+                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                return R.error(response.getErrorDesc());
+            }
         }
-
+        return R.ok();
     }
 
     private IErpOrderService getErpService() {

+ 11 - 2
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreOrderScrmServiceImpl.java

@@ -24,6 +24,7 @@ import com.fs.common.event.TemplateEvent;
 import com.fs.common.event.TemplateListenEnum;
 import com.fs.common.exception.CustomException;
 import com.fs.common.exception.ServiceException;
+import com.fs.common.utils.CloudHostUtils;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.IpUtil;
 import com.fs.common.utils.ServletUtils;
@@ -2030,7 +2031,10 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
         if (order.getStatus() != 1 && order.getStatus() != 2) {
             return R.error("非法操作");
         }
-        if (erpConfig.getErpOpen() != null && erpConfig.getErpOpen() == 1 && order.getExtendOrderId() == null) {
+        if (erpConfig.getErpOpen() != null
+                && erpConfig.getErpOpen() == 1
+                && order.getExtendOrderId() == null
+                && !CloudHostUtils.hasCloudHostName("康年堂")) {
             return R.error("暂未推送至erp,请稍后再试!");
         }
         if (StringUtils.isNotEmpty(order.getExtendOrderId())) {
@@ -2088,7 +2092,12 @@ public class FsStoreOrderScrmServiceImpl implements IFsStoreOrderScrmService {
             //将钱退还给用户
             List<FsStorePaymentScrm> payments = paymentService.selectFsStorePaymentByOrderId(order.getId());
             if (payments != null) {
-                String json = configService.selectConfigByKey("store.pay");
+                String json;
+                if (CloudHostUtils.hasCloudHostName("康年堂")) {
+                    json = configService.selectConfigByKey("his.pay");
+                } else {
+                    json = configService.selectConfigByKey("store.pay");
+                }
                 FsPayConfigScrm fsPayConfig = JSON.parseObject(json, FsPayConfigScrm.class);
                 for (FsStorePaymentScrm payment : payments) {
                     if (payment.getPayMode() == null || payment.getPayMode().equals("wx")) {

+ 11 - 3
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStoreProductScrmServiceImpl.java

@@ -338,7 +338,7 @@ public class FsStoreProductScrmServiceImpl implements IFsStoreProductScrmService
         product.setStoreId(param.getStoreId());
         product.setIsDrug(param.getIsDrug().toString());
         //校验店铺资质信息
-        if(!("益善缘".equals(cloudHostProper.getCompanyName()))){
+        if(!("益善缘".equals(cloudHostProper.getCompanyName())) && !("康年堂".equals(cloudHostProper.getCompanyName()))){
             //获取店铺
             FsStoreScrm store = fsStoreScrmService.selectFsStoreByStoreId(product.getStoreId());
             if(store == null || 1 != store.getStatus()){
@@ -684,6 +684,8 @@ public class FsStoreProductScrmServiceImpl implements IFsStoreProductScrmService
 
     @Override
     public List<FsStoreProductListQueryVO> selectFsStoreProductListQuery(FsStoreProductQueryParam param) {
+        boolean stores = medicalMallConfig.isStores();
+        param.setIsStores(stores?1:0);
         return fsStoreProductMapper.selectFsStoreProductListQuery(param);
     }
 
@@ -713,12 +715,18 @@ public class FsStoreProductScrmServiceImpl implements IFsStoreProductScrmService
 
     @Override
     public List<FsStoreProductListQueryVO> selectFsStoreProductNewQuery(int count) {
-        return fsStoreProductMapper.selectFsStoreProductNewQuery(count,medicalMallConfig);
+        HashMap<String, Object> map = new HashMap<>();
+        map.put("count", count);
+        map.put("config", medicalMallConfig);
+        return fsStoreProductMapper.selectFsStoreProductNewQuery(map);
     }
 
     @Override
     public List<FsStoreProductListQueryVO> selectFsStoreProductHotQuery(int count) {
-        return fsStoreProductMapper.selectFsStoreProductHotQuery(count,medicalMallConfig);
+        HashMap<String, Object> map = new HashMap<>();
+        map.put("count", count);
+        map.put("config", medicalMallConfig);
+        return fsStoreProductMapper.selectFsStoreProductHotQuery(map);
     }
 
     @Override

+ 1 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactMapper.java

@@ -235,6 +235,7 @@ public interface QwExternalContactMapper extends BaseMapper<QwExternalContact> {
             "            <if test=\"userId != null  and userId != ''\"> and ec.user_id   like concat( #{userId}, '%') </if>\n" +
             "            <if test=\"qwUserName != null  and qwUserName != ''\"> and qu.qw_user_name   like concat( #{qwUserName}, '%') </if>\n" +
             "            <if test=\"externalUserId != null  and externalUserId != ''\"> and ec.external_user_id = #{externalUserId}</if>\n" +
+            "            <if test=\"wayId != null  and wayId != ''\"> and  SUBSTRING_INDEX(ec.state, ':', -1) = #{wayId} </if>\n" +
             "            <if test=\"name != null  and name != ''\"> and ec.name like concat( #{name}, '%')</if>\n" +
             "            <if test=\"type != null \"> and ec.type = #{type}</if>\n" +
             "            <if test=\"gender != null \"> and ec.gender = #{gender}</if>\n" +

+ 64 - 18
fs-service/src/main/java/com/fs/qw/mapper/QwFriendWelcomeMapper.java

@@ -55,25 +55,71 @@ public interface QwFriendWelcomeMapper
      * @param qwFriendWelcomeParam 好友欢迎语
      * @return 好友欢迎语集合
      */
+//    @Select("<script> " +
+//            "select  qfw.*  from qw_friend_welcome qfw " +
+//            "left join qw_user qu  ON FIND_IN_SET(qu.id,REPLACE(REPLACE(REPLACE(qfw.qw_user_ids, '[', ''), ']', ''), ' ', '')) > 0 " +
+//            "LEFT JOIN company_user cu on  cu.user_id =qu.company_user_id " +
+//            "        <where>  \n" +
+//            "            <if test=\"qwUserIds != null  and qwUserIds != ''\"> and  FIND_IN_SET(#{qwUserIds},REPLACE(REPLACE(REPLACE(qw_user_ids, '[', ''), ']', ''), ' ', '')) > 0 </if>\n" +
+//            "            <if test=\"isSendMsg != null \"> and qfw.is_send_msg = #{isSendMsg}</if>\n" +
+//            "            <if test=\"welcomeText != null  and welcomeText != ''\"> and qfw.welcome_text = #{welcomeText}</if>\n" +
+//            "            <if test=\"isDayparting != null \"> and qfw.is_dayparting = #{isDayparting}</if>\n" +
+//            "            <if test=\"companyId != null \"> and qfw.company_id = #{companyId}</if>\n" +
+//            "            <if test=\"createTime != null \"> and qfw.create_time = #{createTime}</if>\n" +
+//            "            <if test=\"updateTime != null \"> and qfw.update_time = #{updateTime}</if>\n" +
+//            "            <if test=\"companyUserId != null \"> and qu.company_user_id = #{companyUserId}</if>\n" +
+//            "            <if test=\"cuDeptIdList != null and !cuDeptIdList.isEmpty() and  userType != '00' \">" +
+//            "               AND cu.dept_id IN " +
+//            "                   <foreach collection='cuDeptIdList' item='item' open='(' separator=',' close=')'> " +
+//            "                       #{item} " +
+//            "                   </foreach> " +
+//            "            </if>" +
+//            "        </where>" +
+//            "</script>")
+//    public List<QwFriendWelcome> selectQwFriendWelcomeListMyVO(QwFriendWelcomeParam qwFriendWelcomeParam);
     @Select("<script> " +
-            "select  qfw.*  from qw_friend_welcome qfw " +
-            "left join qw_user qu  ON FIND_IN_SET(qu.id,REPLACE(REPLACE(REPLACE(qfw.qw_user_ids, '[', ''), ']', ''), ' ', '')) > 0 " +
-            "        <where>  \n" +
-            "            <if test=\"qwUserIds != null  and qwUserIds != ''\"> and  FIND_IN_SET(#{qwUserIds},REPLACE(REPLACE(REPLACE(qw_user_ids, '[', ''), ']', ''), ' ', '')) > 0 </if>\n" +
-            "            <if test=\"isSendMsg != null \"> and qfw.is_send_msg = #{isSendMsg}</if>\n" +
-            "            <if test=\"welcomeText != null  and welcomeText != ''\"> and qfw.welcome_text = #{welcomeText}</if>\n" +
-            "            <if test=\"isDayparting != null \"> and qfw.is_dayparting = #{isDayparting}</if>\n" +
-            "            <if test=\"companyId != null \"> and qfw.company_id = #{companyId}</if>\n" +
-            "            <if test=\"createTime != null \"> and qfw.create_time = #{createTime}</if>\n" +
-            "            <if test=\"updateTime != null \"> and qfw.update_time = #{updateTime}</if>\n" +
-            "            <if test=\"companyUserId != null \"> and qu.company_user_id = #{companyUserId}</if>\n" +
-            "            <if test=\"cuDeptIdList != null and !cuDeptIdList.isEmpty() and  userType != '00' \">" +
-            "               AND cu.dept_id IN " +
-            "                   <foreach collection='cuDeptIdList' item='item' open='(' separator=',' close=')'> " +
-            "                       #{item} " +
-            "                   </foreach> " +
-            "            </if>" +
-            "        </where>" +
+            "SELECT qfw.* FROM qw_friend_welcome qfw " +
+            "WHERE " +
+            "   <if test=\"qwUserIds != null and qwUserIds != ''\"> " +
+            "       EXISTS ( " +
+            "           SELECT 1 FROM qw_user qu " +
+            "           JOIN company_user cu ON cu.user_id = qu.company_user_id " +
+            "           WHERE FIND_IN_SET(qu.id, REPLACE(REPLACE(REPLACE(qfw.qw_user_ids, '[', ''), ']', ''), ' ', '')) > 0 " +
+            "           AND qu.id = #{qwUserIds} " +
+            "       ) AND " +
+            "   </if>" +
+            "   <if test=\"isSendMsg != null\"> qfw.is_send_msg = #{isSendMsg} AND </if>" +
+            "   <if test=\"welcomeText != null and welcomeText != ''\"> qfw.welcome_text = #{welcomeText} AND </if>" +
+            "   <if test=\"isDayparting != null\"> qfw.is_dayparting = #{isDayparting} AND </if>" +
+            "   <if test=\"companyId != null\"> qfw.company_id = #{companyId} AND </if>" +
+            "   <if test=\"corpId != null\"> " +
+            "       EXISTS ( " +
+            "           SELECT 1 FROM qw_user qu " +
+            "           JOIN company_user cu ON cu.user_id = qu.company_user_id " +
+            "           WHERE FIND_IN_SET(qu.id, REPLACE(REPLACE(REPLACE(qfw.qw_user_ids, '[', ''), ']', ''), ' ', '')) > 0 " +
+            "           AND qu.corp_id = #{corpId} " +
+            "       ) AND " +
+            "   </if>" +
+            "   <if test=\"companyUserId != null\"> " +
+            "       EXISTS ( " +
+            "           SELECT 1 FROM qw_user qu " +
+            "           JOIN company_user cu ON cu.user_id = qu.company_user_id " +
+            "           WHERE FIND_IN_SET(qu.id, REPLACE(REPLACE(REPLACE(qfw.qw_user_ids, '[', ''), ']', ''), ' ', '')) > 0 " +
+            "           AND qu.company_user_id = #{companyUserId} " +
+            "       ) AND " +
+            "   </if>" +
+            "   <if test=\"cuDeptIdList != null and !cuDeptIdList.isEmpty() and userType != '00'\"> " +
+            "       EXISTS ( " +
+            "           SELECT 1 FROM qw_user qu " +
+            "           JOIN company_user cu ON cu.user_id = qu.company_user_id " +
+            "           WHERE FIND_IN_SET(qu.id, REPLACE(REPLACE(REPLACE(qfw.qw_user_ids, '[', ''), ']', ''), ' ', '')) > 0 " +
+            "           AND cu.dept_id IN " +
+            "               <foreach collection='cuDeptIdList' item='item' open='(' separator=',' close=')'> " +
+            "                   #{item} " +
+            "               </foreach> " +
+            "       ) AND " +
+            "   </if>" +
+            "   1=1 "+
             "</script>")
     public List<QwFriendWelcome> selectQwFriendWelcomeListMyVO(QwFriendWelcomeParam qwFriendWelcomeParam);
 

+ 1 - 0
fs-service/src/main/java/com/fs/qw/param/QwExternalContactParam.java

@@ -99,6 +99,7 @@ public class QwExternalContactParam {
     private String stageStatus;
     private String isBind;
     private String isBindMini;
+    private Long wayId;
 
     @JsonFormat(pattern = "yyyy-MM-dd")
     private Date createTime;

+ 5 - 0
fs-service/src/main/java/com/fs/statis/domain/FsStatisSalerWatch.java

@@ -24,6 +24,11 @@ public class FsStatisSalerWatch {
      */
     private Long id;
 
+    private Long companyId;
+
+    @Excel(name = "所属公司")
+    private String companyName;
+
     /**
      * 部门
      */

+ 6 - 0
fs-service/src/main/java/com/fs/system/mapper/SysUserMapper.java

@@ -1,6 +1,8 @@
 package com.fs.system.mapper;
 
 import java.util.List;
+import java.util.Map;
+
 import org.apache.ibatis.annotations.Param;
 import com.fs.common.core.domain.entity.SysUser;
 
@@ -19,6 +21,10 @@ public interface SysUserMapper
      */
     public List<SysUser> selectUserList(SysUser sysUser);
 
+    public  Long  selectUserCount(SysUser sysUser);
+
+    public  List<Long>  selectUserIdsWithPage(Map<String, Object> params);
+    public  List<SysUser>  selectUserListByIds(List<Long> userIds);
     /**
      * 根据条件分页查询未已配用户角色列表
      * 

+ 9 - 0
fs-service/src/main/java/com/fs/system/service/ISysUserService.java

@@ -17,7 +17,16 @@ public interface ISysUserService
      * @return 用户信息集合信息
      */
     public List<SysUser> selectUserList(SysUser user);
+    /**
+     * 根据条件分页查询已分配用户角色列表
+     *
+     * @param user 用户信息
+     * @return 用户信息集合信息
+     */
+    public Long selectUserCount(SysUser user);
+    public List<Long> selectUserIdsWithPage(SysUser user, int pageNum, int pageSize);
 
+    public List<SysUser> selectUserListByIds(List<Long> userIds);
     /**
      * 根据条件分页查询已分配用户角色列表
      * 

+ 22 - 0
fs-service/src/main/java/com/fs/system/service/impl/SysUserServiceImpl.java

@@ -1,7 +1,10 @@
 package com.fs.system.service.impl;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -66,7 +69,26 @@ public class SysUserServiceImpl implements ISysUserService
     {
         return userMapper.selectUserList(user);
     }
+    @Override
+    @DataScope(deptAlias = "d", userAlias = "u")
+    public Long selectUserCount(SysUser user)
+    {
 
+        return userMapper.selectUserCount(user);
+    }
+    public List<Long> selectUserIdsWithPage(SysUser user, int pageNum, int pageSize){
+        Map<String, Object> params = new HashMap<>();
+        params.put("user", user);
+        params.put("startRow", (pageNum - 1) * pageSize);
+        params.put("pageSize", pageSize);
+        return userMapper.selectUserIdsWithPage(params);
+    }
+    @Override
+    @DataScope(deptAlias = "d", userAlias = "u")
+    public List<SysUser> selectUserListByIds(List<Long> userIds)
+    {
+        return userMapper.selectUserListByIds(userIds);
+    }
     /**
      * 根据条件分页查询已分配用户角色列表
      * 

+ 1 - 0
fs-service/src/main/resources/application-config-bly.yml

@@ -133,6 +133,7 @@ ipad:
   ipadUrl:
   aiApi:
   voiceApi:
+  commonApi:
 wx_miniapp_temp:
   pay_order_temp_id: VXEvKaGNPFuJmhWK9O_QPrTZxe9umDCukq-maI8Vdek
   inquiry_temp_id: 9POPYeqhI48LOPvq-Rfoklze7H-9SlunJKh10Qt4_2I

+ 1 - 0
fs-service/src/main/resources/application-config-dev.yml

@@ -106,6 +106,7 @@ ipad:
   ipadUrl: http://ipad.cdwjyyh.com
   aiApi: http://152.136.202.157:3000/api
   voiceApi:
+  commonApi:
 wx_miniapp_temp:
   pay_order_temp_id:
   inquiry_temp_id:

+ 5 - 3
fs-service/src/main/resources/application-config-druid-czt.yml

@@ -83,11 +83,13 @@ headerImg:
   imgUrl:
 
 ipad:
-  ipadUrl: http://ipad.cdwjyyh.com
+  ipadUrl: http://ipad.cykbja.cn
   aiApi: 1212121212
-
+  commonApi:
+  voiceApi:
 wx_miniapp_temp:
   pay_order_temp_id:
   inquiry_temp_id:
 
-
+# 0 代表关闭 1代表开启(润天老商户号的扣款限制)
+enableRedPackAccount: 1

+ 4 - 4
fs-service/src/main/resources/application-config-druid-hst.yml

@@ -42,8 +42,8 @@ wx:
       port: 6379
       timeout: 2000
     configs:
-      - appId:  wxd0a67578869950ab # 第一个公众号的appid
-        secret: 645f649be6d748e33e71cefec2469e86  # 公众号的appsecret
+      - appId:  wx101a468ce64edb84 # 第一个公众号的appid
+        secret: cdf439b08e520590ea721166e968c6d4  # 公众号的appsecret
         token: PPKOdAlCoMO # 接口配置里的Token值
         aesKey: Eswa6VjwtVMCcw03qZy6fWllgrv5aytIA1SZPEU0kU2 # 接口配置里的EncodingAESKey值
 aifabu:  #爱链接
@@ -60,8 +60,8 @@ watch:
   password3: v9xsKuqn_$d2y
 
 fs :
-  commonApi: http://172.17.0.10:8010
-  h5CommonApi: http://172.17.0.10:8010
+  commonApi: http://172.16.0.26:7771
+  h5CommonApi: http://172.16.0.26:7771
 nuonuo:
   key: 10924508
   secret: A2EB20764D304D16

+ 1 - 0
fs-service/src/main/resources/application-config-druid-jnmy.yml

@@ -88,6 +88,7 @@ ipad:
   ipadUrl: http://qwipad.jnmyunl.com
   aiApi: http://49.232.181.28:3000/api
   voiceApi: http://139.186.176.122:8009
+  commonApi: http://139.186.176.122:7771
 wx_miniapp_temp:
   pay_order_temp_id: -SjnK9K6cNKASa6AD9Q_c0YT7J1lPTEpPIpqbMJF8F0
   inquiry_temp_id: hwFXVh0AWqeasBsZpa0-urb3CrPeYEwBiy3P6AMMGFQ

+ 5 - 5
fs-service/src/main/resources/application-config-druid-knt.yml

@@ -23,13 +23,13 @@ wx:
         token: PPKOdAlCoMO
         aesKey: PKvaxtpSv8NGpfTDm7VUHIK8Wok2ESyYX24qpXJAdMP
   pay:
-    appId: wx7cf96953a4be5181 #微信公众号或者小程序等的appid
-    mchId: 1611402045 #微信支付商户号
+    appId: wx1de020b57c05a990 #微信公众号或者小程序等的appid
+    mchId: 1723480901 #微信支付商户号:陕西康年堂医药连锁有限公司
     mchKey: 8cab128997a3547c1363b0898b877f38 #微信支付商户密钥
     subAppId:  #服务商模式下的子商户公众账号ID
     subMchId:  #服务商模式下的子商户号
     keyPath: c:\\cert\\apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
-    notifyUrl: https://userapp.his.runtzh.com/app/wxpay/wxPayNotify
+    notifyUrl: https://userapp.kangniantangyiyao.top/app/wxpay/wxPayNotify
   mp:
     useRedis: false
     redisConfig:
@@ -58,8 +58,8 @@ watch:
   password3: v9xsKuqn_$d2y
 
 fs :
-  commonApi: http://192.168.0.18:7771
-  h5CommonApi: http://192.168.0.18:7771
+  commonApi: http://192.168.0.196:7771
+  h5CommonApi: http://192.168.0.196:7771
 nuonuo:
   key: 10924508
   secret: A2EB20764D304D16

+ 153 - 0
fs-service/src/main/resources/application-druid-bnkc-test.yml

@@ -0,0 +1,153 @@
+# 数据源配置
+spring:
+    profiles:
+        include: config-druid-bnkc,common
+    # redis 配置
+    redis:
+        host: 127.0.0.1
+        port: 6379
+        # 数据库索引
+        database: 0
+        # 密码
+        password:
+        # 连接超时时间
+        timeout: 10s
+        lettuce:
+            pool:
+                # 连接池中的最小空闲连接
+                min-idle: 0
+                # 连接池中的最大空闲连接
+                max-idle: 8
+                # 连接池的最大数据库连接数
+                max-active: 100
+                # #连接池最大阻塞等待时间(使用负值表示没有限制)
+                max-wait: -1ms
+    datasource:
+#        clickhouse:
+#            type: com.alibaba.druid.pool.DruidDataSource
+#            driverClassName: com.clickhouse.jdbc.ClickHouseDriver
+#            url: jdbc:clickhouse://1.14.104.71:8123/sop_test?compress=0&use_server_time_zone=true&use_client_time_zone=false&timezone=Asia/Shanghai
+#            username: rt_2024
+#            password: Yzx_19860213
+#            initialSize: 10
+#            maxActive: 100
+#            minIdle: 10
+#            maxWait: 6000
+        mysql:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                  url: jdbc:mysql://nj-cdb-n80v6uox.sql.tencentcdb.com:22935/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                  username: root
+                  password: Ylrz_1q2w3e4r5t6y
+                # 从库数据源
+                slave:
+                    # 从数据源开关/默认关闭
+                    enabled: false
+                    url:
+                    username:
+                    password:
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+        sop:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://nj-cdb-n80v6uox.sql.tencentcdb.com:22935/fs_his_sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Ylrz_1q2w3e4r5t6y
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+rocketmq:
+    name-server: rmq-16xj8o92zp.rocketmq.cd.qcloud.tencenttdmq.com:8080
+    producer:
+        group: my-producer-group
+        access-key: ak16xj8o92zp984557f83ba2 # 替换为实际的 accessKey
+        secret-key: sk2ff1c6b15b74b888 # 替换为实际的 secretKey
+    consumer:
+        group: common-group
+        access-key: ak16xj8o92zp984557f83ba2 # 替换为实际的 accessKey
+        secret-key: sk2ff1c6b15b74b888 # 替换为实际的 secretKey
+openIM:
+    secret: openIM123
+    userID: imAdmin
+#是否为新商户,新商户不走mpOpenId
+isNewWxMerchant: true

+ 4 - 1
fs-service/src/main/resources/application-druid-hst.yml

@@ -141,5 +141,8 @@ rocketmq:
 openIM:
   secret: op
   userID: im
+
 #是否为新商户,新商户不走mpOpenId
-isNewWxMerchant: true
+isNewWxMerchant: false
+
+enableRedPackAccount: 1

+ 162 - 0
fs-service/src/main/resources/application-druid-knt-test.yml

@@ -0,0 +1,162 @@
+# 数据源配置
+spring:
+    profiles:
+        include: config-druid-knt,common
+    # redis 配置
+    redis:
+        # 地址
+        host: 127.0.0.1
+        # 端口,默认为6379
+        port: 6379
+        # 数据库索引
+        database: 3
+        # 密码
+        password:
+        # 连接超时时间
+        timeout: 20s
+        lettuce:
+            pool:
+                # 连接池中的最小空闲连接
+                min-idle: 0
+                # 连接池中的最大空闲连接
+                max-idle: 8
+                # 连接池的最大数据库连接数
+                max-active: 8
+                # #连接池最大阻塞等待时间(使用负值表示没有限制)
+                max-wait: -1ms
+    datasource:
+        #        clickhouse:
+        #            type: com.alibaba.druid.pool.DruidDataSource
+        #            driverClassName: com.clickhouse.jdbc.ClickHouseDriver
+        #            url: jdbc:clickhouse://cc-2vc8zzo26w0l7m2l6.public.clickhouse.ads.aliyuncs.com/sop?compress=0&use_server_time_zone=true&use_client_time_zone=false&timezone=Asia/Shanghai
+        #            username: rt_2024
+        #            password: Yzx_19860213
+        #            initialSize: 10
+        #            maxActive: 100
+        #            minIdle: 10
+        #            maxWait: 6000
+        mysql:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://120.46.174.121:2345/fs_knt_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Ylrztek250218!3@.
+                # 从库数据源
+                slave:
+                    # 从数据源开关/默认关闭
+                    enabled: false
+                    url:
+                    username:
+                    password:
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+        sop:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://120.46.174.121:2345/knt_sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Ylrztek250218!3@.
+                read:
+                    url: jdbc:mysql://120.46.174.121:2345/knt_sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Ylrztek250218!3@.
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+rocketmq:
+    name-server: 192.168.0.176:8100 # RocketMQ NameServer 地址
+    producer:
+        group: my-producer-group
+        access-key: jnmyunl # 替换为实际的 accessKey
+        secret-key: 73a!ul~xQl@-6u1 # 替换为实际的 secretKey
+        tls-enable: false
+    consumer:
+        topic: course-finish-notes
+        group: course-finish-group
+        access-key: jnmyunl # 替换为实际的 accessKey
+        secret-key: 73a!ul~xQl@-6u1 # 替换为实际的 secretKey
+        tls-enable: false
+openIM:
+    secret: openIM123
+    userID: imAdmin
+#是否为新商户,新商户不走mpOpenId
+isNewWxMerchant: true

+ 1 - 1
fs-service/src/main/resources/application-druid-kyt.yml

@@ -150,6 +150,6 @@ openIM:
 im:
   type: NONE
 #是否为新商户,新商户不走mpOpenId
-isNewWxMerchant: true
+isNewWxMerchant: false
 
 enableRedPackAccount: 1

+ 155 - 0
fs-service/src/main/resources/application-druid-nmgyt-test.yml

@@ -0,0 +1,155 @@
+# 数据源配置
+spring:
+    profiles:
+        include: config-druid-nmgyt,common
+    # redis 配置
+    redis:
+        # 地址
+        host: 127.0.0.1
+        # 端口,默认为6379
+        port: 6379
+        # 数据库索引
+        database: 0
+        # 密码
+        password:
+        # 连接超时时间
+        timeout: 20s
+        lettuce:
+            pool:
+                # 连接池中的最小空闲连接
+                min-idle: 0
+                # 连接池中的最大空闲连接
+                max-idle: 8
+                # 连接池的最大数据库连接数
+                max-active: 8
+                # #连接池最大阻塞等待时间(使用负值表示没有限制)
+                max-wait: -1ms
+    datasource:
+        #        clickhouse:
+        #            type: com.alibaba.druid.pool.DruidDataSource
+        #            driverClassName: com.clickhouse.jdbc.ClickHouseDriver
+        #            url: jdbc:clickhouse://cc-2vc8zzo26w0l7m2l6.public.clickhouse.ads.aliyuncs.com/sop?compress=0&use_server_time_zone=true&use_client_time_zone=false&timezone=Asia/Shanghai
+        #            username: rt_2024
+        #            password: Yzx_19860213
+        #            initialSize: 10
+        #            maxActive: 100
+        #            minIdle: 10
+        #            maxWait: 6000
+        mysql:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://bj-cdb-b5ouwsa2.sql.tencentcdb.com:23018/fs_his?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Ylrz_c123232014^$
+                # 从库数据源
+                slave:
+                    # 从数据源开关/默认关闭
+                    enabled: false
+                    url:
+                    username:
+                    password:
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+        sop:
+            type: com.alibaba.druid.pool.DruidDataSource
+            driverClassName: com.mysql.cj.jdbc.Driver
+            druid:
+                # 主库数据源
+                master:
+                    url: jdbc:mysql://bj-cdb-b5ouwsa2.sql.tencentcdb.com:23018/sop?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+                    username: root
+                    password: Ylrz_c123232014^$
+                # 初始连接数
+                initialSize: 5
+                # 最小连接池数量
+                minIdle: 10
+                # 最大连接池数量
+                maxActive: 20
+                # 配置获取连接等待超时的时间
+                maxWait: 60000
+                # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+                timeBetweenEvictionRunsMillis: 60000
+                # 配置一个连接在池中最小生存的时间,单位是毫秒
+                minEvictableIdleTimeMillis: 300000
+                # 配置一个连接在池中最大生存的时间,单位是毫秒
+                maxEvictableIdleTimeMillis: 900000
+                # 配置检测连接是否有效
+                validationQuery: SELECT 1 FROM DUAL
+                testWhileIdle: true
+                testOnBorrow: false
+                testOnReturn: false
+                webStatFilter:
+                    enabled: true
+                statViewServlet:
+                    enabled: true
+                    # 设置白名单,不填则允许所有访问
+                    allow:
+                    url-pattern: /druid/*
+                    # 控制台管理用户名和密码
+                    login-username: fs
+                    login-password: 123456
+                filter:
+                    stat:
+                        enabled: true
+                        # 慢SQL记录
+                        log-slow-sql: true
+                        slow-sql-millis: 1000
+                        merge-sql: true
+                    wall:
+                        config:
+                            multi-statement-allow: true
+rocketmq:
+    name-server: rmq-1243b25nj.rocketmq.gz.public.tencenttdmq.com:8080 # RocketMQ NameServer 地址
+    producer:
+        group: my-producer-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+    consumer:
+        group: test-group
+        access-key: ak1243b25nj17d4b2dc1a03 # 替换为实际的 accessKey
+        secret-key: sk08a7ea1f9f4b0237 # 替换为实际的 secretKey
+openIM:
+    secret: openIM123
+    userID: imAdmin
+#是否为新商户,新商户不走mpOpenId
+isNewWxMerchant: true

+ 2 - 0
fs-service/src/main/resources/application-druid-qdtst.yml

@@ -172,3 +172,5 @@ im:
     type: NONE
 #是否为新商户,新商户不走mpOpenId
 isNewWxMerchant: false
+
+enableRedPackAccount: 1

+ 1 - 1
fs-service/src/main/resources/mapper/company/CompanyMapper.xml

@@ -232,7 +232,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <select id="selectCompanyByIds2" parameterType="Long" resultType="Company">
         <include refid="selectCompanyVo"/>
-        where company_id in
+        where is_del = 0 and company_id in
         <foreach item="companyId" collection="companyIds" open="(" separator="," close=")">
             #{companyId}
         </foreach>

+ 85 - 6
fs-service/src/main/resources/mapper/company/CompanyUserMapper.xml

@@ -47,13 +47,34 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <collection  property="roles"   javaType="java.util.List"        resultMap="RoleResult" />
     </resultMap>
 
+    <resultMap id="CompanyUserQwListVOResult" type="com.fs.company.vo.CompanyUserQwListVO">
+        <id property="userId" column="user_id"/>
+        <result property="userName" column="user_name"/>
+        <result property="nickName" column="nick_name"/>
+        <result property="companyId" column="company_id"/>
+        <result property="status" column="status"/>
+        <result property="qwStatus" column="qw_status"/>
+        <result property="phonenumber" column="phonenumber"/>
+        <result property="createTime" column="create_time"/>
+        <result property="deptId" column="dept_id"/>
+        <result property="deptName" column="dept_name"/>
+        <result property="qrCodeWeixin" column="qr_code_weixin"/>
+        <result property="postName" column="post_name"/>
+        <result property="qrCodeWecom" column="qr_code_wecom"/>
+        <result property="jpushId" column="jpush_id"/>
+        <result property="callerNo" column="caller_no"/>
+        <collection property="roleNames" ofType="java.lang.String" javaType="java.util.ArrayList">
+            <result column="role_name"/>
+        </collection>
+    </resultMap>
+
     <resultMap id="deptResult" type="CompanyDept">
-        <id     property="deptId"   column="dept_id"     />
-        <result property="parentId" column="parent_id"   />
-        <result property="deptName" column="dept_name"   />
-        <result property="orderNum" column="order_num"   />
-        <result property="leader"   column="leader"      />
-        <result property="status"   column="dept_status" />
+        <id property="deptId" column="dept_id"/>
+        <result property="parentId" column="parent_id"/>
+        <result property="deptName" column="dept_name"/>
+        <result property="orderNum" column="order_num"/>
+        <result property="leader" column="leader"/>
+        <result property="status" column="dept_status"/>
     </resultMap>
 
     <resultMap id="RoleResult" type="CompanyRole">
@@ -64,7 +85,65 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="dataScope"     column="data_scope"    />
         <result property="status"       column="role_status"    />
     </resultMap>
+    <select id="selectCompanyUserQwListVO" resultMap="CompanyUserQwListVOResult">
+        select
+        u.user_id, u.user_name, u.nick_name, u.company_id, u.status,
+        u.qw_status, u.phonenumber, u.create_time, u.dept_id,
+        u.qr_code_weixin, u.user_type, u.qr_code_wecom, u.jpush_id,
+        u.avatar,
+        d.dept_name,
+        d.leader,
+        cr.role_name as role_name
+        from
+        company_user u
+        left join
+        company_dept d on u.dept_id = d.dept_id
+        left join
+        company_user_role cur on u.user_id = cur.user_id
+        left join
+        company_role cr on cr.role_id = cur.role_id
+        where
+        u.del_flag = '0'
+
+        <if test="userName != null and userName != ''">
+            AND u.user_name like concat('%', #{userName}, '%')
+        </if>
+
+        <if test="nickName != null and nickName != ''">
+            AND u.nick_name like concat( #{nickName}, '%')
+        </if>
+
+        <if test="companyId != null and companyId != ''">
+            AND u.company_id = #{companyId}
+        </if>
+
+        <if test="status != null and status != ''">
+            AND u.status = #{status}
+        </if>
 
+        <if test="qwStatus != null">
+            AND u.qw_status = #{qwStatus}
+        </if>
+
+        <if test="phonenumber != null and phonenumber != ''">
+            AND u.phonenumber like concat('%', #{phonenumber}, '%')
+        </if>
+
+        <if test="beginTime != null and beginTime != ''">
+            AND date_format(u.create_time,'%y%m%d') &gt;= date_format(#{beginTime},'%y%m%d')
+        </if>
+
+        <if test="endTime != null and endTime != ''">
+            AND date_format(u.create_time,'%y%m%d') &lt;= date_format(#{endTime},'%y%m%d')
+        </if>
+
+        <if test="deptId != null and deptId != 0">
+            AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM company_dept t WHERE find_in_set(#{deptId}, ancestors) ))
+        </if>
+
+        <!-- 数据范围过滤 -->
+        ${params.dataScope}
+    </select>
 
 
     <select id="selectCompanyUserList" parameterType="CompanyUser" resultMap="CompanyUserResult">

Some files were not shown because too many files changed in this diff