Sfoglia il codice sorgente

Merge remote-tracking branch 'origin/dev_v1.0.0' into dev_v1.0.0

wangliang 1 anno fa
parent
commit
b97ee6840f

+ 12 - 0
sop-business/src/main/java/com/qmth/sop/business/bean/params/UserArchivesAllocationParam.java

@@ -30,6 +30,10 @@ public class UserArchivesAllocationParam {
     @NotBlank(message = "缺少派单信息")
     private String crmNo;
 
+    @JsonSerialize(using = ToStringSerializer.class)
+    @ApiModelProperty("区域协调人id")
+    private Long regionUserId;
+
     public List<AllocationParam> getAllocationParams() {
         return allocationParams;
     }
@@ -53,4 +57,12 @@ public class UserArchivesAllocationParam {
     public void setCrmNo(String crmNo) {
         this.crmNo = crmNo;
     }
+
+    public Long getRegionUserId() {
+        return regionUserId;
+    }
+
+    public void setRegionUserId(Long regionUserId) {
+        this.regionUserId = regionUserId;
+    }
 }

+ 116 - 0
sop-business/src/main/java/com/qmth/sop/business/bean/result/UserArchivesAllocationResult.java

@@ -47,6 +47,10 @@ public class UserArchivesAllocationResult {
     @ApiModelProperty("县")
     private String area;
 
+    @ApiModelProperty("档位等级id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long levelId;
+
     @ApiModelProperty("档位等级")
     private String level;
 
@@ -62,6 +66,30 @@ public class UserArchivesAllocationResult {
     @ApiModelProperty("未分配")
     private Integer unDistributed;
 
+    @ApiModelProperty("区域协调人配额")
+    private Integer coordinatorQuota;
+    @ApiModelProperty("实施工程师配额")
+    private Integer effectQuota;
+    @ApiModelProperty("助理工程师配额")
+    private Integer assistantQuota;
+
+    @ApiModelProperty("区域协调人已分配")
+    private Integer coordinatorDistributed;
+    @ApiModelProperty("实施工程师已分配")
+    private Integer effectDistributed;
+    @ApiModelProperty("助理工程师已分配")
+    private Integer assistantDistributed;
+
+    @ApiModelProperty("区域协调人差额(取反)")
+    private Integer coordinatorUnDistributed;
+    @ApiModelProperty("实施工程师差额(取反)")
+    private Integer effectUnDistributed;
+    @ApiModelProperty("助理工程师差额(取反)")
+    private Integer assistantUnDistributed;
+
+    @ApiModelProperty("是否发布")
+    private Boolean publish;
+
     // --编辑页面用的附加信息
     @ApiModelProperty("用户分配的数据")
     private List<AllocationDto> allocationDtoList;
@@ -146,6 +174,14 @@ public class UserArchivesAllocationResult {
         this.area = area;
     }
 
+    public Long getLevelId() {
+        return levelId;
+    }
+
+    public void setLevelId(Long levelId) {
+        this.levelId = levelId;
+    }
+
     public String getLevel() {
         return level;
     }
@@ -186,6 +222,78 @@ public class UserArchivesAllocationResult {
         this.unDistributed = unDistributed;
     }
 
+    public Integer getCoordinatorQuota() {
+        return coordinatorQuota;
+    }
+
+    public void setCoordinatorQuota(Integer coordinatorQuota) {
+        this.coordinatorQuota = coordinatorQuota;
+    }
+
+    public Integer getEffectQuota() {
+        return effectQuota;
+    }
+
+    public void setEffectQuota(Integer effectQuota) {
+        this.effectQuota = effectQuota;
+    }
+
+    public Integer getAssistantQuota() {
+        return assistantQuota;
+    }
+
+    public void setAssistantQuota(Integer assistantQuota) {
+        this.assistantQuota = assistantQuota;
+    }
+
+    public Integer getCoordinatorDistributed() {
+        return coordinatorDistributed;
+    }
+
+    public void setCoordinatorDistributed(Integer coordinatorDistributed) {
+        this.coordinatorDistributed = coordinatorDistributed;
+    }
+
+    public Integer getEffectDistributed() {
+        return effectDistributed;
+    }
+
+    public void setEffectDistributed(Integer effectDistributed) {
+        this.effectDistributed = effectDistributed;
+    }
+
+    public Integer getAssistantDistributed() {
+        return assistantDistributed;
+    }
+
+    public void setAssistantDistributed(Integer assistantDistributed) {
+        this.assistantDistributed = assistantDistributed;
+    }
+
+    public Integer getCoordinatorUnDistributed() {
+        return coordinatorUnDistributed;
+    }
+
+    public void setCoordinatorUnDistributed(Integer coordinatorUnDistributed) {
+        this.coordinatorUnDistributed = coordinatorUnDistributed;
+    }
+
+    public Integer getEffectUnDistributed() {
+        return effectUnDistributed;
+    }
+
+    public void setEffectUnDistributed(Integer effectUnDistributed) {
+        this.effectUnDistributed = effectUnDistributed;
+    }
+
+    public Integer getAssistantUnDistributed() {
+        return assistantUnDistributed;
+    }
+
+    public void setAssistantUnDistributed(Integer assistantUnDistributed) {
+        this.assistantUnDistributed = assistantUnDistributed;
+    }
+
     public List<AllocationDto> getAllocationDtoList() {
         return allocationDtoList;
     }
@@ -193,4 +301,12 @@ public class UserArchivesAllocationResult {
     public void setAllocationDtoList(List<AllocationDto> allocationDtoList) {
         this.allocationDtoList = allocationDtoList;
     }
+
+    public Boolean getPublish() {
+        return publish;
+    }
+
+    public void setPublish(Boolean publish) {
+        this.publish = publish;
+    }
 }

+ 30 - 30
sop-business/src/main/java/com/qmth/sop/business/bean/result/UserArchivesAllocationSubTotalResult.java

@@ -14,19 +14,19 @@ public class UserArchivesAllocationSubTotalResult {
     private Integer totalCrmCount;
 
     @ApiModelProperty("已匹配实施工程师数")
-    private Integer effectEngineerCount;
+    private Integer effectDistributed;
     @ApiModelProperty("实施工程师配额")
-    private Integer effectEngineerQuota;
+    private Integer effectQuota;
 
     @ApiModelProperty("已匹配助理工程师数")
-    private Integer assistantEngineerCount;
+    private Integer assistantDistributed;
     @ApiModelProperty("助理工程师配额")
-    private Integer assistantEngineerQuota;
+    private Integer assistantQuota;
 
     @ApiModelProperty("已匹配区域协调人数")
-    private Integer regionCoordinatorCount;
+    private Integer coordinatorDistributed;
     @ApiModelProperty("区域协调人配额")
-    private Integer regionCoordinatorQuota;
+    private Integer coordinatorQuota;
 
     public Integer getPublishedCrmCount() {
         return publishedCrmCount;
@@ -44,51 +44,51 @@ public class UserArchivesAllocationSubTotalResult {
         this.totalCrmCount = totalCrmCount;
     }
 
-    public Integer getEffectEngineerCount() {
-        return effectEngineerCount;
+    public Integer getEffectDistributed() {
+        return effectDistributed;
     }
 
-    public void setEffectEngineerCount(Integer effectEngineerCount) {
-        this.effectEngineerCount = effectEngineerCount;
+    public void setEffectDistributed(Integer effectDistributed) {
+        this.effectDistributed = effectDistributed;
     }
 
-    public Integer getEffectEngineerQuota() {
-        return effectEngineerQuota;
+    public Integer getEffectQuota() {
+        return effectQuota;
     }
 
-    public void setEffectEngineerQuota(Integer effectEngineerQuota) {
-        this.effectEngineerQuota = effectEngineerQuota;
+    public void setEffectQuota(Integer effectQuota) {
+        this.effectQuota = effectQuota;
     }
 
-    public Integer getAssistantEngineerCount() {
-        return assistantEngineerCount;
+    public Integer getAssistantDistributed() {
+        return assistantDistributed;
     }
 
-    public void setAssistantEngineerCount(Integer assistantEngineerCount) {
-        this.assistantEngineerCount = assistantEngineerCount;
+    public void setAssistantDistributed(Integer assistantDistributed) {
+        this.assistantDistributed = assistantDistributed;
     }
 
-    public Integer getAssistantEngineerQuota() {
-        return assistantEngineerQuota;
+    public Integer getAssistantQuota() {
+        return assistantQuota;
     }
 
-    public void setAssistantEngineerQuota(Integer assistantEngineerQuota) {
-        this.assistantEngineerQuota = assistantEngineerQuota;
+    public void setAssistantQuota(Integer assistantQuota) {
+        this.assistantQuota = assistantQuota;
     }
 
-    public Integer getRegionCoordinatorCount() {
-        return regionCoordinatorCount;
+    public Integer getCoordinatorDistributed() {
+        return coordinatorDistributed;
     }
 
-    public void setRegionCoordinatorCount(Integer regionCoordinatorCount) {
-        this.regionCoordinatorCount = regionCoordinatorCount;
+    public void setCoordinatorDistributed(Integer coordinatorDistributed) {
+        this.coordinatorDistributed = coordinatorDistributed;
     }
 
-    public Integer getRegionCoordinatorQuota() {
-        return regionCoordinatorQuota;
+    public Integer getCoordinatorQuota() {
+        return coordinatorQuota;
     }
 
-    public void setRegionCoordinatorQuota(Integer regionCoordinatorQuota) {
-        this.regionCoordinatorQuota = regionCoordinatorQuota;
+    public void setCoordinatorQuota(Integer coordinatorQuota) {
+        this.coordinatorQuota = coordinatorQuota;
     }
 }

+ 43 - 0
sop-business/src/main/java/com/qmth/sop/business/mapper/TBUserArchivesAllocationMapper.java

@@ -1,7 +1,14 @@
 package com.qmth.sop.business.mapper;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.qmth.sop.business.bean.result.SysLogResult;
+import com.qmth.sop.business.bean.result.UserArchivesAllocationResult;
 import com.qmth.sop.business.entity.TBUserArchivesAllocation;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * <p>
@@ -12,5 +19,41 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  * @since 2023-08-01
  */
 public interface TBUserArchivesAllocationMapper extends BaseMapper<TBUserArchivesAllocation> {
+    /**
+     * 查询派单档案分配 派单分页列表
+     *
+     * @param iPage         分页参数
+     * @param serviceUnitId 服务单元id
+     * @param province      省
+     * @param city          市
+     * @param area          县
+     * @param customName    客户名称
+     * @param gap           差额
+     * @return 分页查询结果
+     */
+    IPage<UserArchivesAllocationResult> findCrmAllocationPage(@Param("iPage") Page<SysLogResult> iPage,
+                                                              @Param("serviceUnitId") Long serviceUnitId,
+                                                              @Param("province") String province,
+                                                              @Param("city") String city,
+                                                              @Param("area") String area,
+                                                              @Param("customName") String customName,
+                                                              @Param("gap") Integer gap);
 
+    /**
+     * 查询派单档案分配 派单小计列表
+     *
+     * @param serviceUnitId 服务单元id
+     * @param province      省
+     * @param city          市
+     * @param area          县
+     * @param customName    客户名称
+     * @param gap           差额
+     * @return 查询结果
+     */
+    List<UserArchivesAllocationResult> findCrmAllocationSubTotal(@Param("serviceUnitId") Long serviceUnitId,
+                                                                 @Param("province") String province,
+                                                                 @Param("city") String city,
+                                                                 @Param("area") String area,
+                                                                 @Param("customName") String customName,
+                                                                 @Param("gap") Integer gap);
 }

+ 3 - 2
sop-business/src/main/java/com/qmth/sop/business/service/TBUserArchivesAllocationService.java

@@ -1,6 +1,7 @@
 package com.qmth.sop.business.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.qmth.sop.business.bean.params.UserArchivesAllocationParam;
 import com.qmth.sop.business.bean.result.UserArchivesAllocationResult;
 import com.qmth.sop.business.bean.result.UserArchivesAllocationSubTotalResult;
 import com.qmth.sop.business.entity.TBUserArchivesAllocation;
@@ -47,9 +48,9 @@ public interface TBUserArchivesAllocationService extends IService<TBUserArchives
     /**
      * 分配派单
      *
-     * @param obj 派单参数
+     * @param userArchivesAllocationParam 派单参数
      */
-    void editCrmAllocation(Object obj);
+    void editCrmAllocation(UserArchivesAllocationParam userArchivesAllocationParam);
 
     /**
      * 自动批量调配派单和人员

+ 145 - 6
sop-business/src/main/java/com/qmth/sop/business/service/impl/TBUserArchivesAllocationServiceImpl.java

@@ -1,13 +1,32 @@
 package com.qmth.sop.business.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.sop.business.bean.params.AllocationParam;
+import com.qmth.sop.business.bean.params.UserArchivesAllocationParam;
 import com.qmth.sop.business.bean.result.UserArchivesAllocationResult;
 import com.qmth.sop.business.bean.result.UserArchivesAllocationSubTotalResult;
+import com.qmth.sop.business.entity.SysRole;
+import com.qmth.sop.business.entity.TBCrm;
+import com.qmth.sop.business.entity.TBService;
 import com.qmth.sop.business.entity.TBUserArchivesAllocation;
 import com.qmth.sop.business.mapper.TBUserArchivesAllocationMapper;
-import com.qmth.sop.business.service.TBUserArchivesAllocationService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.sop.business.service.*;
+import com.qmth.sop.common.base.BaseEntity;
+import com.qmth.sop.common.contant.SystemConstant;
+import com.qmth.sop.common.enums.ExceptionResultEnum;
+import com.qmth.sop.common.enums.RoleTypeEnum;
+import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -19,24 +38,144 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class TBUserArchivesAllocationServiceImpl extends ServiceImpl<TBUserArchivesAllocationMapper, TBUserArchivesAllocation> implements TBUserArchivesAllocationService {
+    @Resource
+    private TBServiceService tbServiceService;
+    @Resource
+    private TBCrmService tbCrmService;
+    @Resource
+    private SysRoleService sysRoleService;
+    @Resource
+    private SysUserRoleService sysUserRoleService;
 
     @Override
     public IPage<UserArchivesAllocationResult> findCrmAllocationPage(Long serviceUnitId, String province, String city, String area, String customName, Integer gap, Integer pageNumber, Integer pageSize) {
-        return null;
+        province = SystemConstant.translateSpecificSign(province);
+        city = SystemConstant.translateSpecificSign(city);
+        area = SystemConstant.translateSpecificSign(area);
+        customName = SystemConstant.translateSpecificSign(customName);
+        return this.baseMapper.findCrmAllocationPage(new Page<>(pageNumber, pageSize), serviceUnitId, province, city, area, customName, gap);
     }
 
     @Override
     public UserArchivesAllocationSubTotalResult findCrmAllocationSubTotal(Long serviceUnitId, String province, String city, String area, String customName, Integer gap) {
-        return null;
+        province = SystemConstant.translateSpecificSign(province);
+        city = SystemConstant.translateSpecificSign(city);
+        area = SystemConstant.translateSpecificSign(area);
+        customName = SystemConstant.translateSpecificSign(customName);
+        List<UserArchivesAllocationResult> list = this.baseMapper.findCrmAllocationSubTotal(serviceUnitId, province, city, area, customName, gap);
+        Integer publishedCrmCount = Math.toIntExact(list.stream().filter(UserArchivesAllocationResult::getPublish).count());
+        Integer totalCrmCount = list.size();
+
+        Integer coordinatorQuota = list.stream().mapToInt(UserArchivesAllocationResult::getCoordinatorQuota).sum();
+        Integer coordinatorDistributed = list.stream().mapToInt(UserArchivesAllocationResult::getCoordinatorDistributed).sum();
+
+        Integer effectQuota = list.stream().mapToInt(UserArchivesAllocationResult::getEffectQuota).sum();
+        Integer effectDistributed = list.stream().mapToInt(UserArchivesAllocationResult::getEffectDistributed).sum();
+
+        Integer assistantQuota = list.stream().mapToInt(UserArchivesAllocationResult::getAssistantQuota).sum();
+        Integer assistantDistributed = list.stream().mapToInt(UserArchivesAllocationResult::getAssistantDistributed).sum();
+
+        UserArchivesAllocationSubTotalResult result = new UserArchivesAllocationSubTotalResult();
+        result.setPublishedCrmCount(publishedCrmCount);
+        result.setTotalCrmCount(totalCrmCount);
+        result.setCoordinatorDistributed(coordinatorDistributed);
+        result.setCoordinatorQuota(coordinatorQuota);
+        result.setEffectDistributed(effectDistributed);
+        result.setEffectQuota(effectQuota);
+        result.setAssistantDistributed(assistantDistributed);
+        result.setAssistantQuota(assistantQuota);
+        return result;
     }
 
+    @Transactional
     @Override
-    public void editCrmAllocation(Object obj) {
+    public void editCrmAllocation(UserArchivesAllocationParam userArchivesAllocationParam) {
+        Long serviceUnitId = userArchivesAllocationParam.getServiceUnitId();
+        TBService tbService = tbServiceService.getById(serviceUnitId);
+        if (Objects.isNull(tbService)) {
+            throw ExceptionResultEnum.ERROR.exception("服务单元不存在");
+        }
+
+        String crmNo = userArchivesAllocationParam.getCrmNo();
+        Long regionUserId = userArchivesAllocationParam.getRegionUserId();
 
+        List<TBCrm> tbCrmList = tbCrmService.list(new QueryWrapper<TBCrm>().lambda().eq(TBCrm::getCrmNo, crmNo));
+        if (CollectionUtils.isEmpty(tbCrmList)) {
+            throw ExceptionResultEnum.ERROR.exception("派单不存在");
+        }
+        if (tbCrmList.size() > 1) {
+            throw ExceptionResultEnum.ERROR.exception("存在多个相同派单号的派单[" + crmNo + "]");
+        }
+        List<TBUserArchivesAllocation> dbList = this.list(new QueryWrapper<TBUserArchivesAllocation>()
+                .lambda()
+                .eq(TBUserArchivesAllocation::getCrmNo, crmNo));
+
+        if (dbList.stream().anyMatch(e -> Objects.nonNull(e.getSopNo()))) {
+            throw ExceptionResultEnum.ERROR.exception("已发布的派单不能调配");
+        }
+
+        // 新增关系
+        List<AllocationParam> allocationParamList = userArchivesAllocationParam.getAllocationParams();
+
+
+        List<TBUserArchivesAllocation> tbUserArchivesAllocationList = new ArrayList<>();
+        // 处理实施工程师或助理工程师
+        if (CollectionUtils.isNotEmpty(allocationParamList)) {
+            for (AllocationParam allocationParam : allocationParamList) {
+                Long roleId = allocationParam.getRoleId();
+                List<Long> userIdList = allocationParam.getUserIdList();
+                SysRole role = sysRoleService.getById(roleId);
+                if (Objects.isNull(role)) {
+                    throw ExceptionResultEnum.ERROR.exception("认证角色不存在");
+                } else {
+                    if (!RoleTypeEnum.EFFECT_ENGINEER.equals(role.getType()) || !RoleTypeEnum.ASSISTANT_ENGINEER.equals(role.getType())) {
+                        throw ExceptionResultEnum.ERROR.exception(String.format("认证角色类型为[%s]不属于[%s]或[%s]",
+                                role.getType().getDesc(),
+                                RoleTypeEnum.EFFECT_ENGINEER.getDesc(),
+                                RoleTypeEnum.ASSISTANT_ENGINEER.getDesc()));
+                    }
+                }
+
+                for (Long userId : userIdList) {
+                    List<Long> sysRoleIdList = sysUserRoleService.listRoleByUserId(userId).stream().map(BaseEntity::getId).distinct().collect(Collectors.toList());
+                    if (!sysRoleIdList.contains(roleId)) {
+                        throw ExceptionResultEnum.ERROR.exception("所选用户不包含认证角色[" + role.getType().getDesc() + "]");
+                    }
+                    TBUserArchivesAllocation tbUserArchivesAllocation = new TBUserArchivesAllocation();
+                    tbUserArchivesAllocation.setCrmNo(crmNo);
+                    tbUserArchivesAllocation.setServiceId(serviceUnitId);
+                    tbUserArchivesAllocation.setUserId(userId);
+                    tbUserArchivesAllocation.setRoleId(roleId);
+                    tbUserArchivesAllocation.setRegionUserId(regionUserId);
+                    tbUserArchivesAllocationList.add(tbUserArchivesAllocation);
+                }
+            }
+        }
+
+        // 如果实施和助理工程师都不存在,但是区域负责人存在,也新增一条记录
+        if (CollectionUtils.isEmpty(tbUserArchivesAllocationList)) {
+            if (regionUserId != null && regionUserId > 0) {
+                TBUserArchivesAllocation tbUserArchivesAllocation = new TBUserArchivesAllocation();
+                tbUserArchivesAllocation.setCrmNo(crmNo);
+                tbUserArchivesAllocation.setServiceId(serviceUnitId);
+                tbUserArchivesAllocation.setRegionUserId(regionUserId);
+                tbUserArchivesAllocationList.add(tbUserArchivesAllocation);
+            }
+        }
+
+        // 如果存在要分配的记录则根据crm单号删除原先数据并新增
+        if (CollectionUtils.isNotEmpty(tbUserArchivesAllocationList)) {
+            // 新增前删除派单关系
+            if (CollectionUtils.isNotEmpty(dbList)) {
+                this.removeByIds(dbList);
+            }
+            // 新增分配关系
+            this.saveBatch(tbUserArchivesAllocationList);
+        }
     }
 
+    @Transactional
     @Override
     public void autoEditCrmAllocationBatch(Long serviceUnitId) {
-
     }
 }

+ 3 - 1
sop-business/src/main/resources/db/log/caozixuan_update_log.sql

@@ -71,4 +71,6 @@ ALTER TABLE `t_b_user_archives_allocation`
     CHANGE COLUMN `crm_no` `crm_no` VARCHAR(100) NOT NULL COMMENT 'crm单号' ;
 
 -- 2023/08/17
-INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('2015', '公共接口-查询服务单元列表', '/api/admin/common/query_service_unit', 'URL', '64', '25', 'SYS', '1', '1', '0');
+INSERT INTO `sys_privilege` (`id`, `name`, `url`, `type`, `parent_id`, `sequence`, `property`, `enable`, `default_auth`, `front_display`) VALUES ('2015', '公共接口-查询服务单元列表', '/api/admin/common/query_service_unit', 'URL', '64', '25', 'SYS', '1', '1', '0');
+ALTER TABLE `t_b_user_archives_allocation`
+    CHANGE COLUMN `region_user_id` `region_user_id` BIGINT NULL COMMENT '区域协调人id' ;

+ 189 - 0
sop-business/src/main/resources/mapper/TBUserArchivesAllocationMapper.xml

@@ -2,4 +2,193 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.qmth.sop.business.mapper.TBUserArchivesAllocationMapper">
 
+    <select id="findCrmAllocationPage"
+            resultType="com.qmth.sop.business.bean.result.UserArchivesAllocationResult">
+        SELECT
+            *,
+            (result.coordinatorUnDistributed + result.effectUnDistributed + result.assistantUnDistributed) AS unDistributed
+        FROM
+            (SELECT
+                 tbs.id AS serviceUnitId,
+                 tbs.name AS serviceUnitName,
+                 tbc.id AS crmId,
+                 tbc.crm_no AS crmNo,
+                 su.id AS customId,
+                 su.name AS customName,
+                 su.type AS customType,
+                 su.province AS province,
+                 su.city AS city,
+                 su.area AS area,
+                 sl.id AS levelId,
+                 sl.level AS level,
+                 1 AS coordinatorQuota,
+                 IFNULL(effectQ.quota, 0) AS effectQuota,
+                 IFNULL(assistantQ.quota, 0) AS assistantQuota,
+                 IFNULL(coordinatorR.reality, 0) AS coordinatorDistributed,
+                 IFNULL(effectR.reality, 0) AS effectDistributed,
+                 IFNULL(assistantR.reality, 0) AS assistantDistributed,
+                 1 + IFNULL(effectQ.quota, 0) + IFNULL(assistantQ.quota, 0) AS quota,
+                 IFNULL(coordinatorR.reality, 0) + IFNULL(effectR.reality, 0) + IFNULL(assistantR.reality, 0) AS distributed,
+                 IF(1 - IFNULL(coordinatorR.reality, 0) &lt; 0, 0, 1 - IFNULL(coordinatorR.reality, 0)) AS coordinatorUnDistributed,
+                 IF(IFNULL(effectQ.quota, 0) - IFNULL(effectR.reality, 0) &lt; 0, 0, IFNULL(effectQ.quota, 0) - IFNULL(effectR.reality, 0)) AS effectUnDistributed,
+                 IF(IFNULL(assistantQ.quota, 0) - IFNULL(assistantR.reality, 0) &lt; 0, 0, IFNULL(assistantQ.quota, 0) - IFNULL(assistantR.reality, 0)) AS assistantUnDistributed,
+                 IFNULL(coordinatorR.publish, FALSE) AS publish
+             FROM
+                 t_b_crm tbc
+                     LEFT JOIN t_b_service tbs ON tbc.service_id = tbs.id
+                     LEFT JOIN sys_custom su ON tbc.custom_id = su.id
+                     LEFT JOIN sys_level sl ON su.level_id = sl.id
+                     LEFT JOIN (SELECT
+                                    slr.quota, slr.level_id
+                                FROM
+                                    sys_level_role slr
+                                        LEFT JOIN sys_role sr ON sr.id = slr.role_id
+                                WHERE
+                                    sr.type = 'EFFECT_ENGINEER') effectQ ON effectQ.level_id = sl.id
+                     LEFT JOIN (SELECT
+                                    slr.quota, slr.level_id
+                                FROM
+                                    sys_level_role slr
+                                        LEFT JOIN sys_role sr ON sr.id = slr.role_id
+                                WHERE
+                                    sr.type = 'ASSISTANT_ENGINEER') assistantQ ON assistantQ.level_id = sl.id
+                     LEFT JOIN (SELECT
+                                    crm_no,
+                                    MAX(IF(region_user_id IS NULL, 0, 1)) AS reality,
+                                    MAX(IF(sop_no IS NULL, FALSE, TRUE)) AS publish
+                                FROM
+                                    t_b_user_archives_allocation) coordinatorR ON coordinatorR.crm_no = tbc.crm_no
+                     LEFT JOIN (SELECT
+                                    tbuaa.crm_no, COUNT(*) AS reality
+                                FROM
+                                    t_b_user_archives_allocation tbuaa
+                                        LEFT JOIN sys_role sr ON sr.id = tbuaa.role_id
+                                WHERE
+                                    sr.type = 'EFFECT_ENGINEER'
+                                GROUP BY tbuaa.crm_no) effectR ON effectR.crm_no = tbc.crm_no
+                     LEFT JOIN (SELECT
+                                    tbuaa.crm_no, COUNT(*) AS reality
+                                FROM
+                                    t_b_user_archives_allocation tbuaa
+                                        LEFT JOIN sys_role sr ON sr.id = tbuaa.role_id
+                                WHERE
+                                    sr.type = 'ASSISTANT_ENGINEER'
+                                GROUP BY tbuaa.crm_no) assistantR ON assistantR.crm_no = tbc.crm_no
+            WHERE tbs.status != 'CANCEL') result
+        <where>
+            <if test="serviceUnitId != null">
+                AND result.serviceUnitId = #{serviceUnitId}
+            </if>
+            <if test="province != null and province != ''">
+                AND result.province CONCAT('%',#{province},'%')
+            </if>
+            <if test="city != null and city != ''">
+                AND result.city CONCAT('%',#{city},'%')
+            </if>
+            <if test="area != null and area != ''">
+                AND result.area CONCAT('%',#{area},'%')
+            </if>
+            <if test="customName != null and customName != ''">
+                AND result.customName CONCAT('%',#{customName}.'%')
+            </if>
+            <if test="gap != null">
+                AND (result.coordinatorUnDistributed + result.effectUnDistributed + result.assistantUnDistributed) &lt;= #{gap}
+            </if>
+        </where>
+        ORDER BY result.serviceUnitId DESC, result.crmId DESC
+    </select>
+    <select id="findCrmAllocationSubTotal"
+            resultType="com.qmth.sop.business.bean.result.UserArchivesAllocationResult">
+        SELECT
+            *,
+            (result.coordinatorUnDistributed + result.effectUnDistributed + result.assistantUnDistributed) AS unDistributed
+        FROM
+            (SELECT
+                tbs.id AS serviceUnitId,
+                tbs.name AS serviceUnitName,
+                tbc.id AS crmId,
+                tbc.crm_no AS crmNo,
+                su.id AS customId,
+                su.name AS customName,
+                su.type AS customType,
+                su.province AS province,
+                su.city AS city,
+                su.area AS area,
+                sl.id AS levelId,
+                sl.level AS level,
+                1 AS coordinatorQuota,
+                IFNULL(effectQ.quota, 0) AS effectQuota,
+                IFNULL(assistantQ.quota, 0) AS assistantQuota,
+                IFNULL(coordinatorR.reality, 0) AS coordinatorDistributed,
+                IFNULL(effectR.reality, 0) AS effectDistributed,
+                IFNULL(assistantR.reality, 0) AS assistantDistributed,
+                1 + IFNULL(effectQ.quota, 0) + IFNULL(assistantQ.quota, 0) AS quota,
+                IFNULL(coordinatorR.reality, 0) + IFNULL(effectR.reality, 0) + IFNULL(assistantR.reality, 0) AS distributed,
+                IF(1 - IFNULL(coordinatorR.reality, 0) &lt; 0, 0, 1 - IFNULL(coordinatorR.reality, 0)) AS coordinatorUnDistributed,
+                IF(IFNULL(effectQ.quota, 0) - IFNULL(effectR.reality, 0) &lt; 0, 0, IFNULL(effectQ.quota, 0) - IFNULL(effectR.reality, 0)) AS effectUnDistributed,
+                IF(IFNULL(assistantQ.quota, 0) - IFNULL(assistantR.reality, 0) &lt; 0, 0, IFNULL(assistantQ.quota, 0) - IFNULL(assistantR.reality, 0)) AS assistantUnDistributed,
+                IFNULL(coordinatorR.publish, FALSE) AS publish
+             FROM
+                 t_b_crm tbc
+                     LEFT JOIN t_b_service tbs ON tbc.service_id = tbs.id
+                     LEFT JOIN sys_custom su ON tbc.custom_id = su.id
+                     LEFT JOIN sys_level sl ON su.level_id = sl.id
+                     LEFT JOIN (SELECT
+                                    slr.quota, slr.level_id
+                                FROM
+                                    sys_level_role slr
+                                        LEFT JOIN sys_role sr ON sr.id = slr.role_id
+                                WHERE
+                                    sr.type = 'EFFECT_ENGINEER') effectQ ON effectQ.level_id = sl.id
+                     LEFT JOIN (SELECT
+                                    slr.quota, slr.level_id
+                                FROM
+                                    sys_level_role slr
+                                        LEFT JOIN sys_role sr ON sr.id = slr.role_id
+                                WHERE
+                                    sr.type = 'ASSISTANT_ENGINEER') assistantQ ON assistantQ.level_id = sl.id
+                     LEFT JOIN (SELECT
+                                    crm_no,
+                                    MAX(IF(region_user_id IS NULL, 0, 1)) AS reality,
+                                    MAX(IF(sop_no IS NULL, FALSE, TRUE)) AS publish
+                                FROM
+                                    t_b_user_archives_allocation) coordinatorR ON coordinatorR.crm_no = tbc.crm_no
+                     LEFT JOIN (SELECT
+                                    tbuaa.crm_no, COUNT(*) AS reality
+                                FROM
+                                    t_b_user_archives_allocation tbuaa
+                                        LEFT JOIN sys_role sr ON sr.id = tbuaa.role_id
+                                WHERE
+                                    sr.type = 'EFFECT_ENGINEER'
+                                GROUP BY tbuaa.crm_no) effectR ON effectR.crm_no = tbc.crm_no
+                     LEFT JOIN (SELECT
+                                    tbuaa.crm_no, COUNT(*) AS reality
+                                FROM
+                                    t_b_user_archives_allocation tbuaa
+                                        LEFT JOIN sys_role sr ON sr.id = tbuaa.role_id
+                                WHERE
+                                    sr.type = 'ASSISTANT_ENGINEER'
+                                GROUP BY tbuaa.crm_no) assistantR ON assistantR.crm_no = tbc.crm_no
+             WHERE tbs.status != 'CANCEL') result
+        <where>
+            <if test="serviceUnitId != null">
+                AND result.serviceUnitId = #{serviceUnitId}
+            </if>
+            <if test="province != null and province != ''">
+                AND result.province CONCAT('%',#{province},'%')
+            </if>
+            <if test="city != null and city != ''">
+                AND result.city CONCAT('%',#{city},'%')
+            </if>
+            <if test="area != null and area != ''">
+                AND result.area CONCAT('%',#{area},'%')
+            </if>
+            <if test="customName != null and customName != ''">
+                AND result.customName CONCAT('%',#{customName}.'%')
+            </if>
+            <if test="gap != null">
+                AND (result.coordinatorUnDistributed + result.effectUnDistributed + result.assistantUnDistributed) &lt;= #{gap}
+            </if>
+        </where>
+    </select>
 </mapper>

+ 2 - 1
sop-server/src/main/java/com/qmth/sop/server/api/TBServiceController.java

@@ -4,6 +4,7 @@ package com.qmth.sop.server.api;
 import com.qmth.boot.api.constant.ApiConstant;
 import com.qmth.sop.business.annotation.OperationLog;
 import com.qmth.sop.business.bean.params.ServiceUnitParam;
+import com.qmth.sop.business.bean.result.ServiceUnitResult;
 import com.qmth.sop.business.bean.result.SysLogResult;
 import com.qmth.sop.business.entity.SysUser;
 import com.qmth.sop.business.service.TBServiceService;
@@ -39,7 +40,7 @@ public class TBServiceController {
 
     @ApiOperation(value = "服务单元管理-分页查询")
     @RequestMapping(value = "/page", method = RequestMethod.POST)
-    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = SysLogResult.class)})
+    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = ServiceUnitResult.class)})
     @OperationLog
     public Result findServiceUnitPage(@ApiParam(value = "业务类型") @RequestParam(required = false) ProductTypeEnum type,
                                       @ApiParam(value = "负责人") @RequestParam(required = false) String serviceLeadId,