瀏覽代碼

Merge remote-tracking branch 'origin/master'

yfh 1 周之前
父節點
當前提交
88c2328863
共有 41 個文件被更改,包括 1293 次插入86 次删除
  1. 8 0
      fs-admin/src/main/java/com/fs/his/controller/FsIntegralOrderController.java
  2. 50 0
      fs-admin/src/main/java/com/fs/qw/controller/QwExternalContactTransferCompanyAuditController.java
  3. 1 1
      fs-admin/src/main/java/com/fs/qw/controller/QwSopController.java
  4. 6 4
      fs-company/src/main/java/com/fs/company/controller/company/CompanyController.java
  5. 47 1
      fs-company/src/main/java/com/fs/company/controller/qw/QwExternalContactController.java
  6. 56 0
      fs-company/src/main/java/com/fs/company/controller/qw/QwExternalContactTransferCompanyAuditController.java
  7. 86 4
      fs-company/src/main/java/com/fs/company/controller/qw/QwSopController.java
  8. 9 0
      fs-company/src/main/java/com/fs/company/controller/qw/QwUserController.java
  9. 8 6
      fs-qw-voice/src/main/java/com/fs/app/mq/RocketMQConsumerService.java
  10. 5 0
      fs-service/src/main/java/com/fs/company/mapper/CompanyMapper.java
  11. 5 0
      fs-service/src/main/java/com/fs/company/service/ICompanyService.java
  12. 9 0
      fs-service/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java
  13. 1 0
      fs-service/src/main/java/com/fs/his/mapper/FsIntegralOrderMapper.java
  14. 2 0
      fs-service/src/main/java/com/fs/his/service/IFsIntegralOrderService.java
  15. 33 0
      fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderServiceImpl.java
  16. 78 0
      fs-service/src/main/java/com/fs/qw/domain/QwExternalContactTransferCompanyAudit.java
  17. 60 0
      fs-service/src/main/java/com/fs/qw/domain/QwExternalContactTransferCompanyAuditUser.java
  18. 21 0
      fs-service/src/main/java/com/fs/qw/dto/CompanyTransferAuditDTO.java
  19. 32 0
      fs-service/src/main/java/com/fs/qw/dto/CompanyTransferDTO.java
  20. 14 0
      fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactTransferCompanyAuditMapper.java
  21. 20 0
      fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactTransferCompanyAuditUserMapper.java
  22. 5 1
      fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java
  23. 7 5
      fs-service/src/main/java/com/fs/qw/service/AsyncQwAiChatSopService.java
  24. 35 0
      fs-service/src/main/java/com/fs/qw/service/IQwExternalContactTransferCompanyAuditService.java
  25. 21 0
      fs-service/src/main/java/com/fs/qw/service/IQwExternalContactTransferCompanyAuditUserService.java
  26. 5 2
      fs-service/src/main/java/com/fs/qw/service/IQwUserService.java
  27. 46 9
      fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java
  28. 338 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactTransferCompanyAuditServiceImpl.java
  29. 43 0
      fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactTransferCompanyAuditUserServiceImpl.java
  30. 11 3
      fs-service/src/main/java/com/fs/qw/service/impl/QwUserServiceImpl.java
  31. 2 0
      fs-service/src/main/java/com/fs/qw/vo/QwExternalContactVO.java
  32. 8 6
      fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempServiceImpl.java
  33. 7 5
      fs-service/src/main/java/com/fs/sop/service/impl/SopUserLogsInfoServiceImpl.java
  34. 48 0
      fs-service/src/main/resources/db/20250928-企微客户公司转接.sql
  35. 7 0
      fs-service/src/main/resources/mapper/company/CompanyMapper.xml
  36. 4 0
      fs-service/src/main/resources/mapper/his/FsIntegralOrderMapper.xml
  37. 76 34
      fs-service/src/main/resources/mapper/his/FsStoreOrderMapper.xml
  38. 29 0
      fs-service/src/main/resources/mapper/qw/QwExternalContactTransferCompanyAuditMapper.xml
  39. 28 0
      fs-service/src/main/resources/mapper/qw/QwExternalContactTransferCompanyAuditUserMapper.xml
  40. 17 0
      fs-service/src/main/resources/mapper/qw/QwUserMapper.xml
  41. 5 5
      fs-service/src/main/resources/mapper/sop/QwSopTempContentMapper.xml

+ 8 - 0
fs-admin/src/main/java/com/fs/his/controller/FsIntegralOrderController.java

@@ -25,6 +25,7 @@ import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
+import java.util.Map;
 
 import static com.fs.his.utils.PhoneUtil.decryptAutoPhoneMk;
 import static com.fs.his.utils.PhoneUtil.decryptPhone;
@@ -170,4 +171,11 @@ public class FsIntegralOrderController extends BaseController
     {
         return toAjax(fsIntegralOrderService.deleteFsIntegralOrderByOrderIds(orderIds));
     }
+    @PreAuthorize("@ss.hasPermi('his:integralOrder:cancel')")
+    @Log(title = "积分商品订单", businessType = BusinessType.UPDATE)
+    @PostMapping("/cancelOrder")
+    public AjaxResult cancelOrder(@RequestBody Map<String, String> requestBody){
+        String orderCode = requestBody.get("orderCode");
+        return toAjax(fsIntegralOrderService.cancelOrder(orderCode));
+    }
 }

+ 50 - 0
fs-admin/src/main/java/com/fs/qw/controller/QwExternalContactTransferCompanyAuditController.java

@@ -0,0 +1,50 @@
+package com.fs.qw.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.model.LoginUser;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.utils.SecurityUtils;
+import com.fs.qw.domain.QwExternalContactTransferCompanyAudit;
+import com.fs.qw.dto.CompanyTransferAuditDTO;
+import com.fs.qw.service.IQwExternalContactTransferCompanyAuditService;
+import com.fs.qw.service.IQwExternalContactTransferCompanyAuditUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+@RestController
+@RequestMapping("/qw/externalContactTransferCompanyAudit")
+public class QwExternalContactTransferCompanyAuditController extends BaseController {
+
+    @Autowired
+    private IQwExternalContactTransferCompanyAuditService auditService;
+    @Autowired
+    private IQwExternalContactTransferCompanyAuditUserService auditUserService;
+
+    @PreAuthorize("@ss.hasPermi('qw:externalContactTransferCompanyAudit:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(QwExternalContactTransferCompanyAudit param) {
+        startPage();
+        List<QwExternalContactTransferCompanyAudit> list = auditService.selectQwExternalContactTransferCompanyAuditList(param);
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('qw:externalContactTransferCompanyAudit:detail')")
+    @GetMapping("/detail/{auditId}")
+    public AjaxResult detail(@PathVariable Long auditId) {
+        return AjaxResult.success(auditUserService.getListByAuditId(auditId));
+    }
+
+    @PreAuthorize("@ss.hasPermi('qw:externalContactTransferCompanyAudit:audit')")
+    @PostMapping("/audit")
+    public AjaxResult audit(@Valid @RequestBody CompanyTransferAuditDTO param) {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        auditService.audit(param, loginUser.getUser().getUserName());
+        return AjaxResult.success();
+    }
+
+}

+ 1 - 1
fs-admin/src/main/java/com/fs/qw/controller/QwSopController.java

@@ -52,6 +52,7 @@ public class QwSopController extends BaseController
     private FsUserCourseMapper fsUserCourseMapper;
     @Autowired
     private FsUserCourseVideoMapper fsUserCourseVideoMapper;
+
     /**
      * 查询企微sop列表
      */
@@ -133,7 +134,6 @@ public class QwSopController extends BaseController
         LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
         qwSop.setCreateBy(loginUser.getUser().getNickName());
         qwSop.setCreateTime(sdf.format(new Date()));
-
         return toAjax(qwSopService.insertQwSop(qwSop));
 
     }

+ 6 - 4
fs-company/src/main/java/com/fs/company/controller/company/CompanyController.java

@@ -17,10 +17,7 @@ import com.fs.framework.service.TokenService;
 import com.fs.his.vo.OptionsVO;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 
@@ -119,4 +116,9 @@ public class CompanyController extends BaseController
         return R.ok();
     }
 
+    @GetMapping("/getCompanyListByCorId/{corpId}")
+    public R getCompanyListByCorId(@PathVariable String corpId) {
+        List<OptionsVO> list = companyService.getCompanyListByCorpId(corpId);
+        return R.ok().put("data",list);
+    }
 }

+ 47 - 1
fs-company/src/main/java/com/fs/company/controller/qw/QwExternalContactController.java

@@ -11,6 +11,7 @@ import com.fs.common.utils.PubFun;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.company.domain.CompanyUser;
 import com.fs.company.service.impl.CompanyDeptServiceImpl;
 import com.fs.course.param.FsUserCourseListUParam;
 import com.fs.course.service.IFsUserCourseStudyService;
@@ -24,6 +25,7 @@ import com.fs.his.service.IFsUserService;
 import com.fs.qw.domain.QwContactWay;
 import com.fs.qw.domain.QwExternalContact;
 import com.fs.qw.domain.QwTag;
+import com.fs.qw.dto.CompanyTransferDTO;
 import com.fs.qw.param.*;
 import com.fs.qw.service.*;
 import com.fs.qw.vo.QwExternalContactVO;
@@ -40,6 +42,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
+import javax.validation.Valid;
 import java.io.IOException;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -80,6 +83,8 @@ public class QwExternalContactController extends BaseController
 
     @Autowired
     private CompanyDeptServiceImpl companyDeptService;
+    @Autowired
+    private IQwExternalContactTransferCompanyAuditService auditService;
 
     @Autowired
     private IQwContactWayService qwContactWayService;
@@ -289,7 +294,7 @@ public class QwExternalContactController extends BaseController
     /**
      * 导出企业微信客户列表
      */
-    @PreAuthorize("@ss.hasPermi('qw:externalContact:export')")
+    @PreAuthorize("@ss.hasAnyPermi('qw:externalContact:export,qw:externalContact:companyExport')")
     @Log(title = "企业微信客户", businessType = BusinessType.EXPORT)
     @GetMapping("/export")
     public AjaxResult export(QwExternalContactParam qwExternalContact)
@@ -728,4 +733,45 @@ public class QwExternalContactController extends BaseController
         return util.exportExcel(qwUserDelLossLogVOS, "企微用户删除流失统计");
     }
 
