Sfoglia il codice sorgente

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

caoliqin 6 giorni fa
parent
commit
605829ab05
31 ha cambiato i file con 1300 aggiunte e 137 eliminazioni
  1. 24 7
      fs-admin/src/main/java/com/fs/his/controller/FsIntegralOrderController.java
  2. 109 0
      fs-admin/src/main/java/com/fs/his/controller/FsIntegralOrderLogsController.java
  3. 9 0
      fs-admin/src/main/java/com/fs/his/controller/FsStoreOrderController.java
  4. 10 0
      fs-admin/src/main/java/com/fs/live/controller/LiveAfterSalesController.java
  5. 18 6
      fs-admin/src/main/java/com/fs/qw/qwTask/qwTask.java
  6. 6 0
      fs-company/src/main/java/com/fs/company/controller/live/LiveAfterSalesController.java
  7. 18 2
      fs-qw-task/src/main/java/com/fs/app/controller/CommonController.java
  8. 1 1
      fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java
  9. 34 24
      fs-service/src/main/java/com/fs/erp/service/impl/DfOrderServiceImpl.java
  10. 47 0
      fs-service/src/main/java/com/fs/his/domain/FsIntegralOrderLogs.java
  11. 62 0
      fs-service/src/main/java/com/fs/his/mapper/FsIntegralOrderLogsMapper.java
  12. 1 0
      fs-service/src/main/java/com/fs/his/mapper/FsUserInformationCollectionMapper.java
  13. 62 0
      fs-service/src/main/java/com/fs/his/service/IFsIntegralOrderLogsService.java
  14. 92 0
      fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderLogsServiceImpl.java
  15. 3 0
      fs-service/src/main/java/com/fs/live/mapper/LiveAfterSalesMapper.java
  16. 2 0
      fs-service/src/main/java/com/fs/live/service/ILiveAfterSalesService.java
  17. 220 4
      fs-service/src/main/java/com/fs/live/service/impl/LiveAfterSalesServiceImpl.java
  18. 111 85
      fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java
  19. 16 5
      fs-service/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java
  20. 46 0
      fs-service/src/main/java/com/fs/qw/domain/QwApiSopLogToken.java
  21. 61 0
      fs-service/src/main/java/com/fs/qw/mapper/QwApiSopLogTokenMapper.java
  22. 61 0
      fs-service/src/main/java/com/fs/qw/service/IQwApiSopLogTokenService.java
  23. 91 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwApiSopLogTokenServiceImpl.java
  24. 22 0
      fs-service/src/main/java/com/fs/sop/mapper/QwSopLogsMapper.java
  25. 2 0
      fs-service/src/main/java/com/fs/sop/service/IQwSopLogsService.java
  26. 11 1
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopLogsServiceImpl.java
  27. 1 1
      fs-service/src/main/resources/application-config-druid-hzyy.yml
  28. 1 1
      fs-service/src/main/resources/application-config-druid-sxjz.yml
  29. 76 0
      fs-service/src/main/resources/mapper/his/FsIntegralOrderLogsMapper.xml
  30. 5 0
      fs-service/src/main/resources/mapper/his/FsUserInformationCollectionMapper.xml
  31. 78 0
      fs-service/src/main/resources/mapper/qw/QwApiSopLogTokenMapper.xml

+ 24 - 7
fs-admin/src/main/java/com/fs/his/controller/FsIntegralOrderController.java

@@ -12,10 +12,8 @@ import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.CloudHostUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.his.domain.FsDfAccount;
-import com.fs.his.domain.FsIntegralOrder;
-import com.fs.his.domain.FsIntegralOrderDf;
-import com.fs.his.domain.FsStoreOrder;
+import com.fs.common.utils.uuid.IdUtils;
+import com.fs.his.domain.*;
 import com.fs.his.dto.ExpressInfoDTO;
 import com.fs.his.enums.ShipperCodeEnum;
 import com.fs.his.mapper.FsIntegralOrderMapper;
@@ -59,6 +57,8 @@ public class FsIntegralOrderController extends BaseController
     @Autowired
     private IFsStoreOrderService fsStoreOrderService;
 
+    @Autowired
+    private IFsIntegralOrderLogsService integralOrderLogsService;
 
     @Autowired
     private IFsIntegralOrderDfService integralOrderDfService;
@@ -314,12 +314,20 @@ public class FsIntegralOrderController extends BaseController
             } else {
                 integralOrderDfService.insertFsIntegralOrderDf(df);
             }
-            //积分订单操作日志暂定
+            // 添加积分订单操作记录
+            FsIntegralOrderLogs logs = new FsIntegralOrderLogs();
+            logs.setLogsId(IdUtils.fastUUID());
+            logs.setOrderId(item.getOrderId());
+            logs.setChangeType("set_erp_account");
+            logs.setChangeMessage(nickName+"设置ERP账户为:" + loginAccount);
+            logs.setChangeTime(LocalDateTime.now());
+            logs.setOperator(nickName);
+            integralOrderLogsService.insertFsIntegralOrderLogs(logs);
         });
         return R.ok();
     }
 
-//    @Log(title = "手动推管易", businessType = BusinessType.INSERT)
+    //    @Log(title = "手动推管易", businessType = BusinessType.INSERT)
     @ApiOperation("批量创建ERP订单")
 //    @PreAuthorize("@ss.hasPermi('his:storeOrder:createErpOrder')")
     @Log(title = "积分商品订单", businessType = BusinessType.UPDATE)
@@ -354,9 +362,18 @@ public class FsIntegralOrderController extends BaseController
                     integralOrderDfService.getBaseMapper().insert(df);
                     order.setLoginAccount(df.getLoginAccount());
                     integralOrderMapper.updateById(order);
-                    //日志表,待定
                 }
                 fsIntegralOrderService.createErpOrder(order.getOrderId());
+
+                // 添加积分订单操作记录
+                FsIntegralOrderLogs logs = new FsIntegralOrderLogs();
+                logs.setLogsId(IdUtils.fastUUID());
+                logs.setOrderId(order.getOrderId());
+                logs.setChangeType("create_erp_order");
+                logs.setChangeMessage(getLoginUser().getUser().getNickName()+"创建ERP订单,账户:" + loginAccount);
+                logs.setChangeTime(LocalDateTime.now());
+                logs.setOperator(getLoginUser().getUser().getNickName());
+                integralOrderLogsService.insertFsIntegralOrderLogs(logs);
             }
         }
         return R.ok("推送成功");

+ 109 - 0
fs-admin/src/main/java/com/fs/his/controller/FsIntegralOrderLogsController.java

@@ -0,0 +1,109 @@
+package com.fs.his.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.FsIntegralOrderLogs;
+import com.fs.his.service.IFsIntegralOrderLogsService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 订单操作记录Controller
+ *
+ * @author fs
+ * @date 2025-11-25
+ */
+@RestController
+@RequestMapping("/his/logs")
+public class FsIntegralOrderLogsController extends BaseController
+{
+    @Autowired
+    private IFsIntegralOrderLogsService fsIntegralOrderLogsService;
+
+    /**
+     * 查询订单操作记录列表
+     */
+//    @PreAuthorize("@ss.hasPermi('his:logs:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        startPage();
+        List<FsIntegralOrderLogs> list = fsIntegralOrderLogsService.selectFsIntegralOrderLogsList(fsIntegralOrderLogs);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出订单操作记录列表
+     */
+//    @PreAuthorize("@ss.hasPermi('his:logs:export')")
+    @Log(title = "订单操作记录", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        List<FsIntegralOrderLogs> list = fsIntegralOrderLogsService.selectFsIntegralOrderLogsList(fsIntegralOrderLogs);
+        ExcelUtil<FsIntegralOrderLogs> util = new ExcelUtil<FsIntegralOrderLogs>(FsIntegralOrderLogs.class);
+        return util.exportExcel(list, "订单操作记录数据");
+    }
+
+    /**
+     * 获取订单操作记录详细信息
+     */
+//    @PreAuthorize("@ss.hasPermi('his:logs:query')")
+    @GetMapping(value = "/{logsId}")
+    public AjaxResult getInfo(@PathVariable("logsId") String logsId)
+    {
+        return AjaxResult.success(fsIntegralOrderLogsService.selectFsIntegralOrderLogsByLogsId(logsId));
+    }
+
+    /**
+     * 新增订单操作记录
+     */
+//    @PreAuthorize("@ss.hasPermi('his:logs:add')")
+    @Log(title = "订单操作记录", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        return toAjax(fsIntegralOrderLogsService.insertFsIntegralOrderLogs(fsIntegralOrderLogs));
+    }
+
+    /**
+     * 修改订单操作记录
+     */
+//    @PreAuthorize("@ss.hasPermi('his:logs:edit')")
+    @Log(title = "订单操作记录", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        return toAjax(fsIntegralOrderLogsService.updateFsIntegralOrderLogs(fsIntegralOrderLogs));
+    }
+
+    /**
+     * 根据订单ID查询操作记录
+     */
+//    @PreAuthorize("@ss.hasPermi('his:logs:query')")
+    @GetMapping("/order/{orderId}")
+    public AjaxResult getLogsByOrderId(@PathVariable("orderId") Long orderId)
+    {
+        FsIntegralOrderLogs queryParam = new FsIntegralOrderLogs();
+        queryParam.setOrderId(orderId);
+        List<FsIntegralOrderLogs> list = fsIntegralOrderLogsService.selectFsIntegralOrderLogsList(queryParam);
+        return AjaxResult.success(list);
+    }
+
+    /**
+     * 删除订单操作记录
+     */
+//    @PreAuthorize("@ss.hasPermi('his:logs:remove')")
+    @Log(title = "订单操作记录", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{logsIds}")
+    public AjaxResult remove(@PathVariable String[] logsIds)
+    {
+        return toAjax(fsIntegralOrderLogsService.deleteFsIntegralOrderLogsByLogsIds(logsIds));
+    }
+}

+ 9 - 0
fs-admin/src/main/java/com/fs/his/controller/FsStoreOrderController.java

@@ -34,6 +34,7 @@ import com.fs.his.dto.TracesDTO;
 import com.fs.his.enums.FsStoreOrderLogEnum;
 import com.fs.his.enums.FsStoreOrderStatusEnum;
 import com.fs.his.enums.ShipperCodeEnum;
+import com.fs.his.mapper.FsUserInformationCollectionMapper;
 import com.fs.his.param.FsFollowMsgParam;
 import com.fs.his.param.FsStoreOrderParam;
 import com.fs.his.param.FsStoreOrderSalesParam;
@@ -125,6 +126,8 @@ public class FsStoreOrderController extends BaseController
 
     @Autowired
     private IFsDfAccountService fsDfAccountService;
+    @Autowired
+    private FsUserInformationCollectionMapper userInformationCollectionMapper;
     /**
      * 查询订单列表
      */
@@ -648,6 +651,12 @@ public class FsStoreOrderController extends BaseController
     public AjaxResult sendGoods(@RequestBody FsStoreOrder fsStoreOrder)
     {
         String nickName = getLoginUser().getUser().getNickName();
+        if(CloudHostUtils.hasCloudHostName("金牛明医")){
+            FsUserInformationCollection fsUserInformationCollection = userInformationCollectionMapper.selectFsUserInformationCollectionByOrderCode(fsStoreOrder.getOrderCode());
+            if (fsUserInformationCollection != null&&fsUserInformationCollection.getDoctorType2Confirm()!=1) {
+                return AjaxResult.error("药师未确认");
+            }
+        }
         return toAjax(fsStoreOrderService.sendGoods(fsStoreOrder,nickName));
     }
     /**

+ 10 - 0
fs-admin/src/main/java/com/fs/live/controller/LiveAfterSalesController.java

@@ -180,4 +180,14 @@ public class LiveAfterSalesController extends BaseController
         param.setOperator(loginUser.getUser().getNickName());
         return liveAfterSalesService.cancel(param);
     }
+
+    @PreAuthorize("@ss.hasPermi('store:storeAfterSales:refund')")
+    @PostMapping("/handleImmediatelyRefund")
+    public R handleImmediatelyRefund(@RequestBody LiveAfterSalesRefundParam param)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        param.setOperator(loginUser.getUser().getNickName());
+        return liveAfterSalesService.handleImmediatelyRefund(param.getOrderId());
+    }
+
 }

+ 18 - 6
fs-admin/src/main/java/com/fs/qw/qwTask/qwTask.java

@@ -1,21 +1,17 @@
 package com.fs.qw.qwTask;
 
 import com.fs.course.service.IFsUserCourseService;
-import com.fs.qw.service.IQwExternalContactService;
-import com.fs.qw.service.IQwGroupMsgService;
-import com.fs.qw.service.IQwMaterialService;
-import com.fs.qw.service.IQwUserService;
+import com.fs.qw.service.*;
 import com.fs.sop.service.impl.QwSopLogsServiceImpl;
 import com.fs.sop.service.impl.QwSopServiceImpl;
 import com.fs.sop.service.ISopUserLogsService;
 import com.fs.statis.IFsStatisQwWatchService;
 import com.fs.statis.service.FsStatisSalerWatchService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
 
 @Component("qwTask")
 public class qwTask {
@@ -51,6 +47,8 @@ public class qwTask {
     private IQwMaterialService iQwMaterialService;
 
 
+
+
     //正在使用
     public void qwExternalContact()
     {
@@ -199,4 +197,18 @@ public class qwTask {
     public void updateMaterialByTwoDays(){
         iQwMaterialService.updateQwMaterialByQw();
     }
+
+    /**
+     * 统计 每天的官方群发统计
+     */
+    public void countQwApiAopLogToken(){
+        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        // 获取当前日期(只包含年月日)
+        LocalDate currentDate = LocalDate.now();
+
+        String todayStr = currentDate.format(dateFormatter);
+         qwSopLogsService.countQwApiAopLogToken(todayStr);
+
+
+    }
 }