+    /**
+     * 公司客户
+     */
+    @PreAuthorize("@ss.hasPermi('qw:externalContact:companyExtList')")
+    @GetMapping("/companyExtList")
+    public TableDataInfo companyExtList(QwExternalContactParam qwExternalContact)
+    {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        qwExternalContact.setCompanyId(loginUser.getCompany().getCompanyId());
+
+        startPage();
+        List<QwExternalContactVO> list = qwExternalContactService.selectQwExternalContactListVO(qwExternalContact);
+        list.forEach(item->{
+
+            if (!Objects.equals(item.getTagIds(), "[]") && item.getTagIds()!=null) {
+                QwTagSearchParam param = new QwTagSearchParam();
+                Gson gson = new Gson();
+                List<String> tagIds = gson.fromJson(
+                        item.getTagIds(),
+                        new TypeToken<List<String>>() {
+                        }.getType()
+                );
+
+                param.setTagIds(tagIds);
+
+                item.setTagIdsName(iQwTagService.selectQwTagListByTagIds(param));
+            }
+        });
+
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('qw:externalContact:companyTransfer')")
+    @PostMapping("/companyTransfer")
+    public R companyTransfer(@Valid @RequestBody CompanyTransferDTO param) {
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        CompanyUser user = loginUser.getUser();
+        auditService.addAudit(param, user.getCompanyId(), user.getUserName());
+        return R.ok();
+    }
+
 }

+ 56 - 0
fs-company/src/main/java/com/fs/company/controller/qw/QwExternalContactTransferCompanyAuditController.java

@@ -0,0 +1,56 @@
+package com.fs.company.controller.qw;
+
+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.ServletUtils;
+import com.fs.framework.security.LoginUser;
+import com.fs.framework.service.TokenService;
+import com.fs.qw.domain.QwExternalContactTransferCompanyAudit;
+import com.fs.qw.service.IQwExternalContactTransferCompanyAuditService;
+import com.fs.qw.service.IQwExternalContactTransferCompanyAuditUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/qw/externalContactTransferCompanyAudit")
+public class QwExternalContactTransferCompanyAuditController extends BaseController {
+
+    @Autowired
+    private IQwExternalContactTransferCompanyAuditService auditService;
+    @Autowired
+    private IQwExternalContactTransferCompanyAuditUserService auditUserService;
+    @Autowired
+    private TokenService tokenService;
+
+    @PreAuthorize("@ss.hasPermi('qw:externalContactTransferCompanyAudit:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(QwExternalContactTransferCompanyAudit param) {
+        startPage();
+        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        Long companyId = loginUser.getCompany().getCompanyId();
+        param.setOperCompanyId(companyId);
+        List<QwExternalContactTransferCompanyAudit> list = auditService.selectQwExternalContactTransferCompanyAuditList(param);
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('qw:externalContactTransferCompanyAudit:sync')")
+    @Log(title = "公司转接同步", businessType = BusinessType.INSERT)
+    @PostMapping("/sync/{auditId}")
+    public R sync(@PathVariable("auditId") Long auditId) {
+        auditService.syncTransfer(auditId);
+        return R.ok();
+    }
+
+    @PreAuthorize("@ss.hasPermi('qw:externalContactTransferCompanyAudit:detail')")
+    @GetMapping("/detail/{auditId}")
+    public AjaxResult detail(@PathVariable Long auditId) {
+        return AjaxResult.success(auditUserService.getListByAuditId(auditId));
+    }
+}

+ 86 - 4
fs-company/src/main/java/com/fs/company/controller/qw/QwSopController.java

@@ -1,5 +1,6 @@
 package com.fs.company.controller.qw;
 
+import com.alibaba.fastjson.JSONObject;
 import com.fs.common.annotation.Log;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.controller.BaseController;
@@ -17,21 +18,29 @@ import com.fs.framework.service.TokenService;
 import com.fs.his.vo.OptionsVO;
 import com.fs.qw.domain.QwSopUpdateStatus;
 import com.fs.qw.service.IQwUserService;
+import com.fs.qw.vo.QwUserVO;
 import com.fs.sop.domain.QwSop;
+import com.fs.sop.domain.QwSopTempContent;
+import com.fs.sop.domain.QwSopTempVoice;
 import com.fs.sop.params.QwSopAutoTime;
 import com.fs.sop.params.QwSopEditQwUserParam;
 import com.fs.sop.service.ICompanySopRoleService;
 import com.fs.sop.service.IQwSopService;
+import com.fs.sop.service.IQwSopTempContentService;
+import com.fs.sop.service.IQwSopTempVoiceService;
 import com.fs.sop.vo.SopVoiceListVo;
+import org.apache.commons.beanutils.ConvertUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import java.io.IOException;
 import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * 企微sopController
@@ -64,6 +73,13 @@ public class QwSopController extends BaseController
     @Autowired
     private IQwUserService iQwUserService;
 
+
+    @Autowired
+    private IQwSopTempContentService qwSopTempContentService;
+
+    @Autowired
+    private IQwSopTempVoiceService voiceService;
+
     /**
      * 查询企微sop列表
      */
@@ -228,8 +244,13 @@ public class QwSopController extends BaseController
         qwSop.setCompanyId(companyId);
         qwSop.setCreateBy(loginUser.getUser().getNickName());
         qwSop.setCreateTime(sdf.format(new Date()));
-
-        return toAjax(qwSopService.insertQwSop(qwSop));
+        int count = qwSopService.insertQwSop(qwSop);
+        if(count > 0){
+            if(qwSop.getQwUserIds() != null){
+                updateTempVoiceInfo(qwSop);
+            }
+        }
+        return toAjax(count);
 
     }
 
@@ -241,7 +262,14 @@ public class QwSopController extends BaseController
     @PutMapping
     public R edit(@RequestBody QwSop qwSop)
     {
-        return qwSopService.updateQwSop(qwSop);
+        R sop = qwSopService.updateQwSop(qwSop);
+        String code = sop.get("code").toString();
+        if(code.equals("200")){
+            if(qwSop != null && qwSop.getQwUserIds() != null){
+                updateTempVoiceInfo(qwSop);
+            }
+        }
+        return sop;
     }
 
 
@@ -267,6 +295,52 @@ public class QwSopController extends BaseController
         return toAjax(qwSopService.updateAutoSopTime(param));
     }
 
+    /**
+     * 修改qwSop任务,新增或者删除qwUser
+     * @param qwSop
+     */
+    private void updateTempVoiceInfo(QwSop qwSop) {
+        try {
+            String tempId = qwSop.getTempId();
+            String[] split = qwSop.getQwUserIds().split(",");
+            Long[] qwUserIds = (Long[]) ConvertUtils.convert(split, Long.class);
+
+            List<QwSopTempContent> qwSopTempContentList = qwSopTempContentService.selectQwSopTempContentByTempId(tempId);
+            if(qwSopTempContentList != null && !qwSopTempContentList.isEmpty()){
+                for (QwSopTempContent qwSopTemp : qwSopTempContentList) {
+                    if(qwSopTemp != null && qwSopTemp.getContent() != null){
+                        String content = qwSopTemp.getContent();
+                        JSONObject jsonObject = JSONObject.parseObject(content);
+                        String voiceTxt = jsonObject.getString("value");
+                        String contentType = jsonObject.getString("contentType");
+                        if("7".equals(contentType)){
+                            List<QwUserVO> qwUserVoS = qwUserService.selectQwUserVOByIds(qwUserIds);
+                            if(qwUserVoS != null && !qwUserVoS.isEmpty()){
+                                List<Long> companyUserIdList = qwUserVoS.stream().map(QwUserVO::getCompanyUserId).collect(Collectors.toList());
+                                for (Long companyUserId : companyUserIdList) {
+                                    QwSopTempVoice qwSopTempVoice = voiceService.selectQwSopTempVoiceByCompanyUserIdAndVoiceTxt(companyUserId,voiceTxt);
+                                    if(qwSopTempVoice == null){
+                                        if(companyUserId != null && voiceTxt != null){
+                                            QwSopTempVoice tempVoice = new QwSopTempVoice();
+                                            tempVoice.setVoiceTxt(voiceTxt);
+                                            tempVoice.setCompanyUserId(companyUserId);
+                                            tempVoice.setRecordType(0);
+                                            tempVoice.setCreateTime(LocalDateTime.now());
+                                            tempVoice.setTempId(tempId);
+                                            voiceService.insertQwSopTempVoice(tempVoice);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            logger.error("修改企微sop任务,新增或者删除qwUser异常:" + e.getMessage());
+        }
+    }
+
     /**
      * 删除企微sop
      */
@@ -307,7 +381,15 @@ public class QwSopController extends BaseController
     @PreAuthorize("@ss.hasPermi('qw:sop:updateSopQwUser')")
     public R updateSopQwUser(@RequestBody QwSopEditQwUserParam param)
     {
-        return qwSopService.updateSopQwUser(param);
+        R sop = qwSopService.updateSopQwUser(param);
+        String code = sop.get("code").toString();
+        if(code.equals("200")){
+            QwSop qwSop = qwSopService.selectQwSopById(param.getId());
+            if(qwSop != null && qwSop.getQwUserIds() != null){
+                updateTempVoiceInfo(qwSop);
+            }
+        }
+        return sop;
     }
 
     /**

+ 9 - 0
fs-company/src/main/java/com/fs/company/controller/qw/QwUserController.java

@@ -842,4 +842,13 @@ public class QwUserController extends BaseController
         return R.ok();
     }
 
+    @GetMapping("/companyQwUserlist")
+    public TableDataInfo companyQwUserlist(@RequestParam Long companyId,
+                                           @RequestParam String corpId,
+                                           @RequestParam(required = false) String nickName)
+    {
+        startPage();
+        List<QwUserVO> list = qwUserService.selectQwUserListByCompanyIdAndCorpIdAndNickName(companyId, corpId, nickName);
+        return getDataTable(list);
+    }
 }

+ 8 - 6
fs-qw-voice/src/main/java/com/fs/app/mq/RocketMQConsumerService.java

@@ -77,12 +77,14 @@ public class RocketMQConsumerService implements RocketMQListener<String> {
                                             Long companyUserId = qwUserVO.getCompanyUserId();
                                             QwSopTempVoice qwSopTempVoice = qwSopTempVoiceService.selectQwSopTempVoiceByCompanyUserIdAndVoiceTxt(companyUserId,text);
                                             if(qwSopTempVoice == null){
-                                                QwSopTempVoice sopTempVoice = new QwSopTempVoice();
-                                                sopTempVoice.setCompanyUserId(companyUserId);
-                                                sopTempVoice.setVoiceTxt(text);
-                                                sopTempVoice.setTempId(tempId);
-                                                sopTempVoice.setRecordType(0);
-                                                qwSopTempVoiceService.insertQwSopTempVoice(sopTempVoice);
+                                                if(companyUserId != null && text != null){
+                                                    QwSopTempVoice sopTempVoice = new QwSopTempVoice();
+                                                    sopTempVoice.setCompanyUserId(companyUserId);
+                                                    sopTempVoice.setVoiceTxt(text);
+                                                    sopTempVoice.setTempId(tempId);
+                                                    sopTempVoice.setRecordType(0);
+                                                    qwSopTempVoiceService.insertQwSopTempVoice(sopTempVoice);
+                                                }
                                             }
                                         }
                                     }

+ 5 - 0
fs-service/src/main/java/com/fs/company/mapper/CompanyMapper.java

@@ -198,4 +198,9 @@ public interface CompanyMapper
 
 
     List<CompanyUser> selectCompanyListByIds(@Param("userIds") String result);
+
+    /**
+     * 查询企微主体管理公司列表
+     */
+    List<OptionsVO> getCompanyListByCorpId(@Param("corpId") String corpId);
 }

+ 5 - 0
fs-service/src/main/java/com/fs/company/service/ICompanyService.java

@@ -161,5 +161,10 @@ public interface ICompanyService
      */
     List<CompanyUser> selectCompanyListByIds(String result);
 
+    /**
+     * 查询企微主体管理公司列表
+     */
+    List<OptionsVO> getCompanyListByCorpId(String corpId);
+
     void subtractCompanyMoneyHourse(BigDecimal money, Long companyId, LocalTime start, LocalTime end);
 }

+ 9 - 0
fs-service/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java

@@ -1248,6 +1248,15 @@ public class CompanyServiceImpl implements ICompanyService
     public List<CompanyUser> selectCompanyListByIds(String result) {
         return companyMapper.selectCompanyListByIds(result);
     }
+
+    /**
+     * 查询企微主体管理公司列表
+     */
+    @Override
+    public List<OptionsVO> getCompanyListByCorpId(String corpId) {
+        return companyMapper.getCompanyListByCorpId(corpId);
+    }
+
     @Override
     @Transactional
     public void subtractCompanyMoneyHourse(BigDecimal money, Long companyId, LocalTime start, LocalTime end) {

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

@@ -107,4 +107,5 @@ public interface FsIntegralOrderMapper
     @Select("select fio.*,fu.nick_name,fu.phone from fs_integral_order fio left join fs_user fu on fu.user_id = fio.user_id where order_id=#{orderId} ")
     FsIntegralOrderPVO selectFsIntegralOrderPVO(Long orderId);
 
+    int cancelOrder(@Param("orderId") Long orderId);
 }

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

@@ -103,4 +103,6 @@ public interface IFsIntegralOrderService
     R payConfirm(String orderSn, String payCode, String tradeNo, String payType, int type,String bankTransactionId,String bankSerialNo);
 
     AjaxResult export(FsIntegralOrder fsIntegralOrder);
+
+    int cancelOrder(String orderCode);
 }

+ 33 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsIntegralOrderServiceImpl.java

@@ -619,6 +619,39 @@ public class FsIntegralOrderServiceImpl implements IFsIntegralOrderService
         return util.exportExcel(new ArrayList<>(fsIntegralOrderSet), "积分商品订单数据");
     }
 
+    @Override
+    @Transactional
+    public int cancelOrder(String orderCode) {
+        //查询订单是否存在且是否未发货
+        FsIntegralOrder fsIntegralOrder = fsIntegralOrderMapper.selectFsIntegralOrderByOrderCode(orderCode);
+        if (null==fsIntegralOrder){
+            throw new ServiceException("订单不存在");
+        }
+        if (fsIntegralOrder.getStatus()!=1){
+            throw new ServiceException("订单已发货或已完成");
+        }
+        int i = 0;
+        //修改订单状态
+        i = fsIntegralOrderMapper.cancelOrder(fsIntegralOrder.getOrderId());
+        if (i>0){
+            //原路退回积分
+            FsUser fsUser = fsUserMapper.selectFsUserByUserId(fsIntegralOrder.getUserId());
+            fsUser.setIntegral(fsUser.getIntegral()+Long.parseLong(fsIntegralOrder.getIntegral()));
+            i = fsUserMapper.updateFsUser(fsUser);
+            //新增积分记录
+            FsUserIntegralLogs fsUserIntegralLogs = new FsUserIntegralLogs();
+            fsUserIntegralLogs.setBalance(fsUser.getIntegral());
+            fsUserIntegralLogs.setBusinessId(fsIntegralOrder.getOrderId().toString());
+            fsUserIntegralLogs.setUserId(fsIntegralOrder.getUserId());
+            fsUserIntegralLogs.setLogType(20);
+            fsUserIntegralLogs.setIntegral(Long.parseLong(fsIntegralOrder.getIntegral()));
+            fsUserIntegralLogs.setBusinessType(2);
+            fsUserIntegralLogs.setStatus(0);
+            i = fsUserIntegralLogsMapper.insertFsUserIntegralLogs(fsUserIntegralLogs);
+        }
+        return i;
+    }
+
     /**
      * 处理手机号脱敏
      */

+ 78 - 0
fs-service/src/main/java/com/fs/qw/domain/QwExternalContactTransferCompanyAudit.java

@@ -0,0 +1,78 @@
+package com.fs.qw.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+@TableName("qw_external_contact_transfer_company_audit")
+public class QwExternalContactTransferCompanyAudit {
+
+    @ApiModelProperty("主键ID")
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty("企微主体ID")
+    private Long qwCompanyId;
+
+    @ApiModelProperty("企微CorpID")
+    private String corpId;
+
+    @ApiModelProperty("企微主体名称")
+    private String corpName;
+
+    @ApiModelProperty("接替公司ID")
+    private Long companyId;
+
+    @ApiModelProperty("接替公司名称")
+    private String companyName;
+
+    @ApiModelProperty("接替公司销售ID")
+    private Long companyUserId;
+
+    @ApiModelProperty("接替公司销售名称")
+    private String companyUserName;
+
+    @ApiModelProperty("接替企微用户ID")
+    private Long qwUserId;
+
+    @ApiModelProperty("接替企微用户ID(企微)")
+    private String qwUserExtId;
+
+    @ApiModelProperty("接替企微用户名称")
+    private String qwUserName;
+
+    @ApiModelProperty("消息内容")
+    private String content;
+
+    @ApiModelProperty("转接类型 1在职转接 2离职转接")
+    private Integer transferType;
+
+    @ApiModelProperty("状态 1待审核 2审核通过 3审核被拒")
+    private Integer status;
+
+    @ApiModelProperty("被拒原因")
+    private String reason;
+
+    @ApiModelProperty("备注")
+    private String remark;
+
+    @ApiModelProperty("审核时间")
+    private LocalDateTime auditTime;
+
+    @ApiModelProperty("审核人")
+    private String auditBy;
+
+    @ApiModelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("创建人")
+    private String createBy;
+
+    @ApiModelProperty("提审公司")
+    private Long operCompanyId;
+}

+ 60 - 0
fs-service/src/main/java/com/fs/qw/domain/QwExternalContactTransferCompanyAuditUser.java

@@ -0,0 +1,60 @@
+package com.fs.qw.domain;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+@TableName("qw_external_contact_transfer_company_audit_user")
+public class QwExternalContactTransferCompanyAuditUser {
+
+    @ApiModelProperty("主键ID")
+    private Long id;
+
+    @ApiModelProperty("审核记录ID")
+    private Long auditId;
+
+    @ApiModelProperty("外部联系人ID")
+    private Long externalId;
+
+    @ApiModelProperty("客户ID(企微)")
+    private String externalUserId;
+
+    @ApiModelProperty("客户名称")
+    private String externalUserName;
+
+    @ApiModelProperty("原公司ID")
+    private Long companyId;
+
+    @ApiModelProperty("原公司名称")
+    private String companyName;
+
+    @ApiModelProperty("原公司销售ID")
+    private Long companyUserId;
+
+    @ApiModelProperty("原公司销售名称")
+    private String companyUserName;
+
+    @ApiModelProperty("原企微用户ID")
+    private Long qwUserId;
+
+    @ApiModelProperty("原企微用户ID(企微)")
+    private String qwUserExtId;
+
+    @ApiModelProperty("原企微用户名称")
+    private String qwUserName;
+
+    @ApiModelProperty("0-待处理 1-接替完毕 2-等待接替 3-客户拒绝 4-接替成员客户达到上限")
+    private Integer status;
+
+    @ApiModelProperty("备注")
+    private String remark;
+
+    @ApiModelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("接替时间")
+    private LocalDateTime replaceTime;
+}

+ 21 - 0
fs-service/src/main/java/com/fs/qw/dto/CompanyTransferAuditDTO.java

@@ -0,0 +1,21 @@
+package com.fs.qw.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+@Data
+public class CompanyTransferAuditDTO {
+
+    @NotNull(message = "审核记录不能为空")
+    @ApiModelProperty("审核记录ID")
+    private Long auditId;
+
+    @ApiModelProperty("审核类型 1通过 2拒绝")
+    @NotNull(message = "审核类型不能为空")
+    private Integer type;
+
+    @ApiModelProperty("拒绝理由")
+    private String reason;
+}

+ 32 - 0
fs-service/src/main/java/com/fs/qw/dto/CompanyTransferDTO.java

@@ -0,0 +1,32 @@
+package com.fs.qw.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@Data
+public class CompanyTransferDTO {
+
+    @NotNull(message = "接替员工不能为空")
+    @ApiModelProperty("接替企微用户")
+    private Long qwUserId;
+
+    @ApiModelProperty("转移外部联系人")
+    private List<Long> ids;
+
+    @ApiModelProperty("消息内容")
+    private String content;
+
+    @ApiModelProperty("转移类型 0.转移ids外部联系人 1.转移qwUserName员工下外部联系人")
+    private Integer type = 0;
+
+    @NotNull(message = "转接类型不能为空")
+    @ApiModelProperty("转接类型 1在职转接 2离职转接")
+    private Integer transferType;
+
+    @ApiModelProperty("原员工企微ID")
+    private Long oldQwUserId;
+}

+ 14 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactTransferCompanyAuditMapper.java

@@ -0,0 +1,14 @@
+package com.fs.qw.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.qw.domain.QwExternalContactTransferCompanyAudit;
+
+import java.util.List;
+
+public interface QwExternalContactTransferCompanyAuditMapper extends BaseMapper<QwExternalContactTransferCompanyAudit> {
+
+    /**
+     * 查询审核记录列表
+     */
+    List<QwExternalContactTransferCompanyAudit> selectQwExternalContactTransferCompanyAuditList(QwExternalContactTransferCompanyAudit param);
+}

+ 20 - 0
fs-service/src/main/java/com/fs/qw/mapper/QwExternalContactTransferCompanyAuditUserMapper.java

@@ -0,0 +1,20 @@
+package com.fs.qw.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fs.qw.domain.QwExternalContactTransferCompanyAuditUser;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface QwExternalContactTransferCompanyAuditUserMapper extends BaseMapper<QwExternalContactTransferCompanyAuditUser> {
+
+    /**
+     * 根据ID集合查询已提交的记录
+     */
+    List<QwExternalContactTransferCompanyAuditUser> getExistAuditByExtIds(@Param("ids") List<Long> ids);
+
+    /**
+     * 查询接替记录
+     */
+    List<QwExternalContactTransferCompanyAuditUser> selectListByExtIdAndTakeoverUserIdAndCorpId(@Param("externalUserID") String externalUserID, @Param("takeoverUserId") String takeoverUserId, @Param("corpId") String corpId);
+}

+ 5 - 1
fs-service/src/main/java/com/fs/qw/mapper/QwUserMapper.java

@@ -12,7 +12,6 @@ import com.fs.qw.vo.*;
 import com.fs.qw.vo.sidebar.ExternalContactQwUserVO;
 import com.fs.sop.domain.QwSop;
 import com.fs.sop.dto.SopUserLogsParamDTO;
-import org.apache.commons.lang3.tuple.Pair;
 import org.apache.ibatis.annotations.MapKey;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
@@ -433,4 +432,9 @@ public interface QwUserMapper extends BaseMapper<QwUser>
     void updateSendType(UpdateSendTypeVo vo);
 
     QwUser selectOfflineUser();
+
+    /**
+     * 根据销售公司和企微ID查询企微用户
+     */
+    List<QwUserVO> selectQwUserListVOByCompanyIdAndCorpIdAndNickName(@Param("companyId") Long companyId, @Param("corpId") String corpId, @Param("nickName") String nickName);
 }

+ 7 - 5
fs-service/src/main/java/com/fs/qw/service/AsyncQwAiChatSopService.java

@@ -317,11 +317,13 @@ public class AsyncQwAiChatSopService {
             setting.setVoiceUrl(qwSopTempVoice.getVoiceUrl());
             setting.setVoiceDuration(String.valueOf(qwSopTempVoice.getDuration()));
         } else if (qwSopTempVoice == null) {
-            qwSopTempVoice = new QwSopTempVoice();
-            qwSopTempVoice.setCompanyUserId(companyUserId);
-            qwSopTempVoice.setVoiceTxt(setting.getValue());
-            qwSopTempVoice.setRecordType(0);
-            sopTempVoiceService.insertQwSopTempVoice(qwSopTempVoice);
+            if(companyUserId != null && setting.getValue() != null){
+                qwSopTempVoice = new QwSopTempVoice();
+                qwSopTempVoice.setCompanyUserId(companyUserId);
+                qwSopTempVoice.setVoiceTxt(setting.getValue());
+                qwSopTempVoice.setRecordType(0);
+                sopTempVoiceService.insertQwSopTempVoice(qwSopTempVoice);
+            }
         }
     }
 

+ 35 - 0
fs-service/src/main/java/com/fs/qw/service/IQwExternalContactTransferCompanyAuditService.java

@@ -0,0 +1,35 @@
+package com.fs.qw.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.qw.domain.QwExternalContactTransferCompanyAudit;
+import com.fs.qw.dto.CompanyTransferAuditDTO;
+import com.fs.qw.dto.CompanyTransferDTO;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+import java.util.List;
+
+
+public interface IQwExternalContactTransferCompanyAuditService extends IService<QwExternalContactTransferCompanyAudit> {
+
+    /**
+     * 添加待审核记录
+     */
+    void addAudit(CompanyTransferDTO param, Long companyId, String userName);
+
+    /**
+     * 查询审核记录列表
+     */
+    List<QwExternalContactTransferCompanyAudit> selectQwExternalContactTransferCompanyAuditList(QwExternalContactTransferCompanyAudit param);
+
+    /**
+     * 记录审核
+     */
+    void audit(CompanyTransferAuditDTO param, String userName);
+
+    /**
+     * 同步最新状态
+     */
+    void syncTransfer(Long auditId);
+}

+ 21 - 0
fs-service/src/main/java/com/fs/qw/service/IQwExternalContactTransferCompanyAuditUserService.java

@@ -0,0 +1,21 @@
+package com.fs.qw.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fs.qw.domain.QwExternalContactTransferCompanyAuditUser;
+import com.fs.qw.dto.CompanyTransferAuditDTO;
+
+import javax.validation.Valid;
+import java.util.List;
+
+public interface IQwExternalContactTransferCompanyAuditUserService extends IService<QwExternalContactTransferCompanyAuditUser> {
+
+    /**
+     * 根据ID集合查询已提交的记录
+     */
+    List<QwExternalContactTransferCompanyAuditUser> getExistAuditByExtIds(List<Long> ids);
+
+    /**
+     * 根据审核ID查询记录
+     */
+    List<QwExternalContactTransferCompanyAuditUser> getListByAuditId(Long auditId);
+}

+ 5 - 2
fs-service/src/main/java/com/fs/qw/service/IQwUserService.java

@@ -7,9 +7,7 @@ import com.fs.qw.dto.QwUserKeyDTO;
 import com.fs.qw.param.*;
 import com.fs.qw.vo.*;
 import com.fs.sop.domain.QwSop;
-import org.apache.commons.lang3.tuple.Pair;
 
-import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -193,4 +191,9 @@ public interface IQwUserService
     void atMsg(QwUser qwUser, String s);
 
     void changeVideoStatus(Long id);
+
+    /**
+     * 根据销售公司和企微ID查询企微用户
+     */
+    List<QwUserVO> selectQwUserListByCompanyIdAndCorpIdAndNickName(Long companyId, String corpId, String nickName);
 }

+ 46 - 9
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactServiceImpl.java

@@ -203,9 +203,13 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
 
     @Autowired
     private ISysDictTypeService dictTypeService;
+    @Autowired
+    private QwExternalContactTransferCompanyAuditUserMapper transferCompanyAuditUserMapper;
 
     @Autowired
     private AsyncQwAiChatSopService asyncQwAiChatSopService;
+    @Autowired
+    private QwExternalContactTransferCompanyAuditUserMapper companyAuditUserMapper;
 
 
     Logger logger = LoggerFactory.getLogger(getClass());
@@ -2172,19 +2176,27 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
 
     @Override
     public QwUser getQwUserByRedisForId(String qwUserId) {
-        String key =(String)redisCache.getCacheObject("qwUserRdById:"+qwUserId);
-        if (ObjectUtils.isNotEmpty(key)&& !StringUtil.strIsNullOrEmpty(key)){
-            return JSON.parseObject(key, QwUser.class);
-        }
-        logger.error("qwUserId:{}",qwUserId);
-        if (ObjectUtils.isEmpty(qwUserId)||qwUserId.equals("null")){
-            return null;
+
+        String redisKey = "qwUserRdById:" + qwUserId;
+
+        // 直接从Redis获取JSON字符串
+        String cachedJson = (String) redisCache.getCacheObject(redisKey);
+        if (!StringUtil.strIsNullOrEmpty(cachedJson)) {
+            try {
+                return JSON.parseObject(cachedJson, QwUser.class);
+            } catch (Exception e) {
+                // 解析失败时删除缓存,重新查询
+                redisCache.deleteObject(redisKey);
+            }
         }
+
         QwUser qwUser = qwUserMapper.selectQwUserById(Long.valueOf(qwUserId));
-        if (qwUser==null){
+        if (qwUser == null) {
             return null;
         }
-        redisCache.setCacheObject("qwUserRdById:"+qwUser.getId() ,JSON.toJSONString(qwUser),1, TimeUnit.HOURS);
+
+        // 存储时确保是JSON字符串
+        redisCache.setCacheObject(redisKey, JSON.toJSONString(qwUser), 1, TimeUnit.HOURS);
         return qwUser;
     }
     ;
@@ -2765,6 +2777,23 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
             qwExternalContactMapper.updateQwExternalContactByUseridTransfer(contact1);
         }
 
+        // 跨公司接替回调处理
+        List<QwExternalContactTransferCompanyAuditUser> auditUserList = transferCompanyAuditUserMapper.selectListByExtIdAndTakeoverUserIdAndCorpId(externalUserID, userID, corpId);
+        if (!auditUserList.isEmpty()) {
+            for (QwExternalContactTransferCompanyAuditUser auditUser : auditUserList) {
+                auditUser.setStatus(1);
+                transferCompanyAuditUserMapper.updateById(auditUser);
+            }
+
+            QwExternalContact contact1 = new QwExternalContact();
+            contact1.setUserId(userID);
+            contact1.setCorpId(corpId);
+            contact1.setStatus(4);
+            contact1.setTransferStatus(1);
+            contact1.setExternalUserId(externalUserID);
+            qwExternalContactMapper.updateQwExternalContactByUseridTransfer(contact1);
+        }
+
         //上面存过了,这里就更新
         qwExternalContact.setId(contact.getId());
         qwExternalContactMapper.updateQwExternalContact(qwExternalContact);
@@ -4278,6 +4307,14 @@ public class QwExternalContactServiceImpl extends ServiceImpl<QwExternalContactM
                 qwExternalContactTransferLogMapper.updateQwExternalContactTransferLog(externalContactTransferLog);
             }
 
+        // 跨公司接替回调处理
+        List<QwExternalContactTransferCompanyAuditUser> auditUserList = transferCompanyAuditUserMapper.selectListByExtIdAndTakeoverUserIdAndCorpId(externalUserID, userID, corpId);
+        for (QwExternalContactTransferCompanyAuditUser auditUser : auditUserList) {
+            auditUser.setStatus(status);
+            auditUser.setRemark(failReason);
+            transferCompanyAuditUserMapper.updateById(auditUser);
+        }
+
     }
 
     @Override