+ 6 - 0
fs-company/src/main/java/com/fs/company/controller/live/LiveAfterSalesController.java

@@ -8,6 +8,8 @@ import com.fs.common.core.page.TableDataInfo;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.company.domain.CompanyUser;
+import com.fs.framework.security.SecurityUtils;
 import com.fs.his.domain.FsUser;
 import com.fs.his.service.IFsUserService;
 import com.fs.live.domain.LiveAfterSales;
@@ -55,6 +57,8 @@ public class LiveAfterSalesController extends BaseController
     public TableDataInfo list(LiveAfterSalesVo liveAfterSales)
     {
         startPage();
+        CompanyUser user = SecurityUtils.getLoginUser().getUser();
+        liveAfterSales.setCompanyId(user.getCompanyId());
         List<LiveAfterSalesVo> list = liveAfterSalesService.selectLiveAfterSalesVoList(liveAfterSales);
         for (LiveAfterSalesVo liveAfterSalesVo : list) {
             liveAfterSalesVo.setUserPhone(ParseUtils.parsePhone(liveAfterSalesVo.getUserPhone()));
@@ -71,6 +75,8 @@ public class LiveAfterSalesController extends BaseController
     public AjaxResult export(LiveAfterSalesVo liveAfterSales)
     {
         PageHelper.startPage(1, 10000, "");
+        CompanyUser user = SecurityUtils.getLoginUser().getUser();
+        liveAfterSales.setCompanyId(user.getCompanyId());
         List<LiveAfterSalesVo> list = liveAfterSalesService.selectLiveAfterSalesVoList(liveAfterSales);
         for (LiveAfterSalesVo liveAfterSalesVo : list) {
             liveAfterSalesVo.setUserPhone(liveAfterSalesVo.getUserPhone() == null ? "" : liveAfterSalesVo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));

+ 18 - 2
fs-qw-task/src/main/java/com/fs/app/controller/CommonController.java

@@ -134,11 +134,27 @@ public class CommonController {
     @Autowired
     public RedisCache redisCache;
 
+
+
     /**
-     * 获取跳转微信小程序的链接地址
+     *
+     */
+    @GetMapping("/countQwApiAopLogToken")
+    public void countQwApiAopLogToken() {
+
+        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        // 获取当前日期(只包含年月日)
+        LocalDate currentDate = LocalDate.now();
+
+        String todayStr = currentDate.format(dateFormatter);
+        qwSopLogsService.countQwApiAopLogToken(todayStr);
+
+    }
+
+    /**
+     * 查询视频时长
      */
     @GetMapping("/getVideoDuration")
-    @ApiOperation("获取跳转微信小程序的链接地址")
     public Long getVideoDuration(Long videoId) {
 
             String redisKey = "h5user:video:duration:" + videoId;

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

@@ -2302,7 +2302,7 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
                 companyUserEndDateTime : periodDays.getEndDateTime();
         // 检查时间范围和状态
         log.error("传入参数:开始时间:{},结束时间:{},periodDays={}",effectiveStartTime,effectiveEndTime,periodDays);
-        if (ObjectUtils.isNotEmpty(effectiveStartTime)||ObjectUtils.isNotEmpty(effectiveEndTime)){
+        if (ObjectUtils.isEmpty(effectiveStartTime)||ObjectUtils.isEmpty(effectiveEndTime)){
             log.error("请检查营期时间!");
             return false;
         }

+ 34 - 24
fs-service/src/main/java/com/fs/erp/service/impl/DfOrderServiceImpl.java

@@ -162,6 +162,8 @@ public class DfOrderServiceImpl implements IErpOrderService {
     @Autowired
     private LiveOrderMapper liveOrderMapper;
 
+    @Autowired
+    private FsIntegralOrderLogsMapper fsIntegralOrderLogsMapper;
     @Autowired
     private LiveOrderItemMapper liveOrderItemMapper;
 
@@ -760,39 +762,43 @@ public class DfOrderServiceImpl implements IErpOrderService {
                                         case 1:
                                             break;
                                         case 2:
-                                            sBuilder.append("您好,您有一个包裹正在准备发货,请耐心等待;\n");
-                                            if (order.getDeliverySn() != null && !order.getDeliverySn().isEmpty()) {
-                                                sBuilder.append(" 物流单号为:").append(order.getDeliverySn()).append("\n");
-                                            }
-                                            sBuilder.append("\uD83C\uDF39\uD83C\uDF39\uD83C\uDF39");
                                             break;
                                         case 3:
-                                            if ("202".equals(stateEx) || "301".equals(stateEx)) {
-                                                //211
-                                                //你好,这边查询到您购买的XXX(购买套餐)在XXX(时间)已经送到了,送货员电话为XXX(送货员信息)
-                                                ErpDeliverysRequest erpDeliverysRequest = new ErpDeliverysRequest();
-                                                erpDeliverysRequest.setCode(order.getOrderCode());
-                                                ErpDeliverysResponse express = null;
-                                                express = getDeliver(erpDeliverysRequest);
-                                                sBuilder.append("这边查询到您有一个包裹 ");
-                                                if (express != null && express.getDeliverys() != null && !express.getDeliverys().isEmpty()) {
-                                                    List<ErpDeliverys> deliverys = express.getDeliverys();
-                                                    ErpDeliverys tracesDTO = deliverys.get(deliverys.size() - 1);
-                                                    String remark = tracesDTO.getRemark();
-                                                    if (remark.contains("派送至本人") || remark.contains("签收")) {
-                                                        sBuilder.append(" 在").append(tracesDTO.getAcceptTime()).append("已经签收了\n");
-                                                        sBuilder.append(" 物流单号为:").append(order.getDeliverySn()).append("\n");
-                                                        sBuilder.append("物流信息:").append(remark).append("\n");
+                                            //你好,这边查询到您购买的XXX(购买套餐)在XXX(时间)已经送到了,送货员电话为XXX(送货员信息)
+                                            ErpDeliverysRequest erpDeliverysRequest = new ErpDeliverysRequest();
+                                            erpDeliverysRequest.setCode(order.getOrderCode());
+                                            ErpDeliverysResponse express = null;
+                                            express = getDeliver(erpDeliverysRequest);
+                                            if (express != null && express.getDeliverys() != null && !express.getDeliverys().isEmpty()) {
+                                                List<ErpDeliverys> deliverys = express.getDeliverys();
+                                                ErpDeliverys tracesDTO = deliverys.get(deliverys.size() - 1);
+                                                String remark = tracesDTO.getRemark();
+
+                                                if ("0".equals(stateEx) || "1".equals(stateEx) || "2".equals(stateEx)) {
+                                                    if (remark.contains("已收取快件")){
+                                                        sBuilder.append("您好,您有一个包裹正在准备发货,请耐心等待;\n");
+                                                        if (order.getDeliverySn() != null && !order.getDeliverySn().isEmpty()) {
+                                                            sBuilder.append(" 物流单号为:").append(order.getDeliverySn()).append("\n");
+                                                        }
+                                                        sBuilder.append("\uD83C\uDF39\uD83C\uDF39\uD83C\uDF39");
                                                     }
+                                                } else if ("202".equals(stateEx)) {
                                                     if (remark.contains("正在派送")) {
+                                                        sBuilder.append("这边查询到您有一个包裹 ");
                                                         sBuilder.append("正在派送中\n");
                                                         sBuilder.append(" 物流单号为:").append(order.getDeliverySn()).append("\n");
                                                         sBuilder.append("物流信息:").append(remark).append("\n");
+                                                        sBuilder.append("\uD83C\uDF39\uD83C\uDF39\uD83C\uDF39");
+                                                    }
+
+                                                } else if ("301".equals(stateEx)){
+                                                    if (remark.contains("派送至本人") || remark.contains("签收")) {
+                                                        sBuilder.append("这边查询到您有一个包裹 ");
+                                                        sBuilder.append(" 在").append(tracesDTO.getAcceptTime()).append("已经签收了\n");
+                                                        sBuilder.append(" 物流单号为:").append(order.getDeliverySn()).append("\n");
+                                                        sBuilder.append("物流信息:").append(remark).append("\n");
                                                     }
-                                                } else {
-                                                    sBuilder.append(" 已经送到了\n");
                                                 }
-                                                sBuilder.append("\uD83C\uDF39\uD83C\uDF39\uD83C\uDF39");
                                             }
                                             break;
                                         case 4:
@@ -1053,10 +1059,12 @@ public class DfOrderServiceImpl implements IErpOrderService {
             order.setStatus(1);//设置待发货状态
             order.setDeliverySn("");
             integralOrderMapper.updateById(order);
+            fsIntegralOrderLogsMapper.insert(FsIntegralOrderLogs.builder().orderId(order.getOrderId()).changeType(FsStoreOrderLogEnum.UPDATE_ORDER_DF.getValue()).changeMessage("运单不存在," + FsStoreOrderLogEnum.UPDATE_ORDER_DF.getDesc()).build());
         } else {
             log.info("积分订单物流被取消,退款积分订单{}",order.getOrderCode());
             //以前查询到过物流信息,现在查不到,物流被人为取消
             integralOrderService.mandatoryRefunds(order.getOrderCode());
+            fsIntegralOrderLogsMapper.insert(FsIntegralOrderLogs.builder().orderId(order.getOrderId()).changeType(FsStoreOrderLogEnum.REFUND_ORDER_DF.getValue()).changeMessage("运单不存在," + FsStoreOrderLogEnum.REFUND_ORDER_DF.getDesc()).build());
         }
         log.info("取消订单代服记录更新id{}",order.getOrderCode());
         FsIntegralOrderDf df = new FsIntegralOrderDf();
@@ -1979,6 +1987,8 @@ public class DfOrderServiceImpl implements IErpOrderService {
                                             order.setStatus(2);//修改积分订单为待收货状态
                                             order.setDeliveryTime(DateUtils.getNowDate()); //更新发货时间
                                             fsIntegralOrderMapper.updateById(order);
+                                            //订单发货日志
+                                            fsIntegralOrderLogsMapper.insert(FsIntegralOrderLogs.builder().orderId(order.getOrderId()).changeType("delivery_goods").changeMessage(FsStoreOrderLogEnum.DELIVERY_GOODS.getDesc()).build());
 //                                            fsStoreOrderLogsService.create(order.getOrderId(), FsStoreOrderLogEnum.DELIVERY_GOODS.getValue(), FsStoreOrderLogEnum.DELIVERY_GOODS.getDesc());
 //                                            redisCache.deleteObject(DELIVERY+":"+order.getOrderCode());
 //                                            if (order.getCompanyId() != null && order.getCompanyId() > 0) {

+ 47 - 0
fs-service/src/main/java/com/fs/his/domain/FsIntegralOrderLogs.java

@@ -0,0 +1,47 @@
+package com.fs.his.domain;
+
+import com.fs.common.annotation.Excel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+
+/**
+ * 订单操作记录对象 fs_integral_order_logs
+ *
+ * @author fs
+ * @date 2025-11-25
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class FsIntegralOrderLogs{
+
+    /** $column.columnComment */
+    private String logsId;
+
+    /** 订单id */
+    @Excel(name = "订单id")
+    private Long orderId;
+
+    /** 操作类型 */
+    @Excel(name = "操作类型")
+    private String changeType;
+
+    /** 操作备注 */
+    @Excel(name = "操作备注")
+    private String changeMessage;
+
+    /** 操作时间 */
+    private LocalDateTime changeTime;
+
+    /** 操作员 */
+    @Excel(name = "操作员")
+    private String operator;
+
+
+}

+ 62 - 0
fs-service/src/main/java/com/fs/his/mapper/FsIntegralOrderLogsMapper.java

@@ -0,0 +1,62 @@
+package com.fs.his.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.his.domain.FsIntegralOrderLogs;
+
+import java.util.List;
+
+/**
+ * 订单操作记录Mapper接口
+ *
+ * @author fs
+ * @date 2025-11-25
+ */
+public interface FsIntegralOrderLogsMapper extends BaseMapper<FsIntegralOrderLogs> {
+    /**
+     * 查询订单操作记录
+     *
+     * @param logsId 订单操作记录主键
+     * @return 订单操作记录
+     */
+    FsIntegralOrderLogs selectFsIntegralOrderLogsByLogsId(String logsId);
+
+    /**
+     * 查询订单操作记录列表
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 订单操作记录集合
+     */
+    List<FsIntegralOrderLogs> selectFsIntegralOrderLogsList(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 新增订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    int insertFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 修改订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    int updateFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 删除订单操作记录
+     *
+     * @param logsId 订单操作记录主键
+     * @return 结果
+     */
+    int deleteFsIntegralOrderLogsByLogsId(String logsId);
+
+    /**
+     * 批量删除订单操作记录
+     *
+     * @param logsIds 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteFsIntegralOrderLogsByLogsIds(String[] logsIds);
+}

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

@@ -99,4 +99,5 @@ public interface FsUserInformationCollectionMapper extends BaseMapper<FsUserInfo
 
     List<FsUserInformationCollection>selectFsUserInformationCollectionByDoctorType2(@Param("maps") UserInformationDoctorType2Param userInformationDoctorType2Param);
     List<FsUserInformationCollection>selectFsUserInformationCollectionByDoctorType1(@Param("maps") UserInformationDoctorType2Param userInformationDoctorType2Param);
+    FsUserInformationCollection selectFsUserInformationCollectionByOrderCode(String orderCode);
 }

+ 62 - 0
fs-service/src/main/java/com/fs/his/service/IFsIntegralOrderLogsService.java

@@ -0,0 +1,62 @@
+package com.fs.his.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.his.domain.FsIntegralOrderLogs;
+
+import java.util.List;
+
+/**
+ * 订单操作记录Service接口
+ *
+ * @author fs
+ * @date 2025-11-25
+ */
+public interface IFsIntegralOrderLogsService extends IService<FsIntegralOrderLogs> {
+    /**
+     * 查询订单操作记录
+     *
+     * @param logsId 订单操作记录主键
+     * @return 订单操作记录
+     */
+    FsIntegralOrderLogs selectFsIntegralOrderLogsByLogsId(String logsId);
+
+    /**
+     * 查询订单操作记录列表
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 订单操作记录集合
+     */
+    List<FsIntegralOrderLogs> selectFsIntegralOrderLogsList(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 新增订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    int insertFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 修改订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    int updateFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs);
+
+    /**
+     * 批量删除订单操作记录
+     *
+     * @param logsIds 需要删除的订单操作记录主键集合
+     * @return 结果
+     */
+    int deleteFsIntegralOrderLogsByLogsIds(String[] logsIds);
+
+    /**
+     * 删除订单操作记录信息
+     *
+     * @param logsId 订单操作记录主键
+     * @return 结果
+     */
+    int deleteFsIntegralOrderLogsByLogsId(String logsId);
+}

+ 92 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderLogsServiceImpl.java

@@ -0,0 +1,92 @@
+package com.fs.his.service.impl;
+
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.his.domain.FsIntegralOrderLogs;
+import com.fs.his.mapper.FsIntegralOrderLogsMapper;
+import com.fs.his.service.IFsIntegralOrderLogsService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 订单操作记录Service业务层处理
+ *
+ * @author fs
+ * @date 2025-11-25
+ */
+@Service
+public class FsIntegralOrderLogsServiceImpl extends ServiceImpl<FsIntegralOrderLogsMapper, FsIntegralOrderLogs> implements IFsIntegralOrderLogsService {
+
+    /**
+     * 查询订单操作记录
+     *
+     * @param logsId 订单操作记录主键
+     * @return 订单操作记录
+     */
+    @Override
+    public FsIntegralOrderLogs selectFsIntegralOrderLogsByLogsId(String logsId)
+    {
+        return baseMapper.selectFsIntegralOrderLogsByLogsId(logsId);
+    }
+
+    /**
+     * 查询订单操作记录列表
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 订单操作记录
+     */
+    @Override
+    public List<FsIntegralOrderLogs> selectFsIntegralOrderLogsList(FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        return baseMapper.selectFsIntegralOrderLogsList(fsIntegralOrderLogs);
+    }
+
+    /**
+     * 新增订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    @Override
+    public int insertFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        return baseMapper.insertFsIntegralOrderLogs(fsIntegralOrderLogs);
+    }
+
+    /**
+     * 修改订单操作记录
+     *
+     * @param fsIntegralOrderLogs 订单操作记录
+     * @return 结果
+     */
+    @Override
+    public int updateFsIntegralOrderLogs(FsIntegralOrderLogs fsIntegralOrderLogs)
+    {
+        return baseMapper.updateFsIntegralOrderLogs(fsIntegralOrderLogs);
+    }
+
+    /**
+     * 批量删除订单操作记录
+     *
+     * @param logsIds 需要删除的订单操作记录主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsIntegralOrderLogsByLogsIds(String[] logsIds)
+    {
+        return baseMapper.deleteFsIntegralOrderLogsByLogsIds(logsIds);
+    }
+
+    /**
+     * 删除订单操作记录信息
+     *
+     * @param logsId 订单操作记录主键
+     * @return 结果
+     */
+    @Override
+    public int deleteFsIntegralOrderLogsByLogsId(String logsId)
+    {
+        return baseMapper.deleteFsIntegralOrderLogsByLogsId(logsId);
+    }
+}

+ 3 - 0
fs-service/src/main/java/com/fs/live/mapper/LiveAfterSalesMapper.java

@@ -130,4 +130,7 @@ public interface LiveAfterSalesMapper {
             "where user_id=#{userId}  and sales_status =#{salesStatus} " +
             "</script>"})
     Integer selectLiveAfterSalesCount(@Param("userId")long userId,@Param("salesStatus") int salesStatus);
+
+    @Select(" select  * from  live_after_sales where order_id = #{orderId} and sales_status = 0 ")
+    LiveAfterSales getLiveAfterSalesByOrderId(@Param("orderId") Long orderId);
 }

+ 2 - 0
fs-service/src/main/java/com/fs/live/service/ILiveAfterSalesService.java

@@ -90,4 +90,6 @@ public interface ILiveAfterSalesService {
     List<LiveAfterSalesQueryVO> selectLiveAfterSalesListQuery(LiveAfterSalesQueryParam param);
 
     Integer selectLiveAfterSalesCount(long l, int i);
+
+    R handleImmediatelyRefund(Long orderId);
 }

+ 220 - 4
fs-service/src/main/java/com/fs/live/service/impl/LiveAfterSalesServiceImpl.java

@@ -2,6 +2,7 @@ package com.fs.live.service.impl;
 
 import java.lang.reflect.InvocationTargetException;
 import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
 import java.util.*;
 
@@ -10,6 +11,7 @@ import cn.hutool.core.date.DateTime;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
@@ -17,6 +19,9 @@ 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;
+import com.fs.company.service.ICompanyService;
+import com.fs.config.cloud.CloudHostProper;
 import com.fs.erp.constant.AfterSalesOrderStatusEnum;
 import com.fs.erp.domain.FsJstAftersalePush;
 import com.fs.erp.dto.BaseResponse;
@@ -24,25 +29,30 @@ import com.fs.erp.dto.ErpRefundUpdateRequest;
 import com.fs.erp.mapper.FsJstAftersalePushMapper;
 import com.fs.erp.service.IErpOrderService;
 import com.fs.his.config.FsSysConfig;
+import com.fs.his.domain.FsHfpayConfig;
 import com.fs.his.domain.FsUser;
+import com.fs.his.mapper.FsHfpayConfigMapper;
 import com.fs.his.service.IFsUserService;
 import com.fs.his.utils.ConfigUtil;
+import com.fs.hisStore.config.FsErpConfig;
 import com.fs.hisStore.domain.*;
 import com.fs.hisStore.dto.StoreOrderProductDTO;
-import com.fs.hisStore.enums.AfterSalesStatusEnum;
-import com.fs.hisStore.enums.AfterStatusEnum;
-import com.fs.hisStore.enums.OrderInfoEnum;
-import com.fs.hisStore.enums.SysConfigEnum;
+import com.fs.hisStore.enums.*;
 import com.fs.hisStore.param.FsStoreAfterSalesProductParam;
+import com.fs.hisStore.service.IFsStoreProductScrmService;
 import com.fs.hisStore.service.IFsUserScrmService;
 import com.fs.hisStore.vo.FsStoreAfterSalesQueryVO;
 import com.fs.hisStore.vo.FsStoreOrderItemVO;
+import com.fs.huifuPay.domain.HuiFuRefundResult;
+import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
+import com.fs.huifuPay.service.HuiFuService;
 import com.fs.live.domain.*;
 import com.fs.live.dto.LiveAfterSalesProductDTO;
 import com.fs.live.enums.LiveAfterSalesStatusEnum;
 import com.fs.live.mapper.*;
 import com.fs.live.param.*;
 import com.fs.live.service.ILiveOrderItemService;
+import com.fs.live.service.ILiveOrderLogsService;
 import com.fs.live.service.ILiveOrderService;
 import com.fs.live.vo.LiveAfterSalesListUVO;
 import com.fs.live.vo.LiveAfterSalesQueryVO;
@@ -52,9 +62,17 @@ import com.fs.store.config.StoreConfig;
 import com.fs.store.domain.*;
 import com.fs.store.service.cache.IFsUserCacheService;
 import com.fs.system.service.ISysConfigService;
+import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
+import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.WxPayService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.beanutils.BeanUtils;
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang.ObjectUtils;
 import org.apache.http.util.Asserts;
 import org.springframework.aop.framework.AopContext;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -887,4 +905,202 @@ public class LiveAfterSalesServiceImpl implements ILiveAfterSalesService {
     }
 
 
+    @Autowired
+    private LiveOrderItemMapper liveOrderItemMapper;
+    @Autowired
+    private LiveUserLotteryRecordMapper liveUserLotteryRecordMapper;
+    @Autowired
+    private IFsStoreProductScrmService fsStoreProductService;
+
+    @Autowired
+    private WxPayService wxPayService;
+
+
+    @Autowired
+    private HuiFuService huiFuService;
+
+    @Autowired
+    private ILiveOrderLogsService liveOrderLogsService;
+    @Autowired
+    private ICompanyService companyService;
+
+    @Autowired
+    private LiveAfterSalesMapper liveAfterSalesMapper;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
+    public R handleImmediatelyRefund(Long orderId) {
+        IErpOrderService erpOrderService = getErpService();
+        FsErpConfig erpConfig = configUtil.generateStructConfigByKey("his.config", FsErpConfig.class);
+        LiveOrder order = liveOrderService.selectLiveOrderByOrderId(String.valueOf(orderId));
+        if (order == null) {
+            return R.error("订单不存在");
+        }
+        if (order.getStatus() == -2) {
+            return R.error("已退款");
+        }
+        if (!Integer.valueOf(-1).equals(order.getStatus())) {
+            return R.error("非法操作");
+        }
+        if (erpConfig.getErpOpen() != null
+                && erpConfig.getErpOpen() == 1
+                && StringUtils.isEmpty(order.getExtendOrderId())
+                && !CloudHostUtils.hasCloudHostName("康年堂")) {
+            return R.error("暂未推送至erp,请稍后再试!");
+        }
+//        if (StringUtils.isNotEmpty(order.getExtendOrderId())) {
+//            ErpRefundUpdateRequest request = new ErpRefundUpdateRequest();
+//            request.setTid(order.getOrderCode());
+//            request.setOid(order.getOrderCode());
+//            request.setRefund_state(1);
+//
+//            if (ObjectUtils.equals(order.getStatus(), 2)) {
+//                LiveAfterSalesParam param = new LiveAfterSalesParam();
+//                param.setOrderCode(order.getOrderCode());
+//                param.setRefundAmount(order.getPayMoney());
+//                param.setServiceType(1);
+//                param.setReasons("后台手动退款流程");
+//                param.setExplainImg(null);
+//                List<FsStoreAfterSalesProductParam> productParams = new ArrayList<>();
+//                List <LiveOrderItem> items = liveOrderItemMapper.selectLiveOrderItemByOrderId(order.getOrderId());
+//                for (LiveOrderItem item : items){
+//                    FsStoreAfterSalesProductParam param1 = new FsStoreAfterSalesProductParam();
+//                    param1.setProductId(item.getProductId());
+//                    param1.setNum(Math.toIntExact(item.getNum()));
+//                    productParams.add(param1);
+//                }
+//                return liveAfterSalesService.applyForAfterSales(order.getUserId(), param);
+//            } else {
+//                jSTOrderService.refundUpdateLive(request);
+//            }
+//        }
+        order.setStatus(OrderInfoEnum.STATUS_NE2.getValue());
+        order.setRefundMoney(order.getPayMoney());
+        order.setRefundStatus(String.valueOf(OrderInfoEnum.REFUND_STATUS_2.getValue()));
+        liveUserLotteryRecordMapper.updateOrderStatusByOrderId(order.getOrderId(), -2);
+        liveOrderService.updateLiveOrder(order);
+
+        //退库存
+        //获取订单下的商品
+        List<LiveOrderItem> orderItemVOS = liveOrderItemMapper.selectLiveOrderItemByOrderId(order.getOrderId());
+        for (LiveOrderItem vo : orderItemVOS) {
+            if (vo.getIsAfterSales() == 1) {
+                fsStoreProductService.incProductStock(vo.getNum(), vo.getProductId(), vo.getProductAttrValueId());
+            }
+        }
+        if ("3".equals(order.getPayType())) {
+            //货到付款
+        } else {
+            //将钱退还给用户
+            List<LiveOrderPayment> payments = liveOrderPaymentMapper.selectLiveOrderPaymentByPay(5, order.getOrderId());
+            if (payments != null && !payments.isEmpty()) {
+                String json = configService.selectConfigByKey("his.pay");
+                FsPayConfigScrm fsPayConfig = JSON.parseObject(json, FsPayConfigScrm.class);
+                for (LiveOrderPayment payment : payments) {
+                    if (payment.getPayMode() == null || "wx".equals(payment.getPayMode())) {
+                        WxPayConfig payConfig = new WxPayConfig();
+                        payConfig.setAppId(fsPayConfig.getAppId());
+                        payConfig.setMchId(fsPayConfig.getWxMchId());
+                        payConfig.setMchKey(fsPayConfig.getWxMchKey());
+                        payConfig.setKeyPath(fsPayConfig.getKeyPath());
+                        payConfig.setSubAppId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                        payConfig.setSubMchId(org.apache.commons.lang3.StringUtils.trimToNull(null));
+                        wxPayService.setConfig(payConfig);
+                        WxPayRefundRequest refundRequest = new WxPayRefundRequest();
+                        refundRequest.setOutTradeNo("live-" + payment.getPayCode());
+                        refundRequest.setOutRefundNo("live-" + payment.getPayCode());
+                        refundRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(payment.getPayMoney().toString()));
+                        refundRequest.setRefundFee(WxPayUnifiedOrderRequest.yuanToFen(payment.getPayMoney().toString()));
+                        try {
+                            WxPayRefundResult refundResult = wxPayService.refund(refundRequest);
+                            WxPayRefundQueryResult refundQueryResult = wxPayService.refundQuery("", refundResult.getOutTradeNo(), refundResult.getOutRefundNo(), refundResult.getRefundId());
+                            if (refundQueryResult != null && "SUCCESS".equals(refundQueryResult.getResultCode())) {
+                                LiveOrderPayment paymentMap = new LiveOrderPayment();
+                                paymentMap.setPaymentId(payment.getPaymentId());
+                                paymentMap.setStatus(-1);
+                                paymentMap.setRefundTime(DateUtils.getNowDate());
+                                paymentMap.setRefundMoney(payment.getPayMoney());
+                                liveOrderPaymentMapper.updateLiveOrderPayment(paymentMap);
+                            } else {
+                                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                                return R.error("退款请求失败" + (refundQueryResult != null ? refundQueryResult.getErrCodeDes() : ""));
+                            }
+                        } catch (WxPayException e) {
+                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                            return R.error("退款请求失败" + e.getErrCodeDes());
+                        }
+                    } else if (payment.getPayMode() != null && "hf".equals(payment.getPayMode())) {
+                        String huifuId = "";
+                        FsHfpayConfigMapper fsHfpayConfigMapper = SpringUtils.getBean(FsHfpayConfigMapper.class);
+                        if (payment.getAppId() != null) {
+                            FsHfpayConfig fsHfpayConfig = fsHfpayConfigMapper.selectByAppId(payment.getAppId());
+                            if (fsHfpayConfig != null) {
+                                huifuId = fsHfpayConfig.getHuifuId();
+                            }
+                        } else {
+                            CloudHostProper cloudHostProper = SpringUtils.getBean(CloudHostProper.class);
+                            if ("益善缘".equals(cloudHostProper.getCompanyName())) {
+                                FsHfpayConfig fsPayConfig2 = fsHfpayConfigMapper.selectByAppId("wx0d1a3dd485268521");
+                                if (fsPayConfig2 != null) {
+                                    huifuId = fsPayConfig2.getHuifuId();
+                                }
+                            } else {
+                                huifuId = fsPayConfig.getHuifuId();
+                            }
+                        }
+
+                        V2TradePaymentScanpayRefundRequest request = new V2TradePaymentScanpayRefundRequest();
+                        request.setOrgHfSeqId(payment.getTradeNo());
+                        request.setHuifuId(huifuId);
+                        request.setOrdAmt(payment.getPayMoney().toString());
+                        request.setOrgReqDate(new SimpleDateFormat("yyyyMMdd").format(payment.getCreateTime()));
+                        request.setReqSeqId("refund-" + payment.getPayCode());
+                        Map<String, Object> extendInfoMap = new HashMap<>();
+                        extendInfoMap.put("org_party_order_id", payment.getBankSerialNo());
+                        request.setExtendInfo(extendInfoMap);
+                        HuiFuRefundResult refund = huiFuService.refund(request);
+                        log.info("退款:" + refund);
+                        if (refund != null && ("00000000".equals(refund.getResp_code()) || "00000100".equals(refund.getResp_code()))
+                                && ("S".equals(refund.getTrans_stat()) || "P".equals(refund.getTrans_stat()))) {
+                            payment.setRefundMoney(payment.getPayMoney());
+                            payment.setStatus(-1);
+                            payment.setRefundTime(new Date());
+                            liveOrderPaymentMapper.updateLiveOrderPayment(payment);
+                        } else {
+                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                            return R.error(refund != null ? refund.getResp_desc() : "退款失败");
+                        }
+                    } else {
+                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+                        return R.error("支付类型异常");
+                    }
+                }
+            }
+        }
+        liveOrderLogsService.create(order.getOrderId(), OrderLogEnum.REFUND_ORDER_SUCCESS.getValue(),
+                OrderLogEnum.REFUND_ORDER_SUCCESS.getDesc());
+        //减去公司收入
+        if (order.getCompanyId() != null && order.getCompanyId() > 0 && order.getTuiMoneyStatus() != null && order.getTuiMoneyStatus() == 1) {
+            companyService.subLiveCompanyMoney(order);
+        }
+        // 减去用户佣金
+        if (order.getTuiUserId() != null && order.getTuiUserId() > 0) {
+            IFsUserScrmService userService = SpringUtils.getBean(IFsUserScrmService.class);
+            if (userService != null) {
+                // 需要将LiveOrder转换为FsStoreOrderScrm用于subTuiMoney方法
+                FsStoreOrderScrm storeOrder = new FsStoreOrderScrm();
+                storeOrder.setId(order.getOrderId());
+                storeOrder.setTuiUserId(order.getTuiUserId());
+                userService.subTuiMoney(storeOrder);
+            }
+        }
+        LiveAfterSales liveAfterSales = liveAfterSalesMapper.getLiveAfterSalesByOrderId(orderId);
+        LiveAfterSales liveMp = new LiveAfterSales();
+        liveMp.setId(liveAfterSales.getId());
+        liveMp.setStatus(LiveAfterSalesStatusEnum.STATUS_4.getValue());
+        liveMp.setSalesStatus(3);
+        liveAfterSalesMapper.updateLiveAfterSales(liveMp);
+
+        return R.ok();
+    }
 }

+ 111 - 85
fs-service/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java

@@ -29,6 +29,8 @@ import com.alibaba.fastjson.JSON;
 
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.TypeReference;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.config.FSSysConfig;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
@@ -63,6 +65,7 @@ import com.fs.his.enums.FsStoreOrderLogEnum;
 import com.fs.his.mapper.FsHfpayConfigMapper;
 import com.fs.his.mapper.FsStoreProductAttrValueMapper;
 import com.fs.his.mapper.FsUserMapper;
+import com.fs.his.mapper.FsUserWxMapper;
 import com.fs.his.service.IFsExpressService;
 import com.fs.his.service.IFsStoreProductService;
 import com.fs.his.service.IFsUserService;
@@ -136,6 +139,8 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
     private final RedisCache redisCache;
     @Autowired
     private LiveOrderMapper baseMapper;
+    @Autowired
+    private FsUserWxMapper fsUserWxMapper;
 
 
 
@@ -2364,82 +2369,86 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
 
     private BigDecimal handleDeliveryMoney(Long cityId, FsStoreProductScrm fsStoreProduct, String totalNumSize) {
         BigDecimal storePostage = BigDecimal.ZERO;
-//        List<Long> citys = new ArrayList<>();
-//        citys.add(cityId);
-//        citys.add(0l);
-//        String ids = String.valueOf(fsStoreProduct.getTempId());
-//        List<FsShippingTemplates> shippingTemplatesList = shippingTemplatesService.selectFsShippingTemplatesByIds(ids);
-//        String cityIds = String.join(",", citys.stream()
-//                .map(String::valueOf).collect(Collectors.toList()));
-//        List<FsShippingTemplatesRegion> shippingTemplatesRegionList = shippingTemplatesRegionService.selectFsShippingTemplatesRegionListByTempIdsAndCityIds(ids,cityIds);
-//        Map<Long, Integer> shippingTemplatesMap = shippingTemplatesList
-//                .stream()
-//                .collect(Collectors.toMap(FsShippingTemplates::getId,
-//                        FsShippingTemplates::getType));
-//        //提取运费模板有相同值覆盖
-//        Map<Long, FsShippingTemplatesRegion> shippingTemplatesRegionMap =
-//                shippingTemplatesRegionList.stream()
-//                        .collect(Collectors.toMap(FsShippingTemplatesRegion::getTempId,
-//                                YxShippingTemplatesRegion -> YxShippingTemplatesRegion,
-//                                (key1, key2) -> key2));
-//        Long tempId = Long.valueOf(fsStoreProduct.getTempId());
-//        double num = 0d;
-//        Integer templateType = shippingTemplatesMap.get(tempId);
-//        List<FsStoreProductAttrValue> productAttrValues = fsStoreProductAttrValueMapper.selectFsStoreProductAttrValueByProductId(fsStoreProduct.getProductId());
-//        if(productAttrValues == null || productAttrValues.isEmpty()) {
-//            return storePostage;
-//        }
-//        FsStoreProductAttrValue productAttrValue = productAttrValues.get(0);
-//        Integer totalNum = Integer.valueOf(totalNumSize);
-//        // TYPE_1: 按件数计算
-//        if (ShippingTempEnum.TYPE_1.getValue().equals(templateType)) {
-//            num = totalNum.doubleValue();
-//        }
-//        // TYPE_2: 按重量计算(数量 × 重量)
-//        else if (ShippingTempEnum.TYPE_2.getValue().equals(templateType)) {
-//            num = NumberUtil.mul(totalNum, productAttrValue.getWeight()).doubleValue();
-//        }
-//        // TYPE_3: 按体积计算(数量 × 体积)
-//        else if (ShippingTempEnum.TYPE_3.getValue().equals(templateType)) {
-//            num = NumberUtil.mul(totalNum, productAttrValue.getVolume()).doubleValue();
-//        }
-//        FsShippingTemplatesRegion shippingTemplatesRegion = shippingTemplatesRegionMap.get(tempId);
-//        if (shippingTemplatesRegion == null) {
-//            log.error("没有找到运费模板");
-//            return storePostage;
-//        }
-//        BigDecimal price = NumberUtil.round(NumberUtil.mul(totalNum, fsStoreProduct.getPrice()), 2);
-//
-//        TemplateDTO templateDTO = TemplateDTO.builder()
-//                .number(num)  // 累计数量(件数/重量/体积)
-//                .price(price)  // 累计金额
-//                .first(shippingTemplatesRegion.getFirst().doubleValue())  // 首件数量
-//                .firstPrice(shippingTemplatesRegion.getFirstPrice())  // 首件运费
-//                .continues(shippingTemplatesRegion.getContinues().doubleValue())  // 续件数量
-//                .continuePrice(shippingTemplatesRegion.getContinuePrice())  // 续件运费
-//                .tempId(tempId)  // 模板ID
-//                .cityId(cityId)  // 城市ID
-//                .build();
-//        //只满足首件
-//        if (Double.compare(templateDTO.getNumber(), templateDTO.getFirst()) <= 0) {
-//            storePostage = NumberUtil.round(NumberUtil.add(storePostage,
-//                    templateDTO.getFirstPrice()), 2);
-//        } else {
-//            BigDecimal firstPrice = NumberUtil.add(storePostage, templateDTO.getFirstPrice());
-//
-//            if (templateDTO.getContinues() <= 0) {
-//                storePostage = firstPrice;
-//            } else {
-//                //续件平均值且向上取整数
-//                double average = Math.ceil(NumberUtil.div(NumberUtil.sub(templateDTO.getNumber(),
-//                                templateDTO.getFirst()),
-//                        templateDTO.getContinues().doubleValue()));
-//                //最终邮费
-//                storePostage = NumberUtil.add(firstPrice, NumberUtil.mul(average,
-//                        templateDTO.getContinuePrice()));
-//            }
-//
-//        }
+        List<Long> citys = new ArrayList<>();
+        citys.add(cityId);
+        citys.add(0l);
+        String ids = String.valueOf(fsStoreProduct.getTempId());
+        //如果没有配置运费 直接返回
+        if(StringUtils.isBlank(ids)){
+            return storePostage;
+        }
+        List<FsShippingTemplatesScrm> shippingTemplatesList = shippingTemplatesService.selectFsShippingTemplatesByIds(ids);
+        String cityIds = String.join(",", citys.stream()
+                .map(String::valueOf).collect(Collectors.toList()));
+        List<FsShippingTemplatesRegionScrm> shippingTemplatesRegionList = shippingTemplatesRegionService.selectFsShippingTemplatesRegionListByTempIdsAndCityIds(ids,cityIds);
+        Map<Long, Integer> shippingTemplatesMap = shippingTemplatesList
+                .stream()
+                .collect(Collectors.toMap(FsShippingTemplatesScrm::getId,
+                        FsShippingTemplatesScrm::getType));
+        //提取运费模板有相同值覆盖
+        Map<Long, FsShippingTemplatesRegionScrm> shippingTemplatesRegionMap =
+                shippingTemplatesRegionList.stream()
+                        .collect(Collectors.toMap(FsShippingTemplatesRegionScrm::getTempId,
+                                YxShippingTemplatesRegion -> YxShippingTemplatesRegion,
+                                (key1, key2) -> key2));
+        Long tempId = Long.valueOf(fsStoreProduct.getTempId());
+        double num = 0d;
+        Integer templateType = shippingTemplatesMap.get(tempId);
+        List<FsStoreProductAttrValueScrm> productAttrValues = fsStoreProductAttrValueMapper.selectFsStoreProductAttrValueByProductId(fsStoreProduct.getProductId());
+        if(productAttrValues == null || productAttrValues.isEmpty()) {
+            return storePostage;
+        }
+        FsStoreProductAttrValueScrm productAttrValue = productAttrValues.get(0);
+        Integer totalNum = Integer.valueOf(totalNumSize);
+        // TYPE_1: 按件数计算
+        if (ShippingTempEnum.TYPE_1.getValue().equals(templateType)) {
+            num = totalNum.doubleValue();
+        }
+        // TYPE_2: 按重量计算(数量 × 重量)
+        else if (ShippingTempEnum.TYPE_2.getValue().equals(templateType)) {
+            num = NumberUtil.mul(totalNum, productAttrValue.getWeight()).doubleValue();
+        }
+        // TYPE_3: 按体积计算(数量 × 体积)
+        else if (ShippingTempEnum.TYPE_3.getValue().equals(templateType)) {
+            num = NumberUtil.mul(totalNum, productAttrValue.getVolume()).doubleValue();
+        }
+        FsShippingTemplatesRegionScrm shippingTemplatesRegion = shippingTemplatesRegionMap.get(tempId);
+        if (shippingTemplatesRegion == null) {
+            log.error("没有找到运费模板");
+            return storePostage;
+        }
+        BigDecimal price = NumberUtil.round(NumberUtil.mul(totalNum, fsStoreProduct.getPrice()), 2);
+
+        TemplateDTO templateDTO = TemplateDTO.builder()
+                .number(num)  // 累计数量(件数/重量/体积)
+                .price(price)  // 累计金额
+                .first(shippingTemplatesRegion.getFirst().doubleValue())  // 首件数量
+                .firstPrice(shippingTemplatesRegion.getFirstPrice())  // 首件运费
+                .continues(shippingTemplatesRegion.getContinues().doubleValue())  // 续件数量
+                .continuePrice(shippingTemplatesRegion.getContinuePrice())  // 续件运费
+                .tempId(tempId)  // 模板ID
+                .cityId(cityId.toString())  // 城市ID
+                .build();
+        //只满足首件
+        if (Double.compare(templateDTO.getNumber(), templateDTO.getFirst()) <= 0) {
+            storePostage = NumberUtil.round(NumberUtil.add(storePostage,
+                    templateDTO.getFirstPrice()), 2);
+        } else {
+            BigDecimal firstPrice = NumberUtil.add(storePostage, templateDTO.getFirstPrice());
+
+            if (templateDTO.getContinues() <= 0) {
+                storePostage = firstPrice;
+            } else {
+                //续件平均值且向上取整数
+                double average = Math.ceil(NumberUtil.div(NumberUtil.sub(templateDTO.getNumber(),
+                                templateDTO.getFirst()),
+                        templateDTO.getContinues().doubleValue()));
+                //最终邮费
+                storePostage = NumberUtil.add(firstPrice, NumberUtil.mul(average,
+                        templateDTO.getContinuePrice()));
+            }
+
+        }
 
         return storePostage;
     }
@@ -2847,9 +2856,25 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
         if(StringUtils.isNotEmpty(orderId)&&order.getOrderId().toString().equals(orderId)){
             return R.error("正在支付中...");
         }
-
         FsUserScrm user=userMapper.selectFsUserById(Long.valueOf(order.getUserId()));
-        if(user!=null&& StringUtils.isNotEmpty(user.getMaOpenId())){
+        if(user == null){
+            return R.error("未找到用户信息,请联系管理员!");
+        }
+        String json = configService.selectConfigByKey("his.pay");
+        FsPayConfigScrm fsPayConfig = JSON.parseObject(json, FsPayConfigScrm.class);
+        String openId;
+        if(StringUtils.isNotEmpty(user.getMaOpenId())){
+            log.info("用户信息有openid:{}", user.getMaOpenId());
+            openId = user.getMaOpenId();
+        }else{
+            Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                    .eq(FsUserWx::getFsUserId, order.getUserId())
+                    .eq(FsUserWx::getAppId, fsPayConfig.getAppId());
+            FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+            log.info("查到的openId信息:{}", fsUserWx);
+            openId = fsUserWx.getOpenId();
+        }
+        if(StringUtils.isNotEmpty(openId)){
             //已改价处理
             if(order.getIsEditMoney()!=null&&order.getIsEditMoney()==1){
                 //改过价不做处理
@@ -2888,8 +2913,6 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
 //            order.setOrderCode(orderCode);
 //            if(order.getPayType().equals("1")||order.getPayType().equals("2")){
             if((order.getPayType().equals("1")||order.getPayType().equals("2")||order.getPayType().equals("3")) && order.getPayMoney().compareTo(new BigDecimal(0))>0){
-                String json = configService.selectConfigByKey("his.pay");
-                FsPayConfigScrm fsPayConfig = JSON.parseObject(json, FsPayConfigScrm.class);
                 LiveOrderPayment storePayment=new LiveOrderPayment();
                 storePayment.setCompanyId(order.getCompanyId());
                 storePayment.setCompanyUserId(order.getCompanyUserId());
@@ -2899,9 +2922,9 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                 storePayment.setPayMoney(order.getPayMoney());
                 storePayment.setCreateTime(new Date());
                 storePayment.setPayTypeCode("weixin");
-                storePayment.setBusinessType(2);
+                storePayment.setBusinessType(5);
                 storePayment.setRemark("直播订单支付");
-                storePayment.setOpenId(user.getRealName());
+                storePayment.setOpenId(openId);
                 storePayment.setUserId(user.getUserId());
                 storePayment.setBusinessId(String.valueOf(order.getOrderId()));
                 storePayment.setAppId(fsPayConfig.getAppId() == null ? "" : fsPayConfig.getAppId());
@@ -2910,11 +2933,11 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                 if (fsPayConfig.getType().equals("hf")){
                     HuiFuCreateOrder o = new HuiFuCreateOrder();
                     o.setTradeType("T_MINIAPP");
-                    o.setOpenid(user.getMaOpenId());
+                    o.setOpenid(storePayment.getOpenId());
                     o.setReqSeqId("live-"+storePayment.getPayCode());
                     o.setTransAmt(storePayment.getPayMoney().toString());
                     o.setGoodsDesc("直播订单支付");
-                    if (param != null && StringUtils.isNotBlank(param.getAppId())) {
+                    if (StringUtils.isNotBlank(param.getAppId())) {
                         o.setAppId(param.getAppId());
                     }
                     HuifuCreateOrderResult result = huiFuService.createOrder(o);
@@ -2926,6 +2949,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                         mt.setBusinessCode(order.getOrderCode());
                         liveOrderPaymentMapper.updateLiveOrderPayment(mt);
                         redisCache.setCacheObject("isPaying:"+order.getOrderId(),order.getOrderId().toString(),1, TimeUnit.MINUTES);
+                        log.info("汇付支付");
                         Map<String, Object> resultMap = JSON.parseObject(result.getPay_info(), new TypeReference<Map<String, Object>>() {});
                         String s = (String) resultMap.get("package");
                         resultMap.put("packageValue",s);
@@ -2945,7 +2969,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                     payConfig.setNotifyUrl(fsPayConfig.getNotifyUrlScrm());
                     wxPayService.setConfig(payConfig);
                     WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
-                    orderRequest.setOpenid(user.getMaOpenId());//公众号支付提供用户openid
+                    orderRequest.setOpenid(storePayment.getOpenId());
                     orderRequest.setBody("直播订单支付");
                     orderRequest.setOutTradeNo("live-" + storePayment.getPayCode());
                     orderRequest.setTotalFee(WxPayUnifiedOrderRequest.yuanToFen(storePayment.getPayMoney().toString()));//测试
@@ -3270,9 +3294,11 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
 
         // 更改店铺库存
         fsStoreProduct.setStock(fsStoreProduct.getStock()-Integer.parseInt(liveOrder.getTotalNum()));
+        fsStoreProduct.setSales(fsStoreProduct.getSales()+Long.parseLong(liveOrder.getTotalNum()));
         fsStoreProductService.updateFsStoreProduct(fsStoreProduct);
         // 更新直播间库存
         goods.setStock(goods.getStock()-Integer.parseInt(liveOrder.getTotalNum()));
+        goods.setSales(goods.getSales()+Integer.parseInt(liveOrder.getTotalNum()));
         liveGoodsMapper.updateLiveGoods(goods);
 
         //判断是否是三种特定产品

+ 16 - 5
fs-service/src/main/java/com/fs/live/service/impl/LiveServiceImpl.java

@@ -6,13 +6,18 @@ import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fs.common.core.page.PageRequest;
 import com.fs.common.exception.base.BaseException;
 import com.fs.company.mapper.CompanyMapper;
 import com.fs.core.config.WxMaConfiguration;
 import com.fs.his.domain.FsStoreProduct;
 import com.fs.his.domain.FsUser;
+import com.fs.his.domain.FsUserWx;
 import com.fs.his.mapper.FsUserMapper;
+import com.fs.his.mapper.FsUserWxMapper;
 import com.fs.hisStore.domain.FsStoreProductScrm;
 import com.fs.hisStore.mapper.FsStoreProductScrmMapper;
 import com.fs.live.dto.TemplateMessageSendRequestDTO;
@@ -111,6 +116,8 @@ public class LiveServiceImpl implements ILiveService
     @Autowired
     private FsUserMapper fsUserMapper;
     @Autowired
+    private FsUserWxMapper fsUserWxMapper;
+    @Autowired
     private CompanyMapper companyMapper;
     @Autowired
     private LiveCouponMapper liveCouponMapper;
@@ -243,11 +250,15 @@ public class LiveServiceImpl implements ILiveService
         notifyTask.setPage("/pages_course/living?liveId=" + param.get("liveId"));
         notifyTask.setTaskName("直播间预约提醒");
         notifyTask.setTemplateId((String) param.get("templateId"));
-        FsUser fsUser = fsUserMapper.selectFsUserById(Long.valueOf((Integer) param.get("userId")));
-        String maOpenId = fsUser.getMaOpenId();
-        if (StringUtils.isEmpty(maOpenId)) {
-            maOpenId = (String) param.get("maOpenId");
-        }
+        Long userId = Long.valueOf((Integer) param.get("userId"));
+        Wrapper<FsUserWx> queryWrapper = Wrappers.<FsUserWx>lambdaQuery()
+                .eq(FsUserWx::getFsUserId, userId)
+                .eq(FsUserWx::getAppId, param.getOrDefault("appid", "wx44beed5640bcb1ba"));
+        FsUserWx fsUserWx = fsUserWxMapper.selectOne(queryWrapper);
+        String maOpenId = fsUserWx.getOpenId();
+//        if (StringUtils.isEmpty(maOpenId)) {
+//            maOpenId = (String) param.get("maOpenId");
+//        }
         notifyTask.setTouser(maOpenId);
         notifyTask.setPage(String.valueOf(1));
 

+ 46 - 0
fs-service/src/main/java/com/fs/qw/domain/QwApiSopLogToken.java

@@ -0,0 +1,46 @@
+package com.fs.qw.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 企业微信账号 发官方群发的统计对象 qw_api_sop_log_token
+ *
+ * @author fs
+ * @date 2025-11-26
+ */
+@Data
+public class QwApiSopLogToken {
+
+    /** $column.columnComment */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private String qwUserId;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private Long companyId;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private Date sendTime;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private Long sendCount;
+
+    /** $column.columnComment */
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    private Long sendCountToken;
+
+
+}

+ 61 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwApiSopLogTokenMapper.java

@@ -0,0 +1,61 @@
+package com.fs.qw.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.qw.domain.QwApiSopLogToken;
+
+/**
+ * 企业微信账号 发官方群发的统计Mapper接口
+ * 
+ * @author fs
+ * @date 2025-11-26
+ */
+public interface QwApiSopLogTokenMapper extends BaseMapper<QwApiSopLogToken>{
+    /**
+     * 查询企业微信账号 发官方群发的统计
+     * 
+     * @param id 企业微信账号 发官方群发的统计主键
+     * @return 企业微信账号 发官方群发的统计
+     */
+    QwApiSopLogToken selectQwApiSopLogTokenById(Long id);
+
+    /**
+     * 查询企业微信账号 发官方群发的统计列表
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 企业微信账号 发官方群发的统计集合
+     */
+    List<QwApiSopLogToken> selectQwApiSopLogTokenList(QwApiSopLogToken qwApiSopLogToken);
+
+    /**
+     * 新增企业微信账号 发官方群发的统计
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 结果
+     */
+    int insertQwApiSopLogToken(QwApiSopLogToken qwApiSopLogToken);
+
+    /**
+     * 修改企业微信账号 发官方群发的统计
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 结果
+     */
+    int updateQwApiSopLogToken(QwApiSopLogToken qwApiSopLogToken);
+
+    /**
+     * 删除企业微信账号 发官方群发的统计
+     * 
+     * @param id 企业微信账号 发官方群发的统计主键
+     * @return 结果
+     */
+    int deleteQwApiSopLogTokenById(Long id);
+
+    /**
+     * 批量删除企业微信账号 发官方群发的统计
+     * 
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteQwApiSopLogTokenByIds(Long[] ids);
+}

+ 61 - 0
fs-service/src/main/java/com/fs/qw/service/IQwApiSopLogTokenService.java

@@ -0,0 +1,61 @@
+package com.fs.qw.service;
+
+import java.util.List;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.qw.domain.QwApiSopLogToken;
+
+/**
+ * 企业微信账号 发官方群发的统计Service接口
+ * 
+ * @author fs
+ * @date 2025-11-26
+ */
+public interface IQwApiSopLogTokenService extends IService<QwApiSopLogToken>{
+    /**
+     * 查询企业微信账号 发官方群发的统计
+     * 
+     * @param id 企业微信账号 发官方群发的统计主键
+     * @return 企业微信账号 发官方群发的统计
+     */
+    QwApiSopLogToken selectQwApiSopLogTokenById(Long id);
+
+    /**
+     * 查询企业微信账号 发官方群发的统计列表
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 企业微信账号 发官方群发的统计集合
+     */
+    List<QwApiSopLogToken> selectQwApiSopLogTokenList(QwApiSopLogToken qwApiSopLogToken);
+
+    /**
+     * 新增企业微信账号 发官方群发的统计
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 结果
+     */
+    int insertQwApiSopLogToken(QwApiSopLogToken qwApiSopLogToken);
+
+    /**
+     * 修改企业微信账号 发官方群发的统计
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 结果
+     */
+    int updateQwApiSopLogToken(QwApiSopLogToken qwApiSopLogToken);
+
+    /**
+     * 批量删除企业微信账号 发官方群发的统计
+     * 
+     * @param ids 需要删除的企业微信账号 发官方群发的统计主键集合
+     * @return 结果
+     */
+    int deleteQwApiSopLogTokenByIds(Long[] ids);
+
+    /**
+     * 删除企业微信账号 发官方群发的统计信息
+     * 
+     * @param id 企业微信账号 发官方群发的统计主键
+     * @return 结果
+     */
+    int deleteQwApiSopLogTokenById(Long id);
+}

+ 91 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwApiSopLogTokenServiceImpl.java

@@ -0,0 +1,91 @@
+package com.fs.qw.service.impl;
+
+import java.util.List;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.fs.qw.mapper.QwApiSopLogTokenMapper;
+import com.fs.qw.domain.QwApiSopLogToken;
+import com.fs.qw.service.IQwApiSopLogTokenService;
+
+/**
+ * 企业微信账号 发官方群发的统计Service业务层处理
+ * 
+ * @author fs
+ * @date 2025-11-26
+ */
+@Service
+public class QwApiSopLogTokenServiceImpl extends ServiceImpl<QwApiSopLogTokenMapper, QwApiSopLogToken> implements IQwApiSopLogTokenService {
+
+    /**
+     * 查询企业微信账号 发官方群发的统计
+     * 
+     * @param id 企业微信账号 发官方群发的统计主键
+     * @return 企业微信账号 发官方群发的统计
+     */
+    @Override
+    public QwApiSopLogToken selectQwApiSopLogTokenById(Long id)
+    {
+        return baseMapper.selectQwApiSopLogTokenById(id);
+    }
+
+    /**
+     * 查询企业微信账号 发官方群发的统计列表
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 企业微信账号 发官方群发的统计
+     */
+    @Override
+    public List<QwApiSopLogToken> selectQwApiSopLogTokenList(QwApiSopLogToken qwApiSopLogToken)
+    {
+        return baseMapper.selectQwApiSopLogTokenList(qwApiSopLogToken);
+    }
+
+    /**
+     * 新增企业微信账号 发官方群发的统计
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 结果
+     */
+    @Override
+    public int insertQwApiSopLogToken(QwApiSopLogToken qwApiSopLogToken)
+    {
+        return baseMapper.insertQwApiSopLogToken(qwApiSopLogToken);
+    }
+
+    /**
+     * 修改企业微信账号 发官方群发的统计
+     * 
+     * @param qwApiSopLogToken 企业微信账号 发官方群发的统计
+     * @return 结果
+     */
+    @Override
+    public int updateQwApiSopLogToken(QwApiSopLogToken qwApiSopLogToken)
+    {
+        return baseMapper.updateQwApiSopLogToken(qwApiSopLogToken);
+    }
+
+    /**
+     * 批量删除企业微信账号 发官方群发的统计
+     * 
+     * @param ids 需要删除的企业微信账号 发官方群发的统计主键
+     * @return 结果
+     */
+    @Override
+    public int deleteQwApiSopLogTokenByIds(Long[] ids)
+    {
+        return baseMapper.deleteQwApiSopLogTokenByIds(ids);
+    }
+
+    /**
+     * 删除企业微信账号 发官方群发的统计信息
+     * 
+     * @param id 企业微信账号 发官方群发的统计主键
+     * @return 结果
+     */
+    @Override
+    public int deleteQwApiSopLogTokenById(Long id)
+    {
+        return baseMapper.deleteQwApiSopLogTokenById(id);
+    }
+}

+ 22 - 0
fs-service/src/main/java/com/fs/sop/mapper/QwSopLogsMapper.java

@@ -3,6 +3,7 @@ package com.fs.sop.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.common.annotation.DataSource;
 import com.fs.common.enums.DataSourceType;
+import com.fs.qw.domain.QwApiSopLogToken;
 import com.fs.qw.param.SopMsgParam;
 import com.fs.sop.domain.QwSopLogs;
 import com.fs.sop.params.*;
@@ -332,4 +333,25 @@ public interface QwSopLogsMapper extends BaseMapper<QwSopLogs> {
 
     @DataSource(DataSourceType.SOP)
     void batchUpdateQwSopLogsNewUserById(@Param("data")List<QwSopLogs> qwSopLogsList);
+
+    @DataSource(DataSourceType.SOP)
+    @Select("<script>" +
+            "SELECT\n" +
+            "  qw_user_key as qw_user_id,\n" +
+            "  company_id,\n" +
+            "  send_time,\n" +
+            "  count(*) as send_count," +
+            "  count(*)  * 150 as send_count_token \n" +
+            "FROM\n" +
+            "  `qw_sop_logs`\n" +
+            "WHERE\n" +
+            "  send_type = 1\n" +
+            "  AND send_status = 1\n" +
+            "  AND DATE(send_time) = #{data}\n" +
+            "GROUP BY\n" +
+            "  qw_user_key,\n" +
+            "  company_id\n" +
+            "ORDER BY qw_user_key" +
+            "</script>")
+    List<QwApiSopLogToken> countQwApiAopLogToken(@Param("data") String dateStr);
 }

+ 2 - 0
fs-service/src/main/java/com/fs/sop/service/IQwSopLogsService.java

@@ -132,4 +132,6 @@ public interface IQwSopLogsService extends IService<QwSopLogs>
 
 
     void updateBatch(List<QwSopLogs> collect);
+
+    void countQwApiAopLogToken(String dateStr);
 }

+ 11 - 1
fs-service/src/main/java/com/fs/sop/service/impl/QwSopLogsServiceImpl.java

@@ -17,14 +17,15 @@ import com.fs.company.service.ICompanyUserService;
 import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsCourseWatchLog;
 import com.fs.course.service.IFsCourseWatchLogService;
-import com.fs.course.service.IFsUserCompanyUserService;
 import com.fs.fastGpt.service.IFastGptChatSessionService;
+import com.fs.qw.domain.QwApiSopLogToken;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.domain.QwUser;
 import com.fs.qw.mapper.QwExternalContactMapper;
 import com.fs.qw.mapper.QwUserMapper;
 import com.fs.qw.param.SopMsgParam;
 import com.fs.qw.result.QwExternalContactByQwResult;
+import com.fs.qw.service.IQwApiSopLogTokenService;
 import com.fs.qw.service.impl.AsyncSopTestService;
 import com.fs.qw.service.impl.QwExternalContactServiceImpl;
 import com.fs.qw.vo.QwSopTempSetting;
@@ -109,6 +110,9 @@ public class QwSopLogsServiceImpl extends ServiceImpl<QwSopLogsMapper, QwSopLogs
 
     private AsyncSopTestService asyncSopTestService;
 
+    @Autowired
+    private IQwApiSopLogTokenService sopLogTokenService;
+
     @Autowired
     public void setAsyncSopTestService(@Lazy AsyncSopTestService asyncSopTestService){
         this.asyncSopTestService = asyncSopTestService;
@@ -1605,6 +1609,12 @@ public class QwSopLogsServiceImpl extends ServiceImpl<QwSopLogsMapper, QwSopLogs
         super.updateBatchById(collect);
     }
 
+    @Override
+    public void countQwApiAopLogToken(String dateStr) {
+        List<QwApiSopLogToken> qwApiSopLogTokens = qwSopLogsMapper.countQwApiAopLogToken(dateStr);
+        sopLogTokenService.saveBatch(qwApiSopLogTokens,500);
+    }
+
 
     // 定义一个方法来批量处理插入逻辑,支持每 500 条数据一次的批量插入
     private void processAndInsertQwSopLogs(List<QwSopLogsDoSendListTVO> logsByJsApiNotExtId) {

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

@@ -89,7 +89,7 @@ headerImg:
   imgUrl: https://hzyy.obs.cn-north-4.myhuaweicloud.com/fs/20250616/1750067609692.png
 ipad:
   ipadUrl: http://139.159.133.223:8667
-  aiApi: http://1.95.196.10:3000/api
+  aiApi: http://49.232.181.28:3000/api
   voiceApi:
   commonApi:
 wx_miniapp_temp:

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

@@ -92,7 +92,7 @@ headerImg:
   imgUrl: https://jz-cos-1356808054.cos.ap-chengdu.myqcloud.com/fs/20250515/0877754b59814ea8a428fa3697b20e68.png
 ipad:
   ipadUrl: http://ipad.xintaihl.cn
-  aiApi: http://1.95.196.10:3000/api
+  aiApi: http://49.232.181.28:3000/api
   voiceApi:
   commonApi:
 wx_miniapp_temp:

+ 76 - 0
fs-service/src/main/resources/mapper/his/FsIntegralOrderLogsMapper.xml

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.his.mapper.FsIntegralOrderLogsMapper">
+
+    <resultMap type="FsIntegralOrderLogs" id="FsIntegralOrderLogsResult">
+        <result property="logsId"    column="logs_id"    />
+        <result property="orderId"    column="order_id"    />
+        <result property="changeType"    column="change_type"    />
+        <result property="changeMessage"    column="change_message"    />
+        <result property="changeTime"    column="change_time"    />
+        <result property="operator"    column="operator"    />
+    </resultMap>
+
+    <sql id="selectFsIntegralOrderLogsVo">
+        select logs_id, order_id, change_type, change_message, change_time, operator from fs_integral_order_logs
+    </sql>
+
+    <select id="selectFsIntegralOrderLogsList" parameterType="FsIntegralOrderLogs" resultMap="FsIntegralOrderLogsResult">
+        <include refid="selectFsIntegralOrderLogsVo"/>
+        <where>
+            <if test="orderId != null  and orderId != ''"> and order_id = #{orderId}</if>
+            <if test="changeType != null  and changeType != ''"> and change_type = #{changeType}</if>
+            <if test="changeMessage != null  and changeMessage != ''"> and change_message = #{changeMessage}</if>
+            <if test="changeTime != null "> and change_time = #{changeTime}</if>
+            <if test="operator != null  and operator != ''"> and operator = #{operator}</if>
+        </where>
+    </select>
+
+    <select id="selectFsIntegralOrderLogsByLogsId" parameterType="String" resultMap="FsIntegralOrderLogsResult">
+        <include refid="selectFsIntegralOrderLogsVo"/>
+        where logs_id = #{logsId}
+    </select>
+
+    <insert id="insertFsIntegralOrderLogs" parameterType="FsIntegralOrderLogs" useGeneratedKeys="true" keyProperty="logsId">
+        insert into fs_integral_order_logs
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="orderId != null and orderId != ''">order_id,</if>
+            <if test="changeType != null and changeType != ''">change_type,</if>
+            <if test="changeMessage != null and changeMessage != ''">change_message,</if>
+            <if test="changeTime != null">change_time,</if>
+            <if test="operator != null">operator,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="orderId != null and orderId != ''">#{orderId},</if>
+            <if test="changeType != null and changeType != ''">#{changeType},</if>
+            <if test="changeMessage != null and changeMessage != ''">#{changeMessage},</if>
+            <if test="changeTime != null">#{changeTime},</if>
+            <if test="operator != null">#{operator},</if>
+        </trim>
+    </insert>
+
+    <update id="updateFsIntegralOrderLogs" parameterType="FsIntegralOrderLogs">
+        update fs_integral_order_logs
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="orderId != null and orderId != ''">order_id = #{orderId},</if>
+            <if test="changeType != null and changeType != ''">change_type = #{changeType},</if>
+            <if test="changeMessage != null and changeMessage != ''">change_message = #{changeMessage},</if>
+            <if test="changeTime != null">change_time = #{changeTime},</if>
+            <if test="operator != null">operator = #{operator},</if>
+        </trim>
+        where logs_id = #{logsId}
+    </update>
+
+    <delete id="deleteFsIntegralOrderLogsByLogsId" parameterType="String">
+        delete from fs_integral_order_logs where logs_id = #{logsId}
+    </delete>
+
+    <delete id="deleteFsIntegralOrderLogsByLogsIds" parameterType="String">
+        delete from fs_integral_order_logs where logs_id in
+        <foreach item="logsId" collection="array" open="(" separator="," close=")">
+            #{logsId}
+        </foreach>
+    </delete>
+</mapper>

+ 5 - 0
fs-service/src/main/resources/mapper/his/FsUserInformationCollectionMapper.xml

@@ -108,6 +108,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.packageOrderCode != null  and maps.packageOrderCode != ''"> and fui.package_order_code = #{maps.packageOrderCode}</if>
         </where>
     </select>
+    <select id="selectFsUserInformationCollectionByOrderCode"
+            resultType="com.fs.his.domain.FsUserInformationCollection">
+        <include refid="selectFsUserInformationCollectionVo"/>
+        where package_order_code = #{orderCode}
+    </select>
 
     <insert id="insertFsUserInformationCollection" parameterType="FsUserInformationCollection" useGeneratedKeys="true" keyProperty="id">
         insert into fs_user_information_collection

+ 78 - 0
fs-service/src/main/resources/mapper/qw/QwApiSopLogTokenMapper.xml

@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fs.qw.mapper.QwApiSopLogTokenMapper">
+
+    <resultMap type="QwApiSopLogToken" id="QwApiSopLogTokenResult">
+        <result property="id"    column="id"    />
+        <result property="qwUserId"    column="qw_user_id"    />
+        <result property="companyId"    column="company_id"    />
+        <result property="sendTime"    column="send_time"    />
+        <result property="sendCount"    column="send_count"    />
+        <result property="sendCountToken"    column="send_count_token"    />
+    </resultMap>
+
+    <sql id="selectQwApiSopLogTokenVo">
+        select id, qw_user_id, company_id, send_time, send_count, send_count_token from qw_api_sop_log_token
+    </sql>
+
+    <select id="selectQwApiSopLogTokenList" parameterType="QwApiSopLogToken" resultMap="QwApiSopLogTokenResult">
+        <include refid="selectQwApiSopLogTokenVo"/>
+        <where>
+            <if test="qwUserId != null  and qwUserId != ''"> and qw_user_id = #{qwUserId}</if>
+            <if test="companyId != null "> and company_id = #{companyId}</if>
+            <if test="sendTime != null "> and send_time = #{sendTime}</if>
+            <if test="sendCount != null "> and send_count = #{sendCount}</if>
+            <if test="sendCountToken != null "> and send_count_token = #{sendCountToken}</if>
+        </where>
+    </select>
+
+    <select id="selectQwApiSopLogTokenById" parameterType="Long" resultMap="QwApiSopLogTokenResult">
+        <include refid="selectQwApiSopLogTokenVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertQwApiSopLogToken" parameterType="QwApiSopLogToken">
+        insert into qw_api_sop_log_token
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="qwUserId != null">qw_user_id,</if>
+            <if test="companyId != null">company_id,</if>
+            <if test="sendTime != null">send_time,</if>
+            <if test="sendCount != null">send_count,</if>
+            <if test="sendCountToken != null">send_count_token,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="qwUserId != null">#{qwUserId},</if>
+            <if test="companyId != null">#{companyId},</if>
+            <if test="sendTime != null">#{sendTime},</if>
+            <if test="sendCount != null">#{sendCount},</if>
+            <if test="sendCountToken != null">#{sendCountToken},</if>
+         </trim>
+    </insert>
+
+    <update id="updateQwApiSopLogToken" parameterType="QwApiSopLogToken">
+        update qw_api_sop_log_token
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="qwUserId != null">qw_user_id = #{qwUserId},</if>
+            <if test="companyId != null">company_id = #{companyId},</if>
+            <if test="sendTime != null">send_time = #{sendTime},</if>
+            <if test="sendCount != null">send_count = #{sendCount},</if>
+            <if test="sendCountToken != null">send_count_token = #{sendCountToken},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteQwApiSopLogTokenById" parameterType="Long">
+        delete from qw_api_sop_log_token where id = #{id}
+    </delete>
+
+    <delete id="deleteQwApiSopLogTokenByIds" parameterType="String">
+        delete from qw_api_sop_log_token where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>