+ 338 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactTransferCompanyAuditServiceImpl.java

@@ -0,0 +1,338 @@
+package com.fs.qw.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.exception.ServiceException;
+import com.fs.common.utils.StringUtils;
+import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.mapper.CompanyMapper;
+import com.fs.company.mapper.CompanyUserMapper;
+import com.fs.qw.domain.*;
+import com.fs.qw.dto.CompanyTransferAuditDTO;
+import com.fs.qw.dto.CompanyTransferDTO;
+import com.fs.qw.mapper.QwCompanyMapper;
+import com.fs.qw.mapper.QwExternalContactMapper;
+import com.fs.qw.mapper.QwExternalContactTransferCompanyAuditMapper;
+import com.fs.qw.mapper.QwUserMapper;
+import com.fs.qw.service.IQwExternalContactTransferCompanyAuditService;
+import com.fs.qw.service.IQwExternalContactTransferCompanyAuditUserService;
+import com.fs.qwApi.domain.QwGetTransferResult;
+import com.fs.qwApi.domain.QwTransferCustomerResignedResult;
+import com.fs.qwApi.domain.QwTransferCustomerResult;
+import com.fs.qwApi.domain.inner.QwCustomer;
+import com.fs.qwApi.param.QwGetTransferParam;
+import com.fs.qwApi.param.QwTransferCustomerParam;
+import com.fs.qwApi.param.QwTransferCustomerResignedParam;
+import com.fs.qwApi.service.QwApiService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+public class QwExternalContactTransferCompanyAuditServiceImpl extends ServiceImpl<QwExternalContactTransferCompanyAuditMapper, QwExternalContactTransferCompanyAudit>
+        implements IQwExternalContactTransferCompanyAuditService {
+
+    @Resource
+    private QwUserMapper qwUserMapper;
+    @Resource
+    private QwExternalContactMapper contactMapper;
+    @Resource
+    private QwCompanyMapper qwCompanyMapper;
+    @Resource
+    private CompanyMapper companyMapper;
+    @Resource
+    private CompanyUserMapper companyUserMapper;
+    @Resource
+    private IQwExternalContactTransferCompanyAuditUserService auditUserService;
+    @Autowired
+    private QwApiService qwApiService;
+
+    /**
+     * 添加待审核记录
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void addAudit(CompanyTransferDTO param, Long companyId, String userName) {
+        if (param.getTransferType() != 1 && param.getTransferType() != 2) {
+            throw new ServiceException("转接类型错误");
+        }
+
+        QwUser qwUser = qwUserMapper.selectQwUserById(param.getQwUserId());
+
+        if (Objects.isNull(qwUser)) {
+            throw new ServiceException("接替员工不存在");
+        }
+
+        if (qwUser.getCompanyId().equals(companyId)) {
+            throw new ServiceException("接替员工不能为本公司员工");
+        }
+
+        List<QwExternalContact> qwExternalContacts = new ArrayList<>();
+        // 为1转移员工下客户 其余转移转递的客户
+        if (param.getType() == 1) {
+            if (Objects.nonNull(param.getOldQwUserId())) {
+                QwExternalContact params = new QwExternalContact();
+                params.setCompanyId(companyId);
+                params.setQwUserId(param.getOldQwUserId());
+                qwExternalContacts = contactMapper.selectQwExternalContactList(params);
+            }
+        } else {
+            qwExternalContacts = contactMapper.selectQwExternalContactByIds(param.getIds());
+        }
+
+        boolean hasNotCurrentCompanyUser = qwExternalContacts.stream().anyMatch(c -> !c.getCompanyId().equals(companyId));
+        if (hasNotCurrentCompanyUser) {
+            throw new ServiceException("只能转移本公司下的客户");
+        }
+
+        if (qwExternalContacts.isEmpty()) {
+            throw new ServiceException("请选择需要分配的客户");
+        }
+
+        List<Long> extIds = qwExternalContacts.stream().map(QwExternalContact::getId).collect(Collectors.toList());
+        List<QwExternalContactTransferCompanyAuditUser> existAuditList = auditUserService.getExistAuditByExtIds(extIds);
+        if (!existAuditList.isEmpty()) {
+            String names = existAuditList.stream().map(QwExternalContactTransferCompanyAuditUser::getExternalUserName).collect(Collectors.joining());
+            throw new ServiceException("客户[" + names + "]已提交审核,请勿重复提交");
+        }
+
+        QwCompany qwCompany = qwCompanyMapper.selectQwCompanyByCorpId(qwUser.getCorpId());
+        Company company = companyMapper.selectCompanyById(qwUser.getCompanyId());
+        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(qwUser.getCompanyUserId());
+
+        QwExternalContactTransferCompanyAudit audit = new QwExternalContactTransferCompanyAudit();
+        audit.setTransferType(param.getTransferType());
+        audit.setQwCompanyId(qwCompany.getId());
+        audit.setCorpId(qwCompany.getCorpId());
+        audit.setCorpName(qwCompany.getCorpName());
+        audit.setCompanyId(company.getCompanyId());
+        audit.setCompanyName(company.getCompanyName());
+        audit.setCompanyUserId(companyUser.getUserId());
+        audit.setCompanyUserName(companyUser.getUserName());
+        audit.setQwUserId(qwUser.getId());
+        audit.setQwUserExtId(qwUser.getQwUserId());
+        audit.setQwUserName(qwUser.getQwUserName());
+        audit.setContent(param.getContent());
+        audit.setCreateTime(LocalDateTime.now());
+        audit.setCreateBy(userName);
+        audit.setOperCompanyId(companyId);
+        baseMapper.insert(audit);
+
+        List<QwExternalContactTransferCompanyAuditUser> auditUserList = qwExternalContacts
+            .stream()
+            .map(c -> {
+
+                // 后面可优化为一起查询再取值
+                Company userCompany = companyMapper.selectCompanyById(c.getCompanyId());
+                CompanyUser userCompanyUser = companyUserMapper.selectCompanyUserById(c.getCompanyUserId());
+                QwUser userQwUser = qwUserMapper.selectQwUserById(c.getQwUserId());
+
+                QwExternalContactTransferCompanyAuditUser auditUser = new QwExternalContactTransferCompanyAuditUser();
+                auditUser.setAuditId(audit.getId());
+                auditUser.setExternalId(c.getId());
+                auditUser.setExternalUserId(c.getExternalUserId());
+                auditUser.setExternalUserName(c.getName());
+                auditUser.setCompanyId(userCompany.getCompanyId());
+                auditUser.setCompanyName(userCompany.getCompanyName());
+                auditUser.setCompanyUserId(userCompanyUser.getUserId());
+                auditUser.setCompanyUserName(userCompanyUser.getUserName());
+                auditUser.setQwUserId(userQwUser.getId());
+                auditUser.setQwUserExtId(userQwUser.getQwUserId());
+                auditUser.setQwUserName(userQwUser.getQwUserName());
+                auditUser.setCreateTime(LocalDateTime.now());
+
+                return auditUser;
+            }).collect(Collectors.toList());
+
+        auditUserService.saveBatch(auditUserList);
+    }
+
+    /**
+     * 查询审核记录列表
+     */
+    @Override
+    public List<QwExternalContactTransferCompanyAudit> selectQwExternalContactTransferCompanyAuditList(QwExternalContactTransferCompanyAudit param) {
+        return baseMapper.selectQwExternalContactTransferCompanyAuditList(param);
+    }
+
+    /**
+     * 记录审核
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void audit(CompanyTransferAuditDTO param, String userName) {
+        QwExternalContactTransferCompanyAudit auditInfo = baseMapper.selectById(param.getAuditId());
+        if (Objects.isNull(auditInfo)) {
+            throw new ServiceException("记录不存在");
+        }
+
+        if (auditInfo.getStatus() != 1) {
+            throw new ServiceException("请勿重复审核");
+        }
+
+        // 审核通过
+        if (param.getType() == 1) {
+            auditInfo.setStatus(2);
+            // 转接
+            transferCustomer(auditInfo);
+        }
+        // 拒绝
+        else {
+            auditInfo.setStatus(3);
+            auditInfo.setReason(param.getReason());
+        }
+        auditInfo.setAuditBy(userName);
+        auditInfo.setAuditTime(LocalDateTime.now());
+        baseMapper.updateById(auditInfo);
+    }
+
+    /**
+     * 转接用户
+     */
+    private void transferCustomer(QwExternalContactTransferCompanyAudit auditInfo) {
+        List<QwExternalContactTransferCompanyAuditUser> auditUserList = auditUserService.getListByAuditId(auditInfo.getId());
+        outer:
+        for (QwExternalContactTransferCompanyAuditUser auditUser : auditUserList) {
+            try {
+                // 已提交的不再处理
+                if (auditUser.getStatus() != 0) {
+                    continue;
+                }
+
+                // 在职
+                if (auditInfo.getTransferType() == 1) {
+                    QwTransferCustomerParam qwTransferCustomerParam = new QwTransferCustomerParam();
+                    String content = auditInfo.getContent();
+                    if(StringUtils.isBlank(content)){
+                        content = "您好,您的服务已升级,后续将由我的同事接替我的工作,继续为您服务。";
+                    }
+                    qwTransferCustomerParam.setTransfer_success_msg(content);
+                    qwTransferCustomerParam.setHandover_userid(auditUser.getQwUserExtId());
+                    qwTransferCustomerParam.setTakeover_userid(auditInfo.getQwUserExtId());
+                    qwTransferCustomerParam.setExternal_userid(Collections.singletonList(auditUser.getExternalUserId()));
+                    QwTransferCustomerResult qwTransferCustomerResult = qwApiService.transferCustomer(qwTransferCustomerParam, auditInfo.getCorpId());
+
+                    if (qwTransferCustomerResult.getErrcode() != 0) {
+                        auditUser.setRemark("接替失败: " + qwTransferCustomerResult.getErrmsg());
+                        auditUserService.updateById(auditUser);
+                        continue;
+                    }
+
+                    List<QwCustomer> customer = qwTransferCustomerResult.getCustomer();
+                    if (Objects.isNull(customer) || customer.isEmpty()) {
+                        auditUser.setRemark("接替失败: 未获取到数据");
+                        auditUserService.updateById(auditUser);
+                        continue;
+                    }
+
+                    for (QwCustomer qwCustomer : customer) {
+                        if (qwCustomer.getErrcode() != 0) {
+                            auditUser.setRemark("接替失败: " + qwCustomer.getErrcode());
+                            auditUserService.updateById(auditUser);
+                            continue outer;
+                        }
+
+                        QwExternalContact qwExternal = new QwExternalContact();
+                        qwExternal.setStatus(2);
+                        qwExternal.setTransferStatus(2);
+                        qwExternal.setId(auditUser.getExternalId());
+                        contactMapper.updateQwExternalContact(qwExternal);
+
+                        auditUser.setStatus(2);
+                        auditUser.setReplaceTime(LocalDateTime.now());
+                        auditUserService.updateById(auditUser);
+                    }
+                }
+                // 离职
+                else if (auditInfo.getTransferType() == 2) {
+                    QwTransferCustomerResignedParam qwTransferCustomerParam = new QwTransferCustomerResignedParam();
+                    qwTransferCustomerParam.setHandover_userid(auditUser.getQwUserExtId());
+                    qwTransferCustomerParam.setTakeover_userid(auditInfo.getQwUserExtId());
+                    qwTransferCustomerParam.setExternal_userid(Collections.singletonList(auditUser.getExternalUserId()));
+                    QwTransferCustomerResignedResult qwTransferCustomerResignedParam = qwApiService.resignedTransferCustomer(qwTransferCustomerParam, auditInfo.getCorpId());
+
+                    if (qwTransferCustomerResignedParam.getErrcode() != 0) {
+                        auditUser.setRemark("接替失败: " + qwTransferCustomerResignedParam.getErrmsg());
+                        auditUserService.updateById(auditUser);
+                        continue;
+                    }
+
+                    List<QwCustomer> customer = qwTransferCustomerResignedParam.getCustomer();
+                    if (Objects.isNull(customer) || customer.isEmpty()) {
+                        auditUser.setRemark("接替失败: 未获取到数据");
+                        auditUserService.updateById(auditUser);
+                        continue;
+                    }
+
+                    for (QwCustomer qwCustomer : customer) {
+                        if (qwCustomer.getErrcode() != 0) {
+                            auditUser.setRemark("接替失败: " + qwCustomer.getErrcode());
+                            auditUserService.updateById(auditUser);
+                            continue outer;
+                        }
+
+                        QwExternalContact qwExternal = new QwExternalContact();
+                        qwExternal.setStatus(2);
+                        qwExternal.setTransferStatus(2);
+                        qwExternal.setId(auditUser.getExternalId());
+                        contactMapper.updateQwExternalContact(qwExternal);
+
+                        auditUser.setStatus(2);
+                        auditUser.setReplaceTime(LocalDateTime.now());
+                        auditUserService.updateById(auditUser);
+                    }
+                }
+            } catch (Exception e) {
+                auditUser.setRemark("接替失败: " + e.getMessage());
+                auditUserService.updateById(auditUser);
+            }
+        }
+    }
+
+    /**
+     * 同步最新状态
+     */
+    @Override
+    public void syncTransfer(Long auditId) {
+        QwExternalContactTransferCompanyAudit auditInfo = baseMapper.selectById(auditId);
+        if (Objects.isNull(auditInfo) || auditInfo.getStatus() != 2) {
+            return;
+        }
+
+        List<QwExternalContactTransferCompanyAuditUser> auditUserList = auditUserService.getListByAuditId(auditId);
+        for (QwExternalContactTransferCompanyAuditUser auditUser : auditUserList) {
+            // 仅处理等待接替状态
+            if (auditUser.getStatus() != 2) {
+                continue;
+            }
+
+            QwGetTransferParam getTransferParam = new QwGetTransferParam();
+            getTransferParam.setTakeover_userid(auditInfo.getQwUserExtId());
+            getTransferParam.setHandover_userid(auditUser.getQwUserExtId());
+            QwGetTransferResult transfer = qwApiService.getTransfer(getTransferParam, auditInfo.getCorpId());
+            for (QwGetTransferResult.Customer customer: transfer.getCustomer()) {
+                if (customer.getExternal_userid().equals(auditUser.getExternalUserId())){
+                    if (customer.getStatus() != 2){
+                        auditUser.setStatus(customer.getStatus());
+                        auditUserService.updateById(auditUser);
+
+                        QwExternalContact qwExternalContact = new QwExternalContact();
+                        qwExternalContact.setId(auditUser.getExternalId());
+                        qwExternalContact.setTransferStatus(customer.getStatus());
+                        if (customer.getStatus()==1){
+                            qwExternalContact.setUserId(auditInfo.getQwUserExtId());
+                            qwExternalContact.setQwUserId(auditInfo.getQwUserId());
+                            qwExternalContact.setCompanyUserId(auditInfo.getCompanyUserId());
+                        }
+                        contactMapper.updateQwExternalContact(qwExternalContact);
+                    }
+                }
+            }
+        }
+    }
+}

+ 43 - 0
fs-service/src/main/java/com/fs/qw/service/impl/QwExternalContactTransferCompanyAuditUserServiceImpl.java

@@ -0,0 +1,43 @@
+package com.fs.qw.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.common.exception.ServiceException;
+import com.fs.qw.domain.QwExternalContactTransferCompanyAuditUser;
+import com.fs.qw.dto.CompanyTransferAuditDTO;
+import com.fs.qw.mapper.QwExternalContactTransferCompanyAuditUserMapper;
+import com.fs.qw.service.IQwExternalContactTransferCompanyAuditUserService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+
+@Service
+public class QwExternalContactTransferCompanyAuditUserServiceImpl extends ServiceImpl<QwExternalContactTransferCompanyAuditUserMapper, QwExternalContactTransferCompanyAuditUser>
+        implements IQwExternalContactTransferCompanyAuditUserService {
+
+    /**
+     * 根据ID集合查询已提交的记录
+     */
+    @Override
+    public List<QwExternalContactTransferCompanyAuditUser> getExistAuditByExtIds(List<Long> ids) {
+        if (ids.isEmpty()) {
+            return new ArrayList<>();
+        }
+        return baseMapper.getExistAuditByExtIds(ids);
+    }
+
+    /**
+     * 根据审核ID查询记录
+     */
+    @Override
+    public List<QwExternalContactTransferCompanyAuditUser> getListByAuditId(Long auditId) {
+        Wrapper<QwExternalContactTransferCompanyAuditUser> queryWrapper = Wrappers.<QwExternalContactTransferCompanyAuditUser>lambdaQuery()
+                .eq(QwExternalContactTransferCompanyAuditUser::getAuditId, auditId);
+        return baseMapper.selectList(queryWrapper);
+    }
+}

+ 11 - 3
fs-service/src/main/java/com/fs/qw/service/impl/QwUserServiceImpl.java

@@ -51,7 +51,6 @@ import com.fs.wxwork.dto.*;
 import com.fs.wxwork.service.WxWorkService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.tuple.Pair;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -862,8 +861,9 @@ public class QwUserServiceImpl implements IQwUserService
     {
         int i = qwUserMapper.updateQwUser(qwUser);
         if (i>0){
-            redisCache.setCacheObject("qwUserRdById:"+qwUser.getId() ,JSON.toJSONString(qwUser),1, TimeUnit.HOURS);
-            redisCache.setCacheObject("qwUserRd:"+qwUser.getCorpId()+":"+qwUser.getQwUserId() ,JSON.toJSONString(qwUser),1, TimeUnit.HOURS);
+            QwUser qwUserById = qwUserMapper.selectQwUserById(qwUser.getId());
+            redisCache.setCacheObject("qwUserRdById:"+qwUser.getId() ,JSON.toJSONString(qwUserById),1, TimeUnit.HOURS);
+            redisCache.setCacheObject("qwUserRd:"+qwUser.getCorpId()+":"+qwUser.getQwUserId() ,JSON.toJSONString(qwUserById),1, TimeUnit.HOURS);
         }
         return i;
     }
@@ -1538,6 +1538,14 @@ public class QwUserServiceImpl implements IQwUserService
         qwUserMapper.updateById(qwUser);
     }
 
+    /**
+     * 根据销售公司和企微ID查询企微用户
+     */
+    @Override
+    public List<QwUserVO> selectQwUserListByCompanyIdAndCorpIdAndNickName(Long companyId, String corpId, String nickName) {
+        return qwUserMapper.selectQwUserListVOByCompanyIdAndCorpIdAndNickName(companyId, corpId, nickName);
+    }
+
 
     /**
      * 构建查询条件

+ 2 - 0
fs-service/src/main/java/com/fs/qw/vo/QwExternalContactVO.java

@@ -95,7 +95,9 @@ public class QwExternalContactVO {
 
     private Integer transferStatus;
     private Integer status;
+
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "添加时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
     private Date createTime;
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date lossTime;

+ 8 - 6
fs-service/src/main/java/com/fs/sop/service/impl/QwSopTempServiceImpl.java

@@ -260,12 +260,14 @@ public class QwSopTempServiceImpl implements IQwSopTempService
                                                 Long companyUserId = qwUserVO.getCompanyUserId();
                                                 QwSopTempVoice qwSopTempVoice = qwSopTempVoiceService.selectQwSopTempVoiceByCompanyUserIdAndVoiceTxt(companyUserId,text);
                                                 if(qwSopTempVoice == null){
-                                                    QwSopTempVoice sopTempVoice = new QwSopTempVoice();
-                                                    sopTempVoice.setCompanyUserId(companyUserId);
-                                                    sopTempVoice.setVoiceTxt(text);
-                                                    sopTempVoice.setTempId(tempId);
-                                                    sopTempVoice.setRecordType(0);
-                                                    qwSopTempVoiceService.insertQwSopTempVoice(sopTempVoice);
+                                                    if(companyUserId != null && text != null){
+                                                        QwSopTempVoice sopTempVoice = new QwSopTempVoice();
+                                                        sopTempVoice.setCompanyUserId(companyUserId);
+                                                        sopTempVoice.setVoiceTxt(text);
+                                                        sopTempVoice.setTempId(tempId);
+                                                        sopTempVoice.setRecordType(0);
+                                                        qwSopTempVoiceService.insertQwSopTempVoice(sopTempVoice);
+                                                    }
                                                 }
                                             }
                                         }

+ 7 - 5
fs-service/src/main/java/com/fs/sop/service/impl/SopUserLogsInfoServiceImpl.java

@@ -971,11 +971,13 @@ public class SopUserLogsInfoServiceImpl implements ISopUserLogsInfoService {
             st.setVoiceUrl(qwSopTempVoice.getVoiceUrl());
             st.setVoiceDuration(String.valueOf(qwSopTempVoice.getDuration()));
         } else if (qwSopTempVoice == null) {
-            qwSopTempVoice = new QwSopTempVoice();
-            qwSopTempVoice.setCompanyUserId(Long.valueOf(companyUserId));
-            qwSopTempVoice.setVoiceTxt(st.getValue());
-            qwSopTempVoice.setRecordType(0);
-            sopTempVoiceService.insertQwSopTempVoice(qwSopTempVoice);
+            if(st.getValue() != null){
+                qwSopTempVoice = new QwSopTempVoice();
+                qwSopTempVoice.setCompanyUserId(Long.valueOf(companyUserId));
+                qwSopTempVoice.setVoiceTxt(st.getValue());
+                qwSopTempVoice.setRecordType(0);
+                sopTempVoiceService.insertQwSopTempVoice(qwSopTempVoice);
+            }
         }
     }
 

+ 48 - 0
fs-service/src/main/resources/db/20250928-企微客户公司转接.sql

@@ -0,0 +1,48 @@
+-- 企微客户转移审核记录表
+drop table if exists `qw_external_contact_transfer_company_audit`;
+create table `qw_external_contact_transfer_company_audit` (
+    `id`                    bigint not null auto_increment       comment '主键ID',
+    `qw_company_id`         bigint not null                      comment '企微主体ID',
+    `corp_id`               varchar(255) not null                comment '企微CorpID',
+    `corp_name`             varchar(255) not null                comment '企微主体名称',
+    `company_id`            bigint not null                      comment '接替公司ID',
+    `company_name`          varchar(255) not null                comment '接替公司名称',
+    `company_user_id`       bigint not null                      comment '接替公司销售ID',
+    `company_user_name`     varchar(255) not null                comment '接替公司销售名称',
+    `qw_user_id`            bigint not null                      comment '接替企微用户ID',
+    `qw_user_ext_id`        varchar(255) not null                comment '接替企微用户ID(企微)',
+    `qw_user_name`          varchar(255) not null                comment '接替企微用户名称',
+    `content`               varchar(255)                         comment '消息内容',
+    `transfer_type`         tinyint(1) not null                  comment '转接类型 1在职转接 2离职转接',
+    `status`                tinyint(1) default 1                 comment '状态 1待审核 2审核通过 3审核被拒',
+    `reason`                varchar(500)                         comment '被拒原因',
+    `remark`                varchar(500)                         comment '备注',
+    `audit_time`            datetime                             comment '审核时间',
+    `audit_by`              varchar(255)                         comment '审核人',
+    `create_time`           datetime                             comment '创建时间',
+    `create_by`             varchar(255)                         comment '提审人',
+    `oper_company_id`       bigint not null                      comment '提审公司',
+    primary key (`id`) using btree
+) engine = Innodb comment '企微客户转移审核记录表';
+
+-- 企微客户转移审核用户表
+drop table if exists `qw_external_contact_transfer_company_audit_user`;
+create table `qw_external_contact_transfer_company_audit_user` (
+    `id`                    bigint not null auto_increment       comment '主键ID',
+    `audit_id`              bigint  not null                     comment '审核记录ID',
+    `external_id`           bigint  not null                     comment '外部联系人ID',
+    `external_user_id`      varchar(255) not null                comment '客户ID(企微)',
+    `external_user_name`    varchar(255) not null                comment '客户名称',
+    `company_id`            bigint not null                      comment '原公司ID',
+    `company_name`          varchar(255) not null                comment '原公司名称',
+    `company_user_id`       bigint not null                      comment '原公司销售ID',
+    `company_user_name`     varchar(255) not null                comment '原公司销售名称',
+    `qw_user_id`            bigint not null                      comment '原企微用户ID',
+    `qw_user_ext_id`        varchar(255) not null                comment '原企微用户ID(企微)',
+    `qw_user_name`          varchar(255) not null                comment '原企微用户名称',
+    `status`                tinyint(1) default 0                 comment '0-待处理 1-接替完毕 2-等待接替 3-客户拒绝 4-接替成员客户达到上限',
+    `remark`                varchar(500)                         comment '备注',
+    `create_time`           datetime                             comment '创建时间',
+    `replace_time`          datetime                             comment '接替时间',
+    primary key (`id`) using btree
+) engine = Innodb comment '企微客户转移审核用户表';

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

@@ -255,4 +255,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             and dept_id = #{deptId}
         </if>
     </select>
+
+    <select id="getCompanyListByCorpId" resultType="com.fs.his.vo.OptionsVO">
+        select c.company_id dictValue, c.company_name dictLabel
+        from company c
+        inner join qw_company qc on find_in_set(c.company_id, qc.company_ids)
+        where c.is_del= 0 and qc.corp_id = #{corpId}
+    </select>
 </mapper>

+ 4 - 0
fs-service/src/main/resources/mapper/his/FsIntegralOrderMapper.xml

@@ -145,4 +145,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{orderId}
         </foreach>
     </delete>
+    <update id="cancelOrder" parameterType="FsIntegralOrder">
+        update fs_integral_order set status = -1
+        where order_id = #{orderId}
+    </update>
 </mapper>

+ 76 - 34
fs-service/src/main/resources/mapper/his/FsStoreOrderMapper.xml

@@ -522,39 +522,52 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <if test="(maps.companyUserNickName != null and maps.companyUserNickName !='') or (maps.params.dataScope!=null) ">
             LEFT JOIN  company_user cu on cu.user_id=so.company_user_id
         </if>
+        <if test="maps.coursePlaySourceConfigId != null">
+            LEFT JOIN (
+            SELECT
+            sp.*,
+            ROW_NUMBER() OVER (PARTITION BY sp.business_code ORDER BY sp.create_time DESC) as rn
+            FROM fs_store_payment sp
+            WHERE sp.business_code IS NOT NULL
+            ) sp_latest ON sp_latest.business_code = so.order_code AND sp_latest.rn = 1
+            LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp_latest.app_id
+        </if>
 
         where so.is_del=0
-        <if test="maps.packageSecondName != null and maps.packageSecondName != '' ">
+        <if test="maps.packageSecondName != null and maps.packageSecondName != ''">
             and so.package_second_name like concat('%', #{maps.packageSecondName}, '%')
         </if>
-        <if test="maps.storeId != null ">
+        <if test="maps.storeId != null">
             and so.store_id = #{maps.storeId}
         </if>
+        <if test="maps.coursePlaySourceConfigId != null">
+            and csc.id = #{maps.coursePlaySourceConfigId}
+        </if>
         <if test="maps.orderCodes != null  and maps.orderCodes.size > 0">
             and so.order_code in
             <foreach collection="maps.orderCodes" item="orderCode" open="(" close=")" separator=",">
                 #{orderCode}
             </foreach>
         </if>
-        <if test="maps.orderCode != null and maps.orderCode != ''">
+        <if test="maps.orderCode != null  and maps.orderCode != ''">
             and so.order_code = #{maps.orderCode}
         </if>
-        <if test="maps.prescribeCode != null and maps.prescribeCode != ''">
+        <if test="maps.prescribeCode != null  and maps.prescribeCode != ''">
             and p.prescribe_code = #{maps.prescribeCode}
         </if>
-        <if test="maps.userName != null and maps.userName != ''">
+        <if test="maps.userName != null  and maps.userName != ''">
             and so.user_name like concat('%', #{maps.userName}, '%')
         </if>
-        <if test="maps.userPhone != null and maps.userPhone != ''">
+        <if test="maps.userPhone != null  and maps.userPhone != ''">
             and so.user_phone = #{maps.userPhone}
         </if>
         <if test="maps.userId != null ">
             and so.user_id = #{maps.userId}
         </if>
-        <if test="maps.isFirst != null ">
+        <if test="maps.isFirst != null">
             and so.is_first = #{maps.isFirst}
         </if>
-        <if test="maps.status != null  and maps.status != 6">
+        <if test="maps.status != null and maps.status != 6">
             and so.status = #{maps.status}
         </if>
         <if test="maps.status == 6">
@@ -562,9 +575,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             and (
             so.store_id in (select store_id from fs_store where delivery_type=2 or delivery_type=1)
             )
-            and  (so.extend_order_id is null or so.extend_order_id like '')
+            and  (so.extend_order_id is null or  so.extend_order_id like '')
         </if>
-        <if test="maps.deliverySn != null and maps.deliverySn != ''">
+        <if test="maps.source != null">
+            and so.source = #{maps.source}
+        </if>
+        <if test="maps.deliverySn != null  and maps.deliverySn != ''">
             and so.delivery_sn = #{maps.deliverySn}
         </if>
         <if test="maps.prescribeId != null">
@@ -615,7 +631,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <if test="maps.tuieTime != null">
             and DATE(so.tui_money_time) &lt;= DATE(#{maps.tuieTime})
         </if>
-        <if test="maps.companyUserNickName != null and maps.companyUserNickName !='' ">
+        <if test="maps.companyUserNickName != null and  maps.companyUserNickName !=''">
             and cu.nick_name like concat( #{maps.companyUserNickName}, '%')
         </if>
         <if test="maps.companyIds != null and  maps.companyIds.size >0">
@@ -624,69 +640,69 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 #{companyId}
             </foreach>
         </if>
-        <if test='maps.companyId != null and maps.companyId != "-1" '>
-            and so.company_id = #{maps.companyId}
+        <if test="maps.companyId != null and  maps.companyId != -1">
+            and so.company_id =#{maps.companyId}
         </if>
-        <if test='maps.companyId == "-1"'>
+        <if test="maps.companyId == -1">
             and so.company_id is null
         </if>
-        <if test='maps.deliveryStatus != null '>
+        <if test="maps.deliveryStatus != null">
             and so.delivery_status =#{maps.deliveryStatus}
         </if>
-        <if test='maps.customerId != null '>
+        <if test="maps.customerId != null">
             and so.customer_id =#{maps.customerId}
         </if>
-        <if test='maps.deliveryPayStatus != null '>
+        <if test="maps.deliveryPayStatus != null">
             and so.delivery_pay_status =#{maps.deliveryPayStatus}
         </if>
-        <if test='maps.tuiMoneyStatus != null '>
+        <if test="maps.tuiMoneyStatus != null">
             and so.tui_money_status =#{maps.tuiMoneyStatus}
         </if>
-        <if test='maps.deptId != null '>
+        <if test="maps.deptId != null">
             AND (so.dept_id = #{maps.deptId} OR so.dept_id IN ( SELECT t.dept_id FROM company_dept t WHERE find_in_set(#{maps.deptId}, ancestors) ))
         </if>
-        <if test='maps.packageName != null and maps.packageName != "" '>
+        <if test="maps.packageName != null and maps.packageName != ''">
             and so.package_name like concat('%', #{maps.packageName}, '%')
         </if>
-        <if test='maps.payType != null '>
+        <if test="maps.payType != null">
             and so.pay_type IN
-            <foreach collection="maps.payType.split(',') "  item='item' index='index'  open='(' separator=',' close=')'>
+            <foreach collection="maps.payType.split(',')" item="item" index="index" open="(" close=")" separator=",">
                 #{item}
             </foreach>
         </if>
-        <if test='maps.scheduleId != null and  maps.scheduleId != "-1" '>
+        <if test="maps.scheduleId != null  and  maps.scheduleId != -1">
             and so.schedule_id IN
-            <foreach collection="maps.scheduleId.split(',') "  item='item' index='index'  open='(' separator=',' close=')'>
+            <foreach collection="maps.scheduleId.split(',')" item="item" index="index" open="(" close=")" separator=",">
                 #{item}
             </foreach>
         </if>
-        <if test='maps.scheduleId == "-1" '>
+        <if test="maps.scheduleId == -1">
             and so.schedule_id is null
         </if>
-        <if test='maps.orderBuyType != null and  maps.orderBuyType != "-1" '>
+        <if test="maps.orderBuyType != null and maps.orderBuyType != -1">
             and so.order_buy_type IN
-            <foreach collection="maps.orderBuyType.split(',') "  item='item' index='index'  open='(' separator=',' close=')'>
+            <foreach collection="maps.orderBuyType.split(',')" item="item" index="index" open="(" close=")" separator=",">
                 #{item}
             </foreach>
         </if>
-        <if test='maps.orderBuyType == "-1" '>
+        <if test="maps.orderBuyType == -1">
             and so.order_buy_type is null
         </if>
-        <if test='maps.orderChannel == "-1" '>
+        <if test="maps.orderChannel == -1">
             and so.order_channel is null
         </if>
-        <if test='maps.orderChannel != null and  maps.orderChannel != "-1" '>
+        <if test="maps.orderChannel != null and maps.orderChannel != -1">
             and so.order_channel IN
-            <foreach collection="maps.orderChannel.split(',') "  item='item' index='index'  open='(' separator=',' close=')'>
+            <foreach collection="maps.orderChannel.split(',')" item="item" index="index" open="(" close=")" separator=",">
                 #{item}
             </foreach>
         </if>
-        <if test='maps.qwSubject == "-1"'>
+        <if test="maps.qwSubject == -1">
             and so.qw_subject is null
         </if>
-        <if test='maps.qwSubject != null and  maps.qwSubject != "-1" '>
+        <if test="maps.qwSubject != null and maps.qwSubject != -1">
             and so.qw_subject IN
-            <foreach collection="maps.qwSubject.split(',') "  item='item' index='index'  open='(' separator=',' close=')'>
+            <foreach collection="maps.qwSubject.split(',')" item="item" index="index" open="(" close=")" separator=",">
                 #{item}
             </foreach>
         </if>
@@ -1639,6 +1655,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LEFT JOIN fs_doctor d ON so.doctor_id= d.doctor_id
         LEFT JOIN company_user cu on cu.user_id=so.company_user_id
         LEFT JOIN fs_store_order_df df on df.order_id=so.order_id
+        <if test="maps.coursePlaySourceConfigId != null">
+            LEFT JOIN (
+            SELECT
+            sp.*,
+            ROW_NUMBER() OVER (PARTITION BY sp.business_code ORDER BY sp.create_time DESC) as rn
+            FROM fs_store_payment sp
+            WHERE sp.business_code IS NOT NULL
+            ) sp_latest ON sp_latest.business_code = so.order_code AND sp_latest.rn = 1
+            LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp_latest.app_id
+        </if>
         <where>
             <if test="maps.packageSecondName != null and maps.packageSecondName != ''">
                 and so.package_second_name like concat('%', #{maps.packageSecondName}, '%')
@@ -1646,6 +1672,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.storeId != null">
                 and so.store_id = #{maps.storeId}
             </if>
+            <if test="maps.coursePlaySourceConfigId != null">
+                and csc.id = #{maps.coursePlaySourceConfigId}
+            </if>
             <if test="maps.orderCodes != null  and maps.orderCodes.size > 0">
                 and so.order_code in
                 <foreach collection="maps.orderCodes" item="orderCode" open="(" close=")" separator=",">
@@ -1837,6 +1866,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         LEFT JOIN fs_doctor d ON so.doctor_id= d.doctor_id
         LEFT JOIN company_user cu on cu.user_id=so.company_user_id
         LEFT JOIN fs_store_order_df df on df.order_id=so.order_id
+        <if test="maps.coursePlaySourceConfigId != null">
+            LEFT JOIN (
+            SELECT
+            sp.*,
+            ROW_NUMBER() OVER (PARTITION BY sp.business_code ORDER BY sp.create_time DESC) as rn
+            FROM fs_store_payment sp
+            WHERE sp.business_code IS NOT NULL
+            ) sp_latest ON sp_latest.business_code = so.order_code AND sp_latest.rn = 1
+            LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp_latest.app_id
+        </if>
         <where>
             <if test="maps.packageSecondName != null and maps.packageSecondName != ''">
                 and so.package_second_name like concat('%', #{maps.packageSecondName}, '%')
@@ -1844,6 +1883,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="maps.storeId != null">
                 and so.store_id = #{maps.storeId}
             </if>
+            <if test="maps.coursePlaySourceConfigId != null">
+                and csc.id = #{maps.coursePlaySourceConfigId}
+            </if>
             <if test="maps.orderCodes != null  and maps.orderCodes.size > 0">
                 and so.order_code in
                 <foreach collection="maps.orderCodes" item="orderCode" open="(" close=")" separator=",">

+ 29 - 0
fs-service/src/main/resources/mapper/qw/QwExternalContactTransferCompanyAuditMapper.xml

@@ -0,0 +1,29 @@
+<?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.QwExternalContactTransferCompanyAuditMapper">
+
+    <select id="selectQwExternalContactTransferCompanyAuditList" resultType="com.fs.qw.domain.QwExternalContactTransferCompanyAudit">
+        select *
+        from qw_external_contact_transfer_company_audit
+        <where>
+            <if test="corpName != null and corpName != ''">
+                and corp_name like concat('%', #{corpName}, '%')
+            </if>
+            <if test="companyName != null and companyName != ''">
+                and company_name like concat('%', #{companyName}, '%')
+            </if>
+            <if test="companyUserName != null and companyUserName != ''">
+                and company_user_name like concat('%', #{companyUserName}, '%')
+            </if>
+            <if test="status != null">
+                and `status` = #{status}
+            </if>
+            <if test="operCompanyId != null">
+                and oper_company_id = #{operCompanyId}
+            </if>
+        </where>
+        order by create_time desc,id desc
+    </select>
+</mapper>

+ 28 - 0
fs-service/src/main/resources/mapper/qw/QwExternalContactTransferCompanyAuditUserMapper.xml

@@ -0,0 +1,28 @@
+<?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.QwExternalContactTransferCompanyAuditUserMapper">
+
+    <select id="getExistAuditByExtIds" resultType="com.fs.qw.domain.QwExternalContactTransferCompanyAuditUser">
+        select
+            au.*
+        from qw_external_contact_transfer_company_audit_user au
+        inner join qw_external_contact_transfer_company_audit ca on au.audit_id = ca.id and ca.status = 1
+        where au.external_id in
+        <foreach collection="ids" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </select>
+
+    <select id="selectListByExtIdAndTakeoverUserIdAndCorpId" resultType="com.fs.qw.domain.QwExternalContactTransferCompanyAuditUser">
+        select
+            au.*
+        from qw_external_contact_transfer_company_audit_user au
+        inner join qw_external_contact_transfer_company_audit ca on au.audit_id = ca.id and ca.status = 2
+        where au.status = 2
+          and au.external_user_id = #{externalUserID}
+          and ca.corp_id = #{corpId}
+          and ca.qw_user_ext_id = #{takeoverUserId}
+    </select>
+</mapper>

+ 17 - 0
fs-service/src/main/resources/mapper/qw/QwUserMapper.xml

@@ -269,4 +269,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </foreach>
     </select>
 
+    <select id="selectQwUserListVOByCompanyIdAndCorpIdAndNickName" resultType="com.fs.qw.vo.QwUserVO">
+        select
+            qu.*,
+            cu.nick_name,
+            cu.user_name,
+            qd.dept_name as departmentName,
+            c.company_name
+        from qw_user qu
+        left join company_user cu on cu.user_id = qu.company_user_id
+        right join qw_dept qd on qu.department = qd.dept_id and qd.corp_id = qu.corp_id
+        left join company c on qu.company_id = c.company_id
+        where qu.company_id = #{companyId} and qu.corp_id = #{corpId}
+        <if test="nickName != null and nickName != ''">
+            and qu.qw_user_name like concat('%', #{nickName}, '%')
+        </if>
+    </select>
+
 </mapper>

+ 5 - 5
fs-service/src/main/resources/mapper/sop/QwSopTempContentMapper.xml

@@ -7,21 +7,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     <resultMap type="QwSopTempContent" id="QwSopTempContentResult">
         <result property="id"    column="id"    />
         <result property="rulesId"    column="rules_id"    />
-        <result property="sendType"    column="send_type"    />
+        <result property="contentType"    column="content_type"    />
         <result property="content"    column="content"    />
         <result property="isBindUrl"    column="is_bind_url"    />
         <result property="expiresDays"    column="expires_days"    />
     </resultMap>
 
     <sql id="selectQwSopTempContentVo">
-        select id, rules_id, send_type, content, is_bind_url, expires_days from qw_sop_temp_content
+        select id, rules_id, content_type, content, is_bind_url, expires_days from qw_sop_temp_content
     </sql>
 
     <select id="selectQwSopTempContentList" parameterType="QwSopTempContent" resultMap="QwSopTempContentResult">
         <include refid="selectQwSopTempContentVo"/>
         <where>
             <if test="rulesId != null  and rulesId != ''"> and rules_id = #{rulesId}</if>
-            <if test="sendType != null "> and send_type = #{sendType}</if>
+            <if test="contentType != null "> and content_type = #{contentType}</if>
             <if test="content != null  and content != ''"> and content = #{content}</if>
             <if test="isBindUrl != null "> and is_bind_url = #{isBindUrl}</if>
             <if test="expiresDays != null  and expiresDays != ''"> and expires_days = #{expiresDays}</if>
@@ -56,7 +56,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <trim prefix="(" suffix=")" suffixOverrides=",">
             <if test="id != null">id,</if>
             <if test="rulesId != null">rules_id,</if>
-            <if test="sendType != null">send_type,</if>
+            <if test="contentType != null">content_type,</if>
             <if test="content != null">content,</if>
             <if test="isBindUrl != null">is_bind_url,</if>
             <if test="expiresDays != null">expires_days,</if>
@@ -64,7 +64,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="id != null">#{id},</if>
             <if test="rulesId != null">#{rulesId},</if>
-            <if test="sendType != null">#{sendType},</if>
+            <if test="contentType != null">#{contentType},</if>
             <if test="content != null">#{content},</if>
             <if test="isBindUrl != null">#{isBindUrl},</if>
             <if test="expiresDays != null">#{expiresDays},</if>