Răsfoiți Sursa

feat(sys): 优化省份地区管理和私域公海客户接口

- 省份新增和修改合并为统一接口,新增批量排序接口,支持灵活排序和状态切换
- 优化DictProvinceRegionService中状态开启逻辑,支持旧id状态关闭及新id状态开启
- 调整省份地区查询排序为升序,提升数据显示逻辑一致性
- 新增私域客户相关接口CustomerDataPrivateController,实现私域客户增删改查及转让功能
- 新增公海客户相关接口CustomerDataPublicController,实现公海客户增删改查及认领功能
- 新增多种后台管理请求DTO和响应BO,包括跟进、联系人、操作日志等数据结构,完善数据交互
- 优化SysCustomerDataFollowService,新增查询操作日志权限校验及客户跟进筛选数据公共方法
- 调整日期选择工具DateSelectUtil,完善多个时间选项,修正时间计算逻辑,提高使用灵活性和准确性
- 新增DictProvinceRegionMapper中的批量更新排序接口,支持数据库层面高效操作
- 相关模型中隐藏部分字段用于接口安全或简化展示,并增加分页参数支持请求封装
zhangxf 1 lună în urmă
părinte
comite
ac5c883e57
38 a modificat fișierele cu 2002 adăugiri și 511 ștergeri
  1. 13 4
      src/main/java/com/jtzx/crm/module/api/web/sys/AdminDictProvinceRegionController.java
  2. 138 0
      src/main/java/com/jtzx/crm/module/api/web/sys/CustomerDataPrivateController.java
  3. 113 0
      src/main/java/com/jtzx/crm/module/api/web/sys/CustomerDataPublicController.java
  4. 1 1
      src/main/java/com/jtzx/crm/module/sys/entity/SysCustomerFollowEntity.java
  5. 3 0
      src/main/java/com/jtzx/crm/module/sys/mapper/DictAreaRegionMapper.java
  6. 2 0
      src/main/java/com/jtzx/crm/module/sys/mapper/DictProvinceRegionMapper.java
  7. 6 0
      src/main/java/com/jtzx/crm/module/sys/mapper/SysCustomerDataMapper.java
  8. 3 0
      src/main/java/com/jtzx/crm/module/sys/mapper/xml/DictProvinceRegionMapper.xml
  9. 10 0
      src/main/java/com/jtzx/crm/module/sys/mapper/xml/SysCustomerDataMapper.xml
  10. 5 10
      src/main/java/com/jtzx/crm/module/sys/model/request/AdminSysCustomerFollowInsertOrUpdateDTO.java
  11. 58 0
      src/main/java/com/jtzx/crm/module/sys/model/request/AdminSysCustomerFollowReqDTO.java
  12. 11 42
      src/main/java/com/jtzx/crm/module/sys/model/request/AdminSysCustomerOperLogListDTO.java
  13. 38 0
      src/main/java/com/jtzx/crm/module/sys/model/request/CustomerPersonReqDTO.java
  14. 28 0
      src/main/java/com/jtzx/crm/module/sys/model/request/DictProvinceRegionDTO.java
  15. 35 0
      src/main/java/com/jtzx/crm/module/sys/model/request/TransferUserReqDTO.java
  16. 38 0
      src/main/java/com/jtzx/crm/module/sys/model/response/CustomerFollowOverViewBO.java
  17. 56 0
      src/main/java/com/jtzx/crm/module/sys/model/response/CustomerProductBO.java
  18. 38 0
      src/main/java/com/jtzx/crm/module/sys/model/response/CustomerProductOverViewBO.java
  19. 50 0
      src/main/java/com/jtzx/crm/module/sys/model/response/SysCustomerDetailBO.java
  20. 3 7
      src/main/java/com/jtzx/crm/module/sys/model/response/SysCustomerFollowAuditBO.java
  21. 39 0
      src/main/java/com/jtzx/crm/module/sys/model/response/SysCustomerFollowAuditDataBO.java
  22. 1 1
      src/main/java/com/jtzx/crm/module/sys/model/response/SysCustomerFollowBO.java
  23. 85 0
      src/main/java/com/jtzx/crm/module/sys/model/response/SysCustomerFollowDataBO.java
  24. 41 0
      src/main/java/com/jtzx/crm/module/sys/model/response/SysCustomerFollowHistorySelectBO.java
  25. 4 4
      src/main/java/com/jtzx/crm/module/sys/model/response/SysCustomerFollowListBO.java
  26. 41 0
      src/main/java/com/jtzx/crm/module/sys/model/response/SysCustomerOperLogDataBO.java
  27. 35 0
      src/main/java/com/jtzx/crm/module/sys/model/response/TransferUserReqBO.java
  28. 22 9
      src/main/java/com/jtzx/crm/module/sys/service/DictProvinceRegionService.java
  29. 159 5
      src/main/java/com/jtzx/crm/module/sys/service/SysCustomerDataFollowService.java
  30. 120 22
      src/main/java/com/jtzx/crm/module/sys/service/SysCustomerDataPrivateService.java
  31. 66 20
      src/main/java/com/jtzx/crm/module/sys/service/SysCustomerDataPublicService.java
  32. 147 15
      src/main/java/com/jtzx/crm/module/sys/service/SysCustomerDataService.java
  33. 88 149
      src/main/java/com/jtzx/crm/module/sys/service/SysCustomerFollowAuditService.java
  34. 384 168
      src/main/java/com/jtzx/crm/module/sys/service/SysCustomerFollowService.java
  35. 92 37
      src/main/java/com/jtzx/crm/module/sys/service/SysCustomerOperLogService.java
  36. 11 4
      src/main/java/com/jtzx/crm/module/sys/service/SysCustomerPersonService.java
  37. 3 1
      src/main/java/com/jtzx/crm/module/sys/service/SysParamService.java
  38. 15 12
      src/main/java/com/jtzx/crm/module/sys/util/DateSelectUtil.java

+ 13 - 4
src/main/java/com/jtzx/crm/module/api/web/sys/AdminDictProvinceRegionController.java

@@ -4,6 +4,7 @@ import cc.uncarbon.framework.web.model.response.ApiResult;
 import cn.dev33.satoken.annotation.SaCheckLogin;
 import com.jtzx.crm.module.api.constant.ApiConstant;
 import com.jtzx.crm.module.api.util.CrmAdminStpUtil;
+import com.jtzx.crm.module.sys.model.request.DictProvinceRegionDTO;
 import com.jtzx.crm.module.sys.model.response.DictProvinceRegionBO;
 import com.jtzx.crm.module.sys.service.DictProvinceRegionService;
 import io.swagger.v3.oas.annotations.Operation;
@@ -42,13 +43,21 @@ public class AdminDictProvinceRegionController {
         return ApiResult.data(dictProvinceRegionService.listUnUsed());
     }
 
-    @Operation(summary = "省份新增")
-    @GetMapping("/region/add/{id}/{sortCode}")
-    public ApiResult<Void> insert(@PathVariable Long id, @PathVariable Integer sortCode) {
-        dictProvinceRegionService.openProvinceStatus(id, sortCode);
+    @Operation(summary = "省份新增和修改")
+    @PostMapping("/region/modify")
+    public ApiResult<Void> insert(@RequestBody DictProvinceRegionDTO dto) {
+        dictProvinceRegionService.openProvinceStatus(dto);
         return ApiResult.success();
     }
 
+    @Operation(summary = "省份排序")
+    @PostMapping("/region/sort")
+    public ApiResult<Void> sort(@RequestBody List<DictProvinceRegionDTO> dtoList) {
+        dictProvinceRegionService.regionSort(dtoList);
+        return ApiResult.success();
+    }
+
+
     @Operation(summary = "省份删除")
     @GetMapping("/region/delete/{id}")
     public ApiResult<Void> delete(@PathVariable Long id) {

+ 138 - 0
src/main/java/com/jtzx/crm/module/api/web/sys/CustomerDataPrivateController.java

@@ -0,0 +1,138 @@
+package com.jtzx.crm.module.api.web.sys;
+
+import cc.uncarbon.framework.core.context.UserContextHolder;
+import cc.uncarbon.framework.core.exception.BusinessException;
+import cc.uncarbon.framework.core.page.PageResult;
+import cc.uncarbon.framework.web.model.response.ApiResult;
+import cn.dev33.satoken.annotation.SaCheckLogin;
+import com.jtzx.crm.module.api.constant.ApiConstant;
+import com.jtzx.crm.module.api.util.CrmAdminStpUtil;
+import com.jtzx.crm.module.sys.model.request.*;
+import com.jtzx.crm.module.sys.model.response.*;
+import com.jtzx.crm.module.sys.service.SysCustomerDataFollowService;
+import com.jtzx.crm.module.sys.service.SysCustomerDataPrivateService;
+import com.jtzx.crm.module.sys.service.SysCustomerFollowService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@SaCheckLogin(type = CrmAdminStpUtil.TYPE)
+@Tag(name = "私域(我的)客户信息接口")
+@RequestMapping(value = ApiConstant.HTTP_API_URL_PREFIX + "/api/v1/private")
+@RequiredArgsConstructor
+@RestController
+@Slf4j
+public class CustomerDataPrivateController {
+
+    private final SysCustomerDataPrivateService sysCustomerDataPrivateService;
+
+    private final SysCustomerFollowService sysCustomerFollowService;
+
+    private final SysCustomerDataFollowService sysCustomerDataFollowService;
+
+
+    @Operation(summary = "添加跟进信息接口")
+    @PostMapping(value = "/customer/data/follow/add")
+    public ApiResult<Void> addFollow(@RequestBody AdminSysCustomerFollowInsertOrUpdateDTO dto) {
+        List<String> roles = UserContextHolder.getUserContext().getRoles();
+        if (!roles.contains("Admin") && !roles.contains("Member")) {
+            throw new BusinessException(400, "无权操作");
+        }
+        sysCustomerFollowService.adminInsert(dto);
+        return ApiResult.success();
+    }
+
+
+    @Operation(summary = "查询顶部筛选条件信息接口")
+    @GetMapping(value = "/customer/data/head/select")
+    public ApiResult<SysCustomerPrivateSelectBO> queryHeadSelectPrivateData() {
+        return ApiResult.data(sysCustomerDataPrivateService.queryHeadSelectPrivateData());
+    }
+
+    @Operation(summary = "分页查询私域客户信息接口")
+    @PostMapping(value = "/customer/data/list")
+    public ApiResult<PageResult<SysCustomerDataPrivateBO>> adminList(@RequestBody AdminSysCustomerDataPrivateListDTO dto) {
+        if (!UserContextHolder.getUserContext().getRoles().contains("Admin")) {
+            dto.setUserId(UserContextHolder.getUserId());
+        }
+        return ApiResult.data(sysCustomerDataPrivateService.adminList(dto));
+    }
+
+    @Operation(summary = "修改私域客户信息接口")
+    @PostMapping(value = "/customer/data/update")
+    public ApiResult<Void> update(@RequestBody AdminSysCustomerDataInsertOrUpdateDTO dto) {
+        sysCustomerDataPrivateService.adminUpdateCustomerData(dto);
+        return ApiResult.success();
+    }
+
+    @Operation(summary = "退回公海客户信息接口")
+    @GetMapping(value = "/customer/data/return/{customerId}")
+    public ApiResult<Void> returnCustomerData(@PathVariable Long customerId) {
+        sysCustomerDataPrivateService.returnCustomerPublicData(customerId);
+        return ApiResult.success();
+    }
+
+    @Operation(summary = "添加私域客户信息接口")
+    @PostMapping(value = "/customer/data/insert")
+    public ApiResult<Void> insert(@RequestBody AdminSysCustomerPersonInsertOrUpdateDTO dto) {
+        sysCustomerDataPrivateService.adminInsertCustomerPerson(dto);
+        return ApiResult.success();
+    }
+
+    @Operation(summary = "修改私域客户联系人信息接口")
+    @PostMapping(value = "/customer/person/update")
+    public ApiResult<Void> updateCustomerPerson(@RequestBody AdminSysCustomerPersonInsertOrUpdateDTO dto) {
+        sysCustomerDataPrivateService.adminUpdateCustomerPerson(dto);
+        return ApiResult.success();
+    }
+
+    @Operation(summary = "删除私域客户联系人信息接口")
+    @GetMapping(value = "/customer/data/delete/{id}", produces = "application/json;charset=UTF-8")
+    public ApiResult<Void> delete(@PathVariable Long id) {
+        sysCustomerDataPrivateService.adminDeleteCustomerPerson(id);
+        return ApiResult.success();
+    }
+
+    @Operation(summary = "查询私域客户联系人信息接口")
+    @PostMapping(value = "/customer/data/select", produces = "application/json;charset=UTF-8")
+    public ApiResult<List<SysCustomerPersonBO>> select(@RequestBody CustomerPersonReqDTO dto) {
+        List<String> roles = UserContextHolder.getUserContext().getRoles();
+        if (roles.contains("Member")) {
+            dto.setUserId(UserContextHolder.getUserId());
+        }
+        return ApiResult.data(sysCustomerDataPrivateService.adminListCustomerPerson(dto));
+    }
+
+
+    @Operation(summary = "查询转让人列表信息接口")
+    @GetMapping(value = "/customer/data/transfer/data/{customerId}", produces = "application/json;charset=UTF-8")
+    public ApiResult<List<TransferUserReqBO>> transferData(@PathVariable Long customerId) {
+        return ApiResult.data(sysCustomerDataPrivateService.queryTransferUser(customerId));
+    }
+
+    @Operation(summary = "转让操作信息接口")
+    @PostMapping(value = "/customer/data/transfer", produces = "application/json;charset=UTF-8")
+    public ApiResult<Void> transfer(@RequestBody TransferUserReqDTO dto) {
+        sysCustomerDataPrivateService.transferUser(dto);
+        return ApiResult.success();
+    }
+
+    @Operation(summary = "查询详情信息接口")
+    @PostMapping(value = "/customer/data/detail", produces = "application/json;charset=UTF-8")
+    public ApiResult<SysCustomerDetailBO> queryCustomerDetail(@RequestBody AdminSysCustomerFollowReqDTO dto) {
+        SysCustomerDetailBO detailBO = sysCustomerDataPrivateService.queryCustomerDetail(dto);
+        return ApiResult.data(detailBO);
+    }
+
+
+    @Operation(summary = "查度私域历史跟进信息接口")
+    @PostMapping(value = "/customer/data/follow/history/data", produces = "application/json;charset=UTF-8")
+    public ApiResult<SysCustomerDetailBO> select(@RequestBody AdminSysCustomerFollowReqDTO dto) {
+        return ApiResult.data(sysCustomerDataFollowService.queryCustomerFollowHistoryDataByPage(dto));
+    }
+
+}

+ 113 - 0
src/main/java/com/jtzx/crm/module/api/web/sys/CustomerDataPublicController.java

@@ -0,0 +1,113 @@
+package com.jtzx.crm.module.api.web.sys;
+
+
+import cc.uncarbon.framework.core.page.PageResult;
+import cc.uncarbon.framework.web.model.response.ApiResult;
+import cn.dev33.satoken.annotation.SaCheckLogin;
+import com.jtzx.crm.module.api.constant.ApiConstant;
+import com.jtzx.crm.module.api.util.CrmAdminStpUtil;
+import com.jtzx.crm.module.sys.model.request.*;
+import com.jtzx.crm.module.sys.model.response.SysCustomerDataPublicBO;
+import com.jtzx.crm.module.sys.model.response.SysCustomerDetailBO;
+import com.jtzx.crm.module.sys.model.response.SysCustomerPersonBO;
+import com.jtzx.crm.module.sys.model.response.SysCustomerPublicSelectBO;
+import com.jtzx.crm.module.sys.service.SysCustomerDataPublicService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@SaCheckLogin(type = CrmAdminStpUtil.TYPE)
+@Tag(name = "公海信息接口")
+@RequestMapping(value = ApiConstant.HTTP_API_URL_PREFIX + "/api/v1/public")
+@RequiredArgsConstructor
+@RestController
+@Slf4j
+public class CustomerDataPublicController {
+
+    private final SysCustomerDataPublicService sysCustomerDataPublicService;
+
+
+    @Operation(summary = "查询顶部筛选条件信息接口")
+    @GetMapping(value = "/head/select/data")
+    public ApiResult<SysCustomerPublicSelectBO> queryHeadSelectData() {
+        return ApiResult.data(sysCustomerDataPublicService.queryHeadSelectData());
+    }
+
+    @Operation(summary = "分页查询公海客户信息列表数据接口")
+    @PostMapping(value = "/customer/list")
+    public ApiResult<PageResult<SysCustomerDataPublicBO>> list(@RequestBody @Valid AdminSysCustomerDataPublicListDTO dto) {
+        PageResult<SysCustomerDataPublicBO> pageResult = sysCustomerDataPublicService.adminList(dto);
+        return ApiResult.data(pageResult);
+    }
+
+    @Operation(summary = "新增公海客户数据接口")
+    @PostMapping(value = "/customer/add")
+    public ApiResult<Void> add(@RequestBody @Valid AdminSysCustomerDataInsertOrUpdateDTO dto) {
+        sysCustomerDataPublicService.adminInsertCustomerData(dto);
+        return ApiResult.success();
+    }
+
+
+    @Operation(summary = "修改公海客户数据接口")
+    @PostMapping(value = "/customer/update")
+    public ApiResult<Void> update(@RequestBody @Valid AdminSysCustomerDataInsertOrUpdateDTO dto) {
+        sysCustomerDataPublicService.adminUpdateCustomerData(dto);
+        return ApiResult.success();
+    }
+
+    @Operation(summary = "删除公海客户信息接口")
+    @GetMapping(value = "/customer/delete/{customerId}")
+    public ApiResult<Void> delete(@PathVariable Long customerId) {
+        sysCustomerDataPublicService.adminDeleteCustomerData(customerId);
+        return ApiResult.success();
+    }
+
+
+    @Operation(summary = "认领公海客户信息接口")
+    @GetMapping(value = "/customer/claim/{customerId}")
+    public ApiResult<Void> claim(@PathVariable Long customerId) {
+        sysCustomerDataPublicService.claimCustomer(customerId);
+        return ApiResult.success();
+    }
+
+
+    @Operation(summary = "公海客户添加联系人数据接口")
+    @PostMapping(value = "/customer/person/add")
+    public ApiResult<Void> personAdd(@RequestBody @Valid AdminSysCustomerPersonInsertOrUpdateDTO dto) {
+        sysCustomerDataPublicService.adminInsertCustomerPerson(dto);
+        return ApiResult.success();
+    }
+
+    @Operation(summary = "公海客户修改联系人数据接口")
+    @PostMapping(value = "/customer/person/update")
+    public ApiResult<Void> personUpdate(@RequestBody @Valid AdminSysCustomerPersonInsertOrUpdateDTO dto) {
+        sysCustomerDataPublicService.adminUpdateCustomerPerson(dto);
+        return ApiResult.success();
+    }
+
+    @Operation(summary = "公海客户删除联系人数据接口")
+    @GetMapping(value = "/customer/person/delete/{personId}")
+    public ApiResult<Void> personDelete(@PathVariable Long personId) {
+        sysCustomerDataPublicService.adminDeleteCustomerPerson(personId);
+        return ApiResult.success();
+    }
+
+    @Operation(summary = "公海客户查询联系人数据接口")
+    @GetMapping(value = "/customer/person/query")
+    public ApiResult<List<SysCustomerPersonBO>> personQuery(@RequestBody @Valid CustomerPersonReqDTO dto) {
+        List<SysCustomerPersonBO> sysCustomerPersonBOS = sysCustomerDataPublicService.adminListCustomerPerson(dto);
+        return ApiResult.data(sysCustomerPersonBOS);
+    }
+
+    @Operation(summary = "查询详情信息接口")
+    @PostMapping(value = "/customer/data/detail", produces = "application/json;charset=UTF-8")
+    public ApiResult<SysCustomerDetailBO> queryCustomerDetail(@RequestBody AdminSysCustomerFollowReqDTO dto) {
+        SysCustomerDetailBO detailBO = sysCustomerDataPublicService.queryCustomerDetail(dto);
+        return ApiResult.data(detailBO);
+    }
+}

+ 1 - 1
src/main/java/com/jtzx/crm/module/sys/entity/SysCustomerFollowEntity.java

@@ -98,7 +98,7 @@ public class SysCustomerFollowEntity extends HelioBaseEntity<Long> {
     @TableField(value = "order_datetime")
     private LocalDateTime orderDatetime;
 
-    @Schema(description = "预约,待办取消状态,0-未取消,1-已取消(预约的取消需要填写取消原因,待办的取消是一个开关,不需要填写原因)")
+    @Schema(description = "预约,待办状态,0-待开始,1-已结束,2-已取消(预约的取消需要填写取消原因)")
     @TableField(value = "order_status")
     private Integer orderStatus;
 

+ 3 - 0
src/main/java/com/jtzx/crm/module/sys/mapper/DictAreaRegionMapper.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Mapper;
 
 import com.jtzx.crm.module.sys.entity.DictAreaRegionEntity;
+import org.apache.ibatis.annotations.Param;
 
 
 /**
@@ -12,4 +13,6 @@ import com.jtzx.crm.module.sys.entity.DictAreaRegionEntity;
 @Mapper
 public interface DictAreaRegionMapper extends BaseMapper<DictAreaRegionEntity> {
 
+
+
 }

+ 2 - 0
src/main/java/com/jtzx/crm/module/sys/mapper/DictProvinceRegionMapper.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Mapper;
 
 import com.jtzx.crm.module.sys.entity.DictProvinceRegionEntity;
+import org.apache.ibatis.annotations.Param;
 
 
 /**
@@ -12,4 +13,5 @@ import com.jtzx.crm.module.sys.entity.DictProvinceRegionEntity;
 @Mapper
 public interface DictProvinceRegionMapper extends BaseMapper<DictProvinceRegionEntity> {
 
+    void updateSortCode(@Param("id") Long id, @Param("sortCode") Integer sortCode, @Param("useStatus") Integer useStatus);
 }

+ 6 - 0
src/main/java/com/jtzx/crm/module/sys/mapper/SysCustomerDataMapper.java

@@ -19,4 +19,10 @@ public interface SysCustomerDataMapper extends BaseMapper<SysCustomerDataEntity>
      * @param customerId
      */
     void returnCustomerData(@Param(value = "customerId")Long customerId);
+
+    /**
+     * 去消赢单人信息
+     * @param customerId
+     */
+    void resetSuccessData(@Param(value = "customerId")Long customerId);
 }

+ 3 - 0
src/main/java/com/jtzx/crm/module/sys/mapper/xml/DictProvinceRegionMapper.xml

@@ -2,4 +2,7 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.jtzx.crm.module.sys.mapper.DictProvinceRegionMapper">
 
+    <update id="updateSortCode">
+        update dict_province_region set sort_code = #{sortCode},use_status = #{useStatus} where id = #{id}
+    </update>
 </mapper>

+ 10 - 0
src/main/java/com/jtzx/crm/module/sys/mapper/xml/SysCustomerDataMapper.xml

@@ -14,4 +14,14 @@
         where id = #{customerId}
     </update>
 
+
+    <update id="resetSuccessData" parameterType="java.lang.Long">
+        update sys_customer_data
+        set
+            success_user_id = null,
+            success_user_name = null,
+            success_status = 0
+        where id = #{customerId}
+    </update>
+
 </mapper>

+ 5 - 10
src/main/java/com/jtzx/crm/module/sys/model/request/AdminSysCustomerFollowInsertOrUpdateDTO.java

@@ -1,5 +1,6 @@
 package com.jtzx.crm.module.sys.model.request;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.Size;
 import lombok.AllArgsConstructor;
@@ -47,7 +48,7 @@ public class AdminSysCustomerFollowInsertOrUpdateDTO implements Serializable {
     @Schema(description = "产品id(param_base_data表主id)")
     private Long productId;
 
-    @Schema(description = "产品名称")
+    @Schema(description = "产品名称", hidden = true)
     @Size(max = 255, message = "【产品名称】最长255位")
     private String productName;
 
@@ -64,14 +65,14 @@ public class AdminSysCustomerFollowInsertOrUpdateDTO implements Serializable {
     @Schema(description = "联系人id(customer_person表主id)")
     private Long customerPersonId;
 
-    @Schema(description = "联系人名称")
+    @Schema(description = "联系人名称", hidden = true)
     @Size(max = 255, message = "【联系人名称】最长255位")
     private String customerPersonName;
 
     @Schema(description = "职务id(param_base_data表主id)")
     private Long positionId;
 
-    @Schema(description = "职务名称")
+    @Schema(description = "职务名称", hidden = true)
     @Size(max = 255, message = "【职务名称】最长255位")
     private String positionName;
 
@@ -85,14 +86,10 @@ public class AdminSysCustomerFollowInsertOrUpdateDTO implements Serializable {
     @Schema(description = "待办时间")
     private LocalDateTime orderDatetime;
 
-    @Schema(description = "预约,待办取消状态,0-未取消,1-已取消(预约的取消需要填写取消原因,待办的取消是一个开关,不需要填写原因)")
-    private Integer orderStatus;
-
-    @Schema(description = "预约取消原因")
+    @Schema(description = "预约取消原因", hidden = true)
     @Size(max = 5000, message = "【预约取消原因】最长5000位")
     private String cancelRemark;
 
-
     @Schema(description = "学段id(param_base_data表主id)", hidden = true)
     private Long stageId;
 
@@ -110,6 +107,4 @@ public class AdminSysCustomerFollowInsertOrUpdateDTO implements Serializable {
 
     @Schema(description = "城市名称", hidden = true)
     private String cityName;
-
-
 }

+ 58 - 0
src/main/java/com/jtzx/crm/module/sys/model/request/AdminSysCustomerFollowReqDTO.java

@@ -0,0 +1,58 @@
+package com.jtzx.crm.module.sys.model.request;
+
+import cc.uncarbon.framework.core.constant.HelioConstant;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import lombok.experimental.SuperBuilder;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+
+/**
+ * 后台管理-分页列表我的客户(学校)数据 DTO
+ */
+@Accessors(chain = true)
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class AdminSysCustomerFollowReqDTO implements Serializable {
+
+
+    @Schema(description = "时间段开始时间")
+    @DateTimeFormat(pattern = HelioConstant.Jackson.DATE_TIME_FORMAT)
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = HelioConstant.Jackson.DATE_TIME_FORMAT)
+    private LocalDateTime startDatetime;
+
+    @Schema(description = "时间段结束时间")
+    @DateTimeFormat(pattern = HelioConstant.Jackson.DATE_TIME_FORMAT)
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = HelioConstant.Jackson.DATE_TIME_FORMAT)
+    private LocalDateTime endDatetime;
+
+    @Schema(description = "客户id")
+    private Long customerId;
+
+    @Schema(description = "职位id")
+    private Long positionId;
+
+    @Schema(description = "产品id")
+    private Long productId;
+
+    @Schema(description = "跟进状态id")
+    private Long followId;
+
+    @Schema(description = "用户id(用户表主id)")
+    private Long userId;
+
+    @Schema(description = "页码")
+    private Integer pageNum;
+
+    @Schema(description = "每页行数")
+    private Integer pageSize;
+}

+ 11 - 42
src/main/java/com/jtzx/crm/module/sys/model/request/AdminSysCustomerOperLogListDTO.java

@@ -27,53 +27,22 @@ public class AdminSysCustomerOperLogListDTO implements Serializable {
     @Schema(description = "客户表主id")
     private Long customerId;
 
-    @Schema(description = "客户名称(关键词)")
-    private String customerName;
-
     @Schema(description = "操作人id")
     private Long operUserId;
 
-    @Schema(description = "操作人名称(关键词)")
-    private String operName;
-
-    @Schema(description = "操作类型,0-认领,1-跟进,2-转让,3-转到公海,11-新增,12-修改,13-删除")
-    private Integer operAction;
-
-    @Schema(description = "操作时间")
-    private LocalDateTime operDatetime;
-
-    @Schema(description = "操作人员所在的项目组id")
-    private Long operUserGroupId;
-
-    @Schema(description = "省份id(省份表主id)")
-    private Long provinceId;
-
-    @Schema(description = "省份名称(关键词)")
-    private String provinceName;
-
-    @Schema(description = "城市id(城市表主id)")
-    private Long cityId;
-
-    @Schema(description = "城市名称(关键词)")
-    private String cityName;
-
-    @Schema(description = "跟进状态id,赢单状态id固定-37,方案演示id固定-33")
-    private Long followId;
-
-    @Schema(description = "跟进状态的名称(关键词)")
-    private String followName;
-
-    @Schema(description = "操作内容")
-    private String content;
-
-    @Schema(description = "时间区间起")
-    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = HelioConstant.Jackson.DATE_TIME_FORMAT)
+    @Schema(description = "开始时间")
     @DateTimeFormat(pattern = HelioConstant.Jackson.DATE_TIME_FORMAT)
-    private LocalDateTime beginAt;
-
-    @Schema(description = "时间区间止")
     @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = HelioConstant.Jackson.DATE_TIME_FORMAT)
+    private LocalDateTime startDate;
+
+    @Schema(description = "结束时间")
     @DateTimeFormat(pattern = HelioConstant.Jackson.DATE_TIME_FORMAT)
-    private LocalDateTime endAt;
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = HelioConstant.Jackson.DATE_TIME_FORMAT)
+    private LocalDateTime endDate;
+
+    @Schema(description = "页码")
+    private Integer pageNum;
 
+    @Schema(description = "每页大小")
+    private Integer pageSize;
 }

+ 38 - 0
src/main/java/com/jtzx/crm/module/sys/model/request/CustomerPersonReqDTO.java

@@ -0,0 +1,38 @@
+package com.jtzx.crm.module.sys.model.request;
+
+import cc.uncarbon.framework.core.constant.HelioConstant;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import lombok.experimental.SuperBuilder;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+
+/**
+ * 后台管理-分页列表客户(学校)联系人数据 DTO
+ */
+@Accessors(chain = true)
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class CustomerPersonReqDTO implements Serializable {
+
+    @Schema(description = "客户表主id")
+    private Long customerId;
+
+    @Schema(description = "客户表主id")
+    private Long userId;
+
+    @Schema(description = "姓名(关键词)")
+    private String queryStr;
+
+    @Schema(description = "职务id(param_base_data表主id)")
+    private Long positionId;
+
+}

+ 28 - 0
src/main/java/com/jtzx/crm/module/sys/model/request/DictProvinceRegionDTO.java

@@ -0,0 +1,28 @@
+package com.jtzx.crm.module.sys.model.request;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import lombok.experimental.SuperBuilder;
+
+import java.io.Serializable;
+
+@Accessors(chain = true)
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class DictProvinceRegionDTO implements Serializable {
+
+    @Schema(description = "id(修改后的id)")
+    private Long id;
+
+    @Schema(description = "修改之的id")
+    private Long oldId;
+
+    @Schema(description = "排序码")
+    private Integer sortCode;
+
+}

+ 35 - 0
src/main/java/com/jtzx/crm/module/sys/model/request/TransferUserReqDTO.java

@@ -0,0 +1,35 @@
+package com.jtzx.crm.module.sys.model.request;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import lombok.experimental.SuperBuilder;
+
+import java.io.Serializable;
+
+
+/**
+ * 后台管理-分页列表客户(学校)联系人数据 DTO
+ */
+@Accessors(chain = true)
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class TransferUserReqDTO implements Serializable {
+
+    @Schema(description = "客户表主id")
+    private Long customerId;
+
+    @Schema(description = "客户表主id")
+    private Long userId;
+
+    @Schema(description = "用户名")
+    private String userName;
+
+    @Schema(description = "小组id")
+    private Long groupId;
+
+}

+ 38 - 0
src/main/java/com/jtzx/crm/module/sys/model/response/CustomerFollowOverViewBO.java

@@ -0,0 +1,38 @@
+package com.jtzx.crm.module.sys.model.response;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import lombok.experimental.SuperBuilder;
+
+import java.io.Serializable;
+
+
+/**
+ * 跟进记录总览
+ */
+@Accessors(chain = true)
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class CustomerFollowOverViewBO implements Serializable {
+
+
+    @Schema(description = "历史产品数量")
+    private Integer historyProductCount;
+
+    @Schema(description = "历史人员数量")
+    private Integer historyPersonCount;
+
+    @Schema(description = "跟进次数")
+    private Integer historyFollowCount;
+
+    @Schema(description = "成功次数")
+    private Integer successCount;
+
+    @Schema(description = "失败次数")
+    private Integer failedCount;
+}

+ 56 - 0
src/main/java/com/jtzx/crm/module/sys/model/response/CustomerProductBO.java

@@ -0,0 +1,56 @@
+package com.jtzx.crm.module.sys.model.response;
+
+import cc.uncarbon.framework.core.constant.HelioConstant;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import lombok.experimental.SuperBuilder;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.List;
+
+
+/**
+ * 全国省省份数据 BO
+ */
+@Accessors(chain = true)
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class CustomerProductBO implements Serializable {
+
+    @Schema(description = "产品ID")
+    private Long productId;
+
+    @Schema(description = "产品名称")
+    private String productName;
+
+    @Schema(description = "排序")
+    private Integer sortCode;
+
+    @Schema(description = "数量")
+    private Integer count;
+
+    @Schema(description = "跟进ID")
+    private Long followId;
+
+    @Schema(description = "跟进名称")
+    private String followName;
+
+    @Schema(description = "客户人员ID")
+    private Long customerPersonId;
+
+    @Schema(description = "客户人员名称")
+    private String customerPersonName;
+
+    @Schema(description = "最后跟进时间")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm")
+    private LocalDateTime lastFollowTime;
+}

+ 38 - 0
src/main/java/com/jtzx/crm/module/sys/model/response/CustomerProductOverViewBO.java

@@ -0,0 +1,38 @@
+package com.jtzx.crm.module.sys.model.response;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import lombok.experimental.SuperBuilder;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+
+/**
+ * 产品总览
+ */
+@Accessors(chain = true)
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class CustomerProductOverViewBO implements Serializable {
+
+    @Schema(description = "产品ID")
+    private Long productId;
+
+    @Schema(description = "产品名称")
+    private String productName;
+
+    @Schema(description = "排序")
+    private Integer sortCode;
+
+    @Schema(description = "数量")
+    private Integer count;
+
+}

+ 50 - 0
src/main/java/com/jtzx/crm/module/sys/model/response/SysCustomerDetailBO.java

@@ -0,0 +1,50 @@
+package com.jtzx.crm.module.sys.model.response;
+
+import cc.uncarbon.framework.core.page.PageResult;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import lombok.experimental.SuperBuilder;
+
+import java.io.Serializable;
+import java.util.List;
+
+
+/**
+ * 历史跟进页面顶部筛选条件数据对象
+ */
+@Accessors(chain = true)
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class SysCustomerDetailBO implements Serializable {
+
+
+    @Schema(description = "筛选条件数据")
+    private SysCustomerFollowHistorySelectBO selectData;
+
+    @Schema(description = "跟进数据列表")
+    private PageResult<SysCustomerFollowListBO> dataPageList;
+
+    @Schema(description = "跟进产品总数")
+    private Integer productCount;
+
+    @Schema(description = "跟进产品总览数据")
+    private List<CustomerProductOverViewBO> productOverviewData;
+
+    @Schema(description = "跟进产品数据")
+    private List<CustomerProductBO> productData;
+
+    @Schema(description = "跟进记录总览数据")
+    private CustomerFollowOverViewBO followOverViewData;
+
+
+    @Schema(description = "预约待办数据")
+    private List<SysCustomerFollowDataBO> orderData;
+
+
+
+}

+ 3 - 7
src/main/java/com/jtzx/crm/module/sys/model/response/SysCustomerFollowAuditBO.java

@@ -28,19 +28,15 @@ public class SysCustomerFollowAuditBO implements Serializable {
     private Long id;
 
     @Schema(description = "创建时刻")
-    @DateTimeFormat(pattern = HelioConstant.Jackson.DATE_TIME_FORMAT)
-    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = HelioConstant.Jackson.DATE_TIME_FORMAT)
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createdAt;
 
-    @Schema(description = "更新时刻")
-    @DateTimeFormat(pattern = HelioConstant.Jackson.DATE_TIME_FORMAT)
-    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = HelioConstant.Jackson.DATE_TIME_FORMAT)
-    private LocalDateTime updatedAt;
 
     @Schema(description = "认领人(跟进)id")
     private Long claimUserId;
 
-    @Schema(description = "审核人id")
+    @Schema(description = "认领人(跟进)名称")
     private String claimUserName;
 
     @Schema(description = "认领人员所在的项目组id")

+ 39 - 0
src/main/java/com/jtzx/crm/module/sys/model/response/SysCustomerFollowAuditDataBO.java

@@ -0,0 +1,39 @@
+package com.jtzx.crm.module.sys.model.response;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import lombok.experimental.SuperBuilder;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.List;
+
+
+/**
+ * 赢单跟进审核信息 BO
+ */
+@Accessors(chain = true)
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class SysCustomerFollowAuditDataBO implements Serializable {
+
+    @Schema(description = "待审核数量")
+    private Integer audit0;
+
+    @Schema(description = "已通过数量")
+    private Integer audit1;
+
+    @Schema(description = "已驳回数量")
+    private Integer audit2;
+
+    @Schema(description = "数据")
+    private List<SysCustomerFollowAuditBO> auditData;
+
+}

+ 1 - 1
src/main/java/com/jtzx/crm/module/sys/model/response/SysCustomerFollowBO.java

@@ -91,7 +91,7 @@ public class SysCustomerFollowBO implements Serializable {
     @Schema(description = "待办时间")
     private LocalDateTime orderDatetime;
 
-    @Schema(description = "预约,待办取消状态,0-未取消,1-已取消(预约的取消需要填写取消原因,待办的取消是一个开关,不需要填写原因)")
+    @Schema(description = "预约,待办状态,0-待开始,1-已结束,2-已取消(预约的取消需要填写取消原因)")
     private Integer orderStatus;
 
     @Schema(description = "预约取消原因")

+ 85 - 0
src/main/java/com/jtzx/crm/module/sys/model/response/SysCustomerFollowDataBO.java

@@ -0,0 +1,85 @@
+package com.jtzx.crm.module.sys.model.response;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import lombok.experimental.SuperBuilder;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+
+/**
+ * 客户跟进数据信息 BO
+ */
+@Accessors(chain = true)
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class SysCustomerFollowDataBO implements Serializable {
+
+    @Schema(description = "主键ID")
+    private Long id;
+
+    @Schema(description = "创建时刻")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm")
+    private LocalDateTime createdAt;
+
+    @Schema(description = "认领人(跟进)id")
+    private Long claimUserId;
+
+    @Schema(description = "认领人(跟进)名称")
+    private String claimUserName;
+
+    @Schema(description = "跟进时间")
+    private LocalDateTime claimDatetime;
+
+    @Schema(description = "客户表主id")
+    private Long customerId;
+
+    @Schema(description = "客户名称")
+    private String customerName;
+
+    @Schema(description = "产品id(param_base_data表主id)")
+    private Long productId;
+
+    @Schema(description = "产品名称")
+    private String productName;
+
+    @Schema(description = "跟进状态id,赢单状态id固定-37,方案演示id固定-33")
+    private Long followId;
+
+    @Schema(description = "跟进状态的名称")
+    private String followName;
+
+    @Schema(description = "是否赢单,0-否,1-是")
+    private Integer successStatus;
+
+    @Schema(description = "联系人id(customer_person表主id)")
+    private Long customerPersonId;
+
+    @Schema(description = "联系人名称")
+    private String customerPersonName;
+
+    @Schema(description = "职务id(param_base_data表主id)")
+    private Long positionId;
+
+    @Schema(description = "职务名称")
+    private String positionName;
+
+    @Schema(description = "跟进内容")
+    private String followContent;
+
+    @Schema(description = "预约待办类型,0-预约,1-待办,(follow_id=33时为预约,其它为待办),这个数据可以为null")
+    private Integer orderType;
+
+    @Schema(description = "待办时间")
+    private LocalDateTime orderDatetime;
+
+}

+ 41 - 0
src/main/java/com/jtzx/crm/module/sys/model/response/SysCustomerFollowHistorySelectBO.java

@@ -0,0 +1,41 @@
+package com.jtzx.crm.module.sys.model.response;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import lombok.experimental.SuperBuilder;
+
+import java.io.Serializable;
+import java.util.List;
+
+
+/**
+ * 历史跟进页面顶部筛选条件数据对象
+ */
+@Accessors(chain = true)
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class SysCustomerFollowHistorySelectBO implements Serializable {
+
+
+    @Schema(description = "时间数据")
+    private List<DateSelectBO> dateData;
+
+    @Schema(description = "产品数据")
+    private List<SelectBO> productData;
+
+    @Schema(description = "跟进状态数据")
+    private List<SelectBO> followData;
+
+    @Schema(description = "职务数据")
+    private List<SelectBO> positionData;
+
+    @Schema(description = "成员数据")
+    private List<BindUserBO> memberData;
+
+
+}

+ 4 - 4
src/main/java/com/jtzx/crm/module/sys/model/response/SysCustomerFollowListBO.java

@@ -27,8 +27,8 @@ public class SysCustomerFollowListBO implements Serializable {
     @Schema(description = "主键ID")
     private Long id;
 
-    @Schema(description = "客户类型名称")
-    private String typeName;
+//    @Schema(description = "客户类型名称")
+//    private String typeName;
 
     @Schema(description = "客户名称")
     private String customerName;
@@ -64,7 +64,7 @@ public class SysCustomerFollowListBO implements Serializable {
     private String followContent;
 
     @Schema(description = "跟进时间")
-    @DateTimeFormat(pattern = HelioConstant.Jackson.DATE_FORMAT)
-    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = HelioConstant.Jackson.DATE_FORMAT)
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm")
     private LocalDateTime claimDatetime;
 }

+ 41 - 0
src/main/java/com/jtzx/crm/module/sys/model/response/SysCustomerOperLogDataBO.java

@@ -0,0 +1,41 @@
+package com.jtzx.crm.module.sys.model.response;
+
+import cc.uncarbon.framework.core.constant.HelioConstant;
+import cc.uncarbon.framework.core.page.PageResult;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import lombok.experimental.SuperBuilder;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.List;
+
+
+/**
+ * 客户操作日志信息数据 BO
+ */
+@Accessors(chain = true)
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class SysCustomerOperLogDataBO implements Serializable {
+
+    @Schema(description = "时间数据")
+    private List<DateSelectBO> dateData;
+
+    @Schema(description = "分组数据")
+    private List<SelectBO> groupData;
+
+    @Schema(description = "成员数据")
+    private List<BindUserBO> memberData;
+
+    @Schema(description = "操作记录列表数据")
+    private PageResult<SysCustomerOperLogBO> data;
+
+}

+ 35 - 0
src/main/java/com/jtzx/crm/module/sys/model/response/TransferUserReqBO.java

@@ -0,0 +1,35 @@
+package com.jtzx.crm.module.sys.model.response;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import lombok.experimental.SuperBuilder;
+
+import java.io.Serializable;
+
+
+/**
+ * 后台管理-分页列表客户(学校)联系人数据 DTO
+ */
+@Accessors(chain = true)
+@SuperBuilder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class TransferUserReqBO implements Serializable {
+
+    @Schema(description = "客户表主id")
+    private Long customerId;
+
+    @Schema(description = "客户表主id")
+    private Long userId;
+
+    @Schema(description = "用户名")
+    private String userName;
+
+    @Schema(description = "小组id")
+    private Long groupId;
+
+}

+ 22 - 9
src/main/java/com/jtzx/crm/module/sys/service/DictProvinceRegionService.java

@@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.jtzx.crm.module.sys.entity.DictProvinceRegionEntity;
 import com.jtzx.crm.module.sys.mapper.DictProvinceRegionMapper;
+import com.jtzx.crm.module.sys.model.request.DictProvinceRegionDTO;
 import com.jtzx.crm.module.sys.model.response.DictProvinceRegionBO;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -50,7 +51,7 @@ public class DictProvinceRegionService {
                 new QueryWrapper<DictProvinceRegionEntity>()
                         .lambda()// 排序
                         .eq(DictProvinceRegionEntity::getUseStatus, 1)
-                        .orderByDesc(DictProvinceRegionEntity::getSortCode)
+                        .orderByAsc(DictProvinceRegionEntity::getSortCode)
         );
         return this.entityList2BOs(list);
     }
@@ -63,7 +64,7 @@ public class DictProvinceRegionService {
                 new QueryWrapper<DictProvinceRegionEntity>()
                         .lambda()// 排序
                         .eq(DictProvinceRegionEntity::getUseStatus, 0)
-                        .orderByDesc(DictProvinceRegionEntity::getCode)
+                        .orderByAsc(DictProvinceRegionEntity::getCode)
         );
         return this.entityList2BOs(list);
     }
@@ -71,13 +72,12 @@ public class DictProvinceRegionService {
 
     /**
      * 更新使用状态(相当于是参数设置中新增一个地区管理)
-     * @param id
      */
-    public void openProvinceStatus(Long id, Integer sortCode) {
-        DictProvinceRegionEntity region = dictProvinceRegionMapper.selectById(id);
-        region.setUseStatus(1);
-        region.setSortCode(sortCode);
-        dictProvinceRegionMapper.updateById(region);
+    public void openProvinceStatus(DictProvinceRegionDTO dto) {
+        if(dto.getOldId()!=null){
+            dictProvinceRegionMapper.updateSortCode(dto.getOldId(),null,0);
+        }
+        dictProvinceRegionMapper.updateSortCode(dto.getId(),dto.getSortCode(),1);
     }
 
     /**
@@ -104,7 +104,6 @@ public class DictProvinceRegionService {
                     e.setSortCode(e.getSortCode() - 1));
             dictProvinceRegionMapper.updateById(regionEntityList);
         }
-
     }
 
 
@@ -122,6 +121,20 @@ public class DictProvinceRegionService {
         return this.entity2BO(entity);
     }
 
+    /**
+     * 批量操作,前端排序
+     * @param dtoList
+     */
+    public void regionSort(List<DictProvinceRegionDTO> dtoList){
+        dictProvinceRegionMapper.selectList(null)
+                .forEach(e -> dictProvinceRegionMapper.updateSortCode(e.getId(),null,0));
+
+        dtoList.forEach(dto -> dictProvinceRegionMapper.updateSortCode(dto.getId(), dto.getSortCode(), 1));
+
+    }
+
+
+
     /*
     ----------------------------------------------------------------
                         私有方法 private methods

+ 159 - 5
src/main/java/com/jtzx/crm/module/sys/service/SysCustomerDataFollowService.java

@@ -1,10 +1,13 @@
 package com.jtzx.crm.module.sys.service;
 
 
+import cc.uncarbon.framework.core.context.UserContextHolder;
+import cc.uncarbon.framework.core.exception.BusinessException;
 import cc.uncarbon.framework.core.page.PageResult;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.text.CharSequenceUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.google.common.collect.Lists;
@@ -15,10 +18,9 @@ import com.jtzx.crm.module.sys.mapper.SysCustomerFollowMapper;
 import com.jtzx.crm.module.sys.mapper.SysGroupMapper;
 import com.jtzx.crm.module.sys.mapper.SysParamBaseDataMapper;
 import com.jtzx.crm.module.sys.model.request.AdminSysCustomerDataFollowListDTO;
-import com.jtzx.crm.module.sys.model.response.BindUserBO;
-import com.jtzx.crm.module.sys.model.response.SysCustomerFollowListBO;
-import com.jtzx.crm.module.sys.model.response.SysCustomerFollowSelectBO;
-import com.jtzx.crm.module.sys.model.response.SysCustomerSelectBO;
+import com.jtzx.crm.module.sys.model.request.AdminSysCustomerFollowReqDTO;
+import com.jtzx.crm.module.sys.model.request.AdminSysCustomerOperLogListDTO;
+import com.jtzx.crm.module.sys.model.response.*;
 import com.jtzx.crm.module.sys.util.DateSelectUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -43,12 +45,14 @@ public class SysCustomerDataFollowService {
 
     private final SysParamBaseDataMapper sysParamBaseDataMapper;
 
-
     private final SysCustomerUserCommonService sysCustomerUserCommonService;
 
+    private final SysCustomerOperLogService sysCustomerOperLogService;
+
 
     /**
      * 查询客户跟进页面顶部筛选条件数据
+     *
      * @return
      */
     public SysCustomerFollowSelectBO queryHeadSelectPrivateData() {
@@ -139,6 +143,156 @@ public class SysCustomerDataFollowService {
         return this.entityPage2BOPage(entityPage);
     }
 
+    /**
+     * 操作日志列表查询
+     */
+    public SysCustomerOperLogDataBO queryOperLogData(AdminSysCustomerOperLogListDTO dto) {
+        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("Admin")) {
+            throw new BusinessException(400, "无权操作");
+        }
+        return sysCustomerOperLogService.adminList(dto, true, true);
+    }
+
+
+    /**
+     * 客户跟进顶部筛选条件数据公开方法
+     *
+     * @param customerId
+     * @return
+     */
+    public SysCustomerFollowHistorySelectBO queryCustomerFollowSelectCommonData(Long customerId, Long userId) {
+        SysCustomerFollowHistorySelectBO resultData = SysCustomerFollowHistorySelectBO.builder().build();
+        List<SelectBO> productData = Lists.newArrayList();
+        List<SelectBO> followData = Lists.newArrayList();
+        List<BindUserBO> memberData = Lists.newArrayList();
+        List<SelectBO> positionData = Lists.newArrayList();
+        //查询跟进数据
+        List<SysCustomerFollowEntity> followEntityList =
+                sysCustomerFollowMapper.selectList(
+                        new LambdaQueryWrapper<>(SysCustomerFollowEntity.class)
+                                .select(
+                                        SysCustomerFollowEntity::getProductId,
+                                        SysCustomerFollowEntity::getProductName,
+                                        SysCustomerFollowEntity::getFollowId,
+                                        SysCustomerFollowEntity::getFollowName,
+                                        SysCustomerFollowEntity::getClaimUserId,
+                                        SysCustomerFollowEntity::getClaimUserName
+                                )
+                                .eq(SysCustomerFollowEntity::getCustomerId, customerId)
+                                .ne(userId != null, SysCustomerFollowEntity::getClaimUserId, userId)
+                                .orderByDesc(SysCustomerFollowEntity::getCreatedAt)
+                );
+        if (CollUtil.isNotEmpty(followEntityList)) {
+            followEntityList.forEach(
+                    entity -> {
+                        if (CollUtil.isEmpty(productData) || productData.stream().map(SelectBO::getId).noneMatch(entity.getProductId()::equals)) {
+                            SelectBO productBO = SelectBO.builder()
+                                    .id(entity.getProductId())
+                                    .name(entity.getProductName())
+                                    .build();
+                            productData.add(productBO);
+                        }
+                        if (CollUtil.isEmpty(followData) || followData.stream().map(SelectBO::getId).noneMatch(entity.getFollowId()::equals)) {
+                            SelectBO followBO = SelectBO.builder()
+                                    .id(entity.getFollowId())
+                                    .name(entity.getFollowName())
+                                    .build();
+                            followData.add(followBO);
+                        }
+                        if (CollUtil.isEmpty(memberData) || memberData.stream().map(BindUserBO::getId).noneMatch(entity.getClaimUserId()::equals)) {
+                            BindUserBO memberBO = BindUserBO.builder()
+                                    .id(entity.getClaimUserId())
+                                    .username(entity.getClaimUserName())
+                                    .build();
+                            memberData.add(memberBO);
+                        }
+                        if(userId!=null){
+                            if (CollUtil.isEmpty(positionData) || positionData.stream().map(SelectBO::getId).noneMatch(entity.getPositionId()::equals)) {
+                                SelectBO positionBO = SelectBO.builder()
+                                        .id(entity.getPositionId())
+                                        .name(entity.getPositionName())
+                                        .build();
+                                positionData.add(positionBO);
+                            }
+                        }
+                    }
+            );
+            SelectBO bo = SelectBO.builder()
+                    .name("全部")
+                    .build();
+            productData.addFirst(bo);
+            followData.addFirst(bo);
+            positionData.addFirst(bo);
+            BindUserBO memberBO = BindUserBO.builder()
+                    .username("全部")
+                    .build();
+            memberData.addFirst(memberBO);
+        }
+        resultData.setProductData(productData);
+        resultData.setFollowData(followData);
+        resultData.setMemberData(memberData);
+        resultData.setDateData(Lists.newArrayList());
+        resultData.setPositionData(Lists.newArrayList());
+        if(userId!=null){
+            resultData.setPositionData(positionData);
+            resultData.setDateData(DateSelectUtil.getDateData());
+        }
+        return resultData;
+    }
+
+
+    /**
+     * 查询客户跟进历史数据
+     *
+     * @param dto
+     */
+    public SysCustomerDetailBO queryCustomerFollowHistoryDataByPage(AdminSysCustomerFollowReqDTO dto) {
+        //查询跟进数据
+        Page<SysCustomerFollowEntity> pageData =
+                sysCustomerFollowMapper.selectPage(
+                        new Page<>(dto.getPageNum(), dto.getPageSize()),
+                        new LambdaQueryWrapper<>(SysCustomerFollowEntity.class)
+                                .eq(SysCustomerFollowEntity::getCustomerId, dto.getCustomerId())
+                                .ne(SysCustomerFollowEntity::getClaimUserId, UserContextHolder.getUserId())
+                                .eq(dto.getProductId() != null, SysCustomerFollowEntity::getProductId, dto.getProductId())
+                                .eq(dto.getFollowId() != null, SysCustomerFollowEntity::getFollowId, dto.getFollowId())
+                                .eq(dto.getUserId() != null, SysCustomerFollowEntity::getClaimUserId, dto.getUserId())
+                                .orderByDesc(SysCustomerFollowEntity::getCreatedAt)
+                );
+        PageResult<SysCustomerFollowListBO> pageResult = this.entityPage2BOPage(pageData);
+
+
+        SysCustomerDetailBO resultData = SysCustomerDetailBO.builder().build();
+        resultData.setDataPageList(pageResult);
+        resultData.setSelectData(this.queryCustomerFollowSelectCommonData(dto.getCustomerId(), UserContextHolder.getUserId()));
+        return resultData;
+    }
+
+
+    /**
+     * 查询客户跟进数据
+     *
+     * @param dto
+     */
+    public PageResult<SysCustomerFollowListBO> queryCustomerFollowDataCommonByPage(AdminSysCustomerFollowReqDTO dto) {
+        //查询跟进数据
+        Page<SysCustomerFollowEntity> pageData =
+                sysCustomerFollowMapper.selectPage(
+                        new Page<>(dto.getPageNum(), dto.getPageSize()),
+                        new LambdaQueryWrapper<>(SysCustomerFollowEntity.class)
+                                .eq(SysCustomerFollowEntity::getCustomerId, dto.getCustomerId())
+                                .eq(dto.getProductId() != null, SysCustomerFollowEntity::getProductId, dto.getProductId())
+                                .eq(dto.getFollowId() != null, SysCustomerFollowEntity::getFollowId, dto.getFollowId())
+                                .eq(dto.getUserId() != null, SysCustomerFollowEntity::getClaimUserId, dto.getUserId())
+                                .eq(dto.getPositionId() != null, SysCustomerFollowEntity::getPositionId, dto.getPositionId())
+                                .ge(dto.getStartDatetime() != null, SysCustomerFollowEntity::getCreatedAt, dto.getStartDatetime())
+                                .le(dto.getEndDatetime() != null, SysCustomerFollowEntity::getCreatedAt, dto.getEndDatetime())
+                                .orderByDesc(SysCustomerFollowEntity::getCreatedAt)
+                );
+        return this.entityPage2BOPage(pageData);
+    }
+
+
     /**
      * 实体分页转 BO 分页
      *

+ 120 - 22
src/main/java/com/jtzx/crm/module/sys/service/SysCustomerDataPrivateService.java

@@ -11,17 +11,9 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.google.common.collect.Lists;
-import com.jtzx.crm.module.sys.entity.SysCustomerDataEntity;
-import com.jtzx.crm.module.sys.entity.SysCustomerFollowEntity;
-import com.jtzx.crm.module.sys.entity.SysGroupEntity;
-import com.jtzx.crm.module.sys.entity.SysParamBaseDataEntity;
-import com.jtzx.crm.module.sys.mapper.SysCustomerDataMapper;
-import com.jtzx.crm.module.sys.mapper.SysCustomerFollowMapper;
-import com.jtzx.crm.module.sys.mapper.SysGroupMapper;
-import com.jtzx.crm.module.sys.mapper.SysParamBaseDataMapper;
-import com.jtzx.crm.module.sys.model.request.AdminSysCustomerDataInsertOrUpdateDTO;
-import com.jtzx.crm.module.sys.model.request.AdminSysCustomerDataPrivateListDTO;
-import com.jtzx.crm.module.sys.model.request.AdminSysCustomerPersonInsertOrUpdateDTO;
+import com.jtzx.crm.module.sys.entity.*;
+import com.jtzx.crm.module.sys.mapper.*;
+import com.jtzx.crm.module.sys.model.request.*;
 import com.jtzx.crm.module.sys.model.response.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -46,14 +38,23 @@ public class SysCustomerDataPrivateService {
 
     private final SysCustomerFollowMapper sysCustomerFollowMapper;
 
+    private final SysUserMapper sysUserMapper;
+
     private final SysCustomerUserCommonService sysCustomerUserCommonService;
 
     private final SysCustomerDataService sysCustomerDataService;
 
-    private final SysCustomerPersonService  sysCustomerPersonService;
+    private final SysCustomerPersonService sysCustomerPersonService;
+
+    private final SysCustomerDataFollowService sysCustomerDataFollowService;
+
+    private final SysCustomerFollowService sysCustomerFollowService;
+
+    private final SysCustomerOperLogService sysCustomerOperLogService;
 
     /**
      * 查询私域(我的)客户页面顶部筛选条件数据
+     *
      * @return
      */
     public SysCustomerPrivateSelectBO queryHeadSelectPrivateData() {
@@ -78,6 +79,16 @@ public class SysCustomerDataPrivateService {
      * 后台管理-我的客户(学校)分页列表
      */
     public PageResult<SysCustomerDataPrivateBO> adminList(AdminSysCustomerDataPrivateListDTO dto) {
+
+        List<String> roles = UserContextHolder.getUserContext().getRoles();
+        if (!roles.contains("Admin") && !roles.contains("Member")) {
+            return new PageResult<SysCustomerDataPrivateBO>()
+                    .setCurrent(1)
+                    .setSize(dto.getPageSize())
+                    .setTotal(0)
+                    .setRecords(Lists.newArrayList());
+        }
+
         List<Long> userIds = Lists.newArrayList();
         if (dto.getUserId() != null) {
             userIds.add(dto.getUserId());
@@ -142,12 +153,13 @@ public class SysCustomerDataPrivateService {
 
     /**
      * 我的客户修改
+     *
      * @param dto
      */
     @Transactional(rollbackFor = Exception.class)
     public void adminUpdateCustomerData(AdminSysCustomerDataInsertOrUpdateDTO dto) {
         List<String> roles = UserContextHolder.getUserContext().getRoles();
-        if (!roles.contains("admin") && !roles.contains("Member")) {
+        if (!roles.contains("Admin") && !roles.contains("Member")) {
             throw new BusinessException(400, "无权操作");
         }
         sysCustomerDataService.adminUpdate(dto);
@@ -156,37 +168,44 @@ public class SysCustomerDataPrivateService {
 
     /**
      * 客户退回公海
+     *
      * @param customerId
      */
     @Transactional(rollbackFor = Exception.class)
-    public void returnCustomerData(Long customerId) {
+    public void returnCustomerPublicData(Long customerId) {
+        List<String> roles = UserContextHolder.getUserContext().getRoles();
+        if (!roles.contains("Admin") && !roles.contains("Member")) {
+            throw new BusinessException(400, "无权操作");
+        }
         sysCustomerDataService.returnCustomerData(customerId);
     }
 
 
     /**
      * 我的客户添加联系人
+     *
      * @param dto
      * @return
      */
     @Transactional(rollbackFor = Exception.class)
-    public Long adminInsertCustomerPerson(AdminSysCustomerPersonInsertOrUpdateDTO dto) {
+    public void adminInsertCustomerPerson(AdminSysCustomerPersonInsertOrUpdateDTO dto) {
         List<String> roles = UserContextHolder.getUserContext().getRoles();
-        if (!roles.contains("admin") && !roles.contains("Member")) {
+        if (!roles.contains("Admin") && !roles.contains("Member")) {
             throw new BusinessException(400, "无权操作");
         }
-        return sysCustomerPersonService.adminInsert(dto);
+        sysCustomerPersonService.adminInsert(dto);
     }
 
 
     /**
      * 我的客户修改联系人
+     *
      * @param dto
      */
     @Transactional(rollbackFor = Exception.class)
     public void adminUpdateCustomerPerson(AdminSysCustomerPersonInsertOrUpdateDTO dto) {
         List<String> roles = UserContextHolder.getUserContext().getRoles();
-        if (!roles.contains("admin") && !roles.contains("Member")) {
+        if (!roles.contains("Admin") && !roles.contains("Member")) {
             throw new BusinessException(400, "无权操作");
         }
         sysCustomerPersonService.adminUpdate(dto);
@@ -194,12 +213,13 @@ public class SysCustomerDataPrivateService {
 
     /**
      * 我的客户删除联系人
+     *
      * @param id
      */
     @Transactional(rollbackFor = Exception.class)
     public void adminDeleteCustomerPerson(Long id) {
         List<String> roles = UserContextHolder.getUserContext().getRoles();
-        if (!roles.contains("admin") && !roles.contains("Member")) {
+        if (!roles.contains("Admin") && !roles.contains("Member")) {
             throw new BusinessException(400, "无权操作");
         }
         sysCustomerPersonService.adminDelete(id);
@@ -209,12 +229,90 @@ public class SysCustomerDataPrivateService {
     /**
      * 查询我的客户联系人
      */
-    public List<SysCustomerPersonBO> adminListCustomerPerson(Long customerId, Long positionId) {
+    public List<SysCustomerPersonBO> adminListCustomerPerson(CustomerPersonReqDTO dto) {
         List<String> roles = UserContextHolder.getUserContext().getRoles();
-        if (!roles.contains("admin") && !roles.contains("Member")) {
+        if (!roles.contains("Admin") && !roles.contains("Member")) {
+            return Lists.newArrayList();
+        }
+        return sysCustomerPersonService.adminList(dto);
+    }
+
+
+    /**
+     * 查询转让人信息  ,转让时需要先查询能够接受当前这个客户的受让人信息列表
+     *
+     * @param customerId
+     * @return
+     */
+    public List<TransferUserReqBO> queryTransferUser(Long customerId) {
+
+        List<String> roles = UserContextHolder.getUserContext().getRoles();
+        if (!roles.contains("Admin") && !roles.contains("Member")) {
+            throw new BusinessException(400, "无权操作");
+        }
+        return sysCustomerDataService.queryTransferUser(customerId);
+    }
+
+    /**
+     * 转让操作
+     *
+     * @param dto
+     */
+    public void transferUser(TransferUserReqDTO dto) {
+        List<String> roles = UserContextHolder.getUserContext().getRoles();
+        if (!roles.contains("Admin") && !roles.contains("Member")) {
+            throw new BusinessException(400, "无权操作");
+        }
+        sysCustomerDataService.transferUser(dto);
+    }
+
+
+    /**
+     * 查询我的客户详情的信息总览
+     *
+     * @param dto
+     */
+    public SysCustomerDetailBO queryCustomerDetail(AdminSysCustomerFollowReqDTO dto) {
+        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("Admin")) {
+            throw new BusinessException(400, "无权操作");
+        }
+        SysCustomerDetailBO detailBO = SysCustomerDetailBO.builder().build();
+        dto.setUserId(UserContextHolder.getUserId());
+        //顶部筛选条件数据
+        SysCustomerFollowHistorySelectBO publicCustomerSelectData = sysCustomerDataFollowService.queryCustomerFollowSelectCommonData(dto.getCustomerId(), dto.getUserId());
+        detailBO.setSelectData(publicCustomerSelectData);
+        //客户详情信息
+        PageResult<SysCustomerFollowListBO> dataPageList = sysCustomerDataFollowService.queryCustomerFollowDataCommonByPage(dto);
+        detailBO.setDataPageList(dataPageList);
+        detailBO.setProductCount(0);
+        //跟进产品信息总览
+        List<CustomerProductOverViewBO> overViewBOS = sysCustomerFollowService.queryProductOverViewData(dto.getCustomerId());
+        if (CollUtil.isNotEmpty(overViewBOS)) {
+            int productCount = overViewBOS.stream().map(CustomerProductOverViewBO::getCount).reduce(0, Integer::sum);
+            detailBO.setProductCount(productCount);
+        }
+        detailBO.setProductOverviewData(overViewBOS);
+        //跟进产品信息列表
+        detailBO.setProductData(sysCustomerFollowService.queryCustomerProductData(dto.getCustomerId(), dto.getUserId()));
+        //预约待办信息
+        detailBO.setOrderData(sysCustomerFollowService.handleOrderData(dto.getCustomerId(), dto.getUserId()));
+        SysUserEntity sysUserEntity = sysUserMapper.selectById(UserContextHolder.getUserId());
+        //历史跟进总览开关
+        if (sysUserEntity.getHistoryFollowStatus() != null && sysUserEntity.getHistoryFollowStatus() == 1) {
+            //历史跟进总览
+            detailBO.setFollowOverViewData(sysCustomerFollowService.handleCustomerFollowOverViewData(dto.getCustomerId(), dto.getUserId()));
+        }
+        return detailBO;
+    }
+
+    /**
+     * 操作日志列表查询
+     */
+    public SysCustomerOperLogDataBO queryOperLogData(AdminSysCustomerOperLogListDTO dto) {
+        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("Admin")) {
             throw new BusinessException(400, "无权操作");
         }
-        return sysCustomerPersonService.adminList(customerId,positionId,UserContextHolder.getUserId());
+        return sysCustomerOperLogService.adminList(dto, true, false);
     }
 
 

+ 66 - 20
src/main/java/com/jtzx/crm/module/sys/service/SysCustomerDataPublicService.java

@@ -3,24 +3,23 @@ package com.jtzx.crm.module.sys.service;
 
 import cc.uncarbon.framework.core.context.UserContextHolder;
 import cc.uncarbon.framework.core.exception.BusinessException;
+import cc.uncarbon.framework.core.page.PageParam;
 import cc.uncarbon.framework.core.page.PageResult;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.text.CharSequenceUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.jtzx.crm.module.sys.entity.SysCustomerDataEntity;
+import com.jtzx.crm.module.sys.entity.SysCustomerFollowEntity;
 import com.jtzx.crm.module.sys.entity.SysParamBaseDataEntity;
 import com.jtzx.crm.module.sys.mapper.SysCustomerDataMapper;
+import com.jtzx.crm.module.sys.mapper.SysCustomerFollowMapper;
 import com.jtzx.crm.module.sys.mapper.SysParamBaseDataMapper;
-import com.jtzx.crm.module.sys.model.request.AdminSysCustomerDataInsertOrUpdateDTO;
-import com.jtzx.crm.module.sys.model.request.AdminSysCustomerDataPublicListDTO;
-import com.jtzx.crm.module.sys.model.request.AdminSysCustomerPersonInsertOrUpdateDTO;
-import com.jtzx.crm.module.sys.model.response.SysCustomerDataPublicBO;
-import com.jtzx.crm.module.sys.model.response.SysCustomerPersonBO;
-import com.jtzx.crm.module.sys.model.response.SysCustomerPublicSelectBO;
-import com.jtzx.crm.module.sys.model.response.SysCustomerSelectBO;
+import com.jtzx.crm.module.sys.model.request.*;
+import com.jtzx.crm.module.sys.model.response.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -48,10 +47,17 @@ public class SysCustomerDataPublicService {
 
     private final SysCustomerDataService sysCustomerDataService;
 
-    private final SysCustomerPersonService  sysCustomerPersonService;
+    private final SysCustomerPersonService sysCustomerPersonService;
+
+    private final SysCustomerDataFollowService sysCustomerDataFollowService;
+
+    private final SysCustomerFollowService sysCustomerFollowService;
+
+    private final SysCustomerOperLogService sysCustomerOperLogService;
 
     /**
      * 查询公海客户页面顶部筛选条件数据
+     *
      * @return
      */
     public SysCustomerPublicSelectBO queryHeadSelectData() {
@@ -97,11 +103,12 @@ public class SysCustomerDataPublicService {
 
     /**
      * 新增公海客户
+     *
      * @param dto
      */
     @Transactional(rollbackFor = Exception.class)
     public void adminInsertCustomerData(AdminSysCustomerDataInsertOrUpdateDTO dto) {
-        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("admin")) {
+        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("Admin")) {
             throw new BusinessException(400, "无权操作");
         }
         sysCustomerDataService.adminInsert(dto);
@@ -109,11 +116,12 @@ public class SysCustomerDataPublicService {
 
     /**
      * 公海客户修改
+     *
      * @param dto
      */
     @Transactional(rollbackFor = Exception.class)
     public void adminUpdateCustomerData(AdminSysCustomerDataInsertOrUpdateDTO dto) {
-        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("admin")) {
+        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("Admin")) {
             throw new BusinessException(400, "无权操作");
         }
         sysCustomerDataService.adminUpdate(dto);
@@ -121,11 +129,12 @@ public class SysCustomerDataPublicService {
 
     /**
      * 删除公海客户
+     *
      * @param id
      */
     @Transactional(rollbackFor = Exception.class)
     public void adminDeleteCustomerData(Long id) {
-        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("admin")) {
+        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("Admin")) {
             throw new BusinessException(400, "无权操作");
         }
         sysCustomerDataService.adminDelete(id);
@@ -133,6 +142,7 @@ public class SysCustomerDataPublicService {
 
     /**
      * 公海认领客户
+     *
      * @param customerId
      */
     @Transactional(rollbackFor = Exception.class)
@@ -141,28 +151,29 @@ public class SysCustomerDataPublicService {
     }
 
 
-
     /**
      * 公海添加客户联系人
+     *
      * @param dto
      * @return
      */
     @Transactional(rollbackFor = Exception.class)
-    public Long adminInsertCustomerPerson(AdminSysCustomerPersonInsertOrUpdateDTO dto) {
-        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("admin")) {
+    public void adminInsertCustomerPerson(AdminSysCustomerPersonInsertOrUpdateDTO dto) {
+        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("Admin")) {
             throw new BusinessException(400, "无权操作");
         }
-       return sysCustomerPersonService.adminInsert(dto);
+        sysCustomerPersonService.adminInsert(dto);
     }
 
 
     /**
      * 公海修改客户联系人
+     *
      * @param dto
      */
     @Transactional(rollbackFor = Exception.class)
     public void adminUpdateCustomerPerson(AdminSysCustomerPersonInsertOrUpdateDTO dto) {
-        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("admin")) {
+        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("Admin")) {
             throw new BusinessException(400, "无权操作");
         }
         sysCustomerPersonService.adminUpdate(dto);
@@ -170,11 +181,12 @@ public class SysCustomerDataPublicService {
 
     /**
      * 公海删除联系人
+     *
      * @param id
      */
     @Transactional(rollbackFor = Exception.class)
     public void adminDeleteCustomerPerson(Long id) {
-        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("admin")) {
+        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("Admin")) {
             throw new BusinessException(400, "无权操作");
         }
         sysCustomerPersonService.adminDelete(id);
@@ -183,11 +195,45 @@ public class SysCustomerDataPublicService {
     /**
      * 查询公海客户联系人
      */
-    public List<SysCustomerPersonBO> adminListCustomerPerson(Long customerId, Long positionId) {
-        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("admin")) {
+    public List<SysCustomerPersonBO> adminListCustomerPerson(CustomerPersonReqDTO dto) {
+        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("Admin")) {
+            throw new BusinessException(400, "无权操作");
+        }
+        return sysCustomerPersonService.adminList(dto);
+    }
+
+
+    /**
+     * 查询公海客户详情的信息总览
+     *
+     * @param dto
+     */
+    public SysCustomerDetailBO queryCustomerDetail(AdminSysCustomerFollowReqDTO dto) {
+        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("Admin")) {
+            throw new BusinessException(400, "无权操作");
+        }
+        SysCustomerDetailBO detailBO = SysCustomerDetailBO.builder().build();
+        //顶部筛选条件数据
+        SysCustomerFollowHistorySelectBO publicCustomerSelectData = sysCustomerDataFollowService.queryCustomerFollowSelectCommonData(dto.getCustomerId(), null);
+        detailBO.setSelectData(publicCustomerSelectData);
+        //客户详情信息
+        PageResult<SysCustomerFollowListBO> dataPageList = sysCustomerDataFollowService.queryCustomerFollowDataCommonByPage(dto);
+        detailBO.setDataPageList(dataPageList);
+        //信息总览
+        detailBO.setProductOverviewData(sysCustomerFollowService.queryProductOverViewData(dto.getCustomerId()));
+        //跟进记录总览
+        detailBO.setFollowOverViewData(sysCustomerFollowService.handleCustomerFollowOverViewData(dto.getCustomerId(), null));
+        return detailBO;
+    }
+
+    /**
+     * 操作日志列表查询
+     */
+    public SysCustomerOperLogDataBO queryOperLogData(AdminSysCustomerOperLogListDTO dto) {
+        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("Admin")) {
             throw new BusinessException(400, "无权操作");
         }
-       return sysCustomerPersonService.adminList(customerId,positionId,null);
+        return sysCustomerOperLogService.adminList(dto, false, false);
     }
 
 

+ 147 - 15
src/main/java/com/jtzx/crm/module/sys/service/SysCustomerDataService.java

@@ -4,23 +4,23 @@ import cc.uncarbon.framework.core.context.UserContextHolder;
 import cc.uncarbon.framework.core.exception.BusinessException;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.jtzx.crm.module.sys.entity.SysCustomerDataEntity;
-import com.jtzx.crm.module.sys.entity.SysCustomerFollowEntity;
-import com.jtzx.crm.module.sys.entity.SysCustomerOperLogEntity;
-import com.jtzx.crm.module.sys.entity.SysUserGroupRelationEntity;
-import com.jtzx.crm.module.sys.mapper.SysCustomerDataMapper;
-import com.jtzx.crm.module.sys.mapper.SysCustomerFollowMapper;
-import com.jtzx.crm.module.sys.mapper.SysCustomerOperLogMapper;
-import com.jtzx.crm.module.sys.mapper.SysUserGroupRelationMapper;
+import com.google.common.collect.Lists;
+import com.jtzx.crm.module.sys.entity.*;
+import com.jtzx.crm.module.sys.mapper.*;
 import com.jtzx.crm.module.sys.model.request.AdminSysCustomerDataInsertOrUpdateDTO;
+import com.jtzx.crm.module.sys.model.request.TransferUserReqDTO;
 import com.jtzx.crm.module.sys.model.response.SysCustomerDataBO;
+import com.jtzx.crm.module.sys.model.response.TransferUserReqBO;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.time.LocalDateTime;
+import java.util.Comparator;
+import java.util.List;
 
 
 /**
@@ -39,6 +39,10 @@ public class SysCustomerDataService {
 
     private final SysCustomerFollowMapper sysCustomerFollowMapper;
 
+    private final SysGroupMapper sysGroupMapper;
+
+    private final SysUserMapper sysUserMapper;
+
 
     /**
      * 根据 ID 取详情
@@ -170,6 +174,7 @@ public class SysCustomerDataService {
 
     /**
      * 认领操作
+     *
      * @param customerId
      */
     @Transactional(rollbackFor = Exception.class)
@@ -190,7 +195,7 @@ public class SysCustomerDataService {
                         .eq(SysUserGroupRelationEntity::getCityId, sysCustomerDataEntity.getCityId())
                         .last("limit 1")
         );
-        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("admin")) {
+        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("Admin")) {
             if (userGroupRelation == null) {
                 throw new BusinessException(400, "无权操作");
             }
@@ -224,6 +229,7 @@ public class SysCustomerDataService {
 
     /**
      * 客户退回公海
+     *
      * @param customerId
      */
     @Transactional(rollbackFor = Exception.class)
@@ -231,14 +237,14 @@ public class SysCustomerDataService {
         //先查询有没有赢单
         SysCustomerDataEntity sysCustomerDataEntity = sysCustomerDataMapper.selectById(customerId);
         if (sysCustomerDataEntity == null) {
-            throw new BusinessException(400,"客户不存在");
+            throw new BusinessException(400, "客户不存在");
         }
-        if(sysCustomerDataEntity.getSuccessStatus()==1){
-            throw new BusinessException(400,"客户已赢单,不能退回公海");
+        if (sysCustomerDataEntity.getSuccessStatus() == 1) {
+            throw new BusinessException(400, "客户已赢单,不能退回公海");
         }
-        if(CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("admin")){
-            if(!sysCustomerDataEntity.getClaimUserId().equals(UserContextHolder.getUserId())){
-                throw new BusinessException(400,"认领人不正确,无权操作");
+        if (CollUtil.isEmpty(UserContextHolder.getUserContext().getRoles()) || !UserContextHolder.getUserContext().getRoles().contains("Admin")) {
+            if (!sysCustomerDataEntity.getClaimUserId().equals(UserContextHolder.getUserId())) {
+                throw new BusinessException(400, "认领人不正确,无权操作");
             }
         }
         sysCustomerDataMapper.returnCustomerData(customerId);
@@ -260,6 +266,132 @@ public class SysCustomerDataService {
         sysCustomerOperLogMapper.insert(logEntity);
     }
 
+
+    /**
+     * 转让操作
+     *
+     * @param dto
+     */
+    public void transferUser(TransferUserReqDTO dto) {
+        SysCustomerDataEntity sysCustomerDataEntity = sysCustomerDataMapper.selectById(dto.getCustomerId());
+        if (sysCustomerDataEntity == null) {
+            throw new BusinessException(400, "客户信息不存在");
+        }
+        SysUserEntity sysUserEntity = sysUserMapper.selectById(dto.getUserId());
+        if (sysUserEntity == null) {
+            throw new BusinessException(400, "用户不存在");
+        }
+
+        SysUserGroupRelationEntity groupRelationEntity =
+                sysUserGroupRelationMapper.selectOne(
+                        new LambdaQueryWrapper<>(SysUserGroupRelationEntity.class)
+                                .select(SysUserGroupRelationEntity::getUserId,
+                                        SysUserGroupRelationEntity::getGroupId)
+                                .eq(SysUserGroupRelationEntity::getProvinceId, sysCustomerDataEntity.getProvinceId())
+                                .eq(SysUserGroupRelationEntity::getCityId, sysCustomerDataEntity.getCityId())
+                                .eq(SysUserGroupRelationEntity::getUserId, dto.getUserId())
+                );
+        if (groupRelationEntity == null) {
+            throw new BusinessException(400, "用户未分配小组");
+        }
+        sysCustomerDataEntity.setClaimDatetime(LocalDateTime.now());
+        sysCustomerDataEntity.setClaimUserGroupId(groupRelationEntity.getGroupId());
+        sysCustomerDataEntity.setClaimUserName(sysUserEntity.getUserName());
+        sysCustomerDataEntity.setClaimUserId(sysUserEntity.getId());
+        if(sysCustomerDataEntity.getSuccessStatus()==null){
+            sysCustomerDataEntity.setSuccessStatus(0);
+        }
+        if (sysCustomerDataEntity.getSuccessStatus() == 0) {
+            if (sysCustomerDataEntity.getSuccessUserId() != null || StrUtil.isNotEmpty(sysCustomerDataEntity.getSuccessUserName())) {
+                sysCustomerDataMapper.resetSuccessData(sysCustomerDataEntity.getId());
+            }
+        } else {
+            sysCustomerDataEntity.setSuccessUserId(sysUserEntity.getId());
+            sysCustomerDataEntity.setSuccessUserName(sysUserEntity.getUserName());
+        }
+        sysCustomerDataMapper.updateById(sysCustomerDataEntity);
+    }
+
+    /**
+     * 查询转让人信息  ,转让时需要先查询能够接受当前这个客户的受让人信息列表
+     *
+     * @param customerId
+     * @return
+     */
+    public List<TransferUserReqBO> queryTransferUser(Long customerId) {
+        SysCustomerDataEntity sysCustomerDataEntity = sysCustomerDataMapper.selectById(customerId);
+        if (sysCustomerDataEntity == null) {
+            throw new BusinessException(400, "客户信息不存在");
+        }
+
+        List<TransferUserReqBO> resultData = Lists.newArrayList();
+        List<SysUserGroupRelationEntity> groupRelationEntityList =
+                sysUserGroupRelationMapper.selectList(
+                        new LambdaQueryWrapper<>(SysUserGroupRelationEntity.class)
+                                .select(SysUserGroupRelationEntity::getUserId,
+                                        SysUserGroupRelationEntity::getCreatedAt,
+                                        SysUserGroupRelationEntity::getGroupId)
+                                .eq(SysUserGroupRelationEntity::getProvinceId, sysCustomerDataEntity.getProvinceId())
+                                .eq(SysUserGroupRelationEntity::getCityId, sysCustomerDataEntity.getCityId())
+                                .ne(SysUserGroupRelationEntity::getUserId, UserContextHolder.getUserId())
+                );
+        if (CollUtil.isEmpty(groupRelationEntityList)) {
+            return resultData;
+        }
+
+        List<SysUserEntity> sysUserEntityList =
+                sysUserMapper.selectList(
+                        new LambdaQueryWrapper<>(SysUserEntity.class)
+                                .select(
+                                        SysUserEntity::getId,
+                                        SysUserEntity::getUserName
+                                )
+                                .in(SysUserEntity::getId, groupRelationEntityList.stream()
+                                        .map(SysUserGroupRelationEntity::getUserId).distinct().toList())
+                                .eq(SysUserEntity::getStatus, 1)
+
+                );
+        if (CollUtil.isEmpty(sysUserEntityList)) {
+            return resultData;
+        }
+
+
+        List<SysGroupEntity> groupEntityList =
+                sysGroupMapper.selectList(
+                        new LambdaQueryWrapper<>(SysGroupEntity.class)
+                                .select(
+                                        SysGroupEntity::getId,
+                                        SysGroupEntity::getTitle,
+                                        SysGroupEntity::getSortCode
+
+                                )
+                                .in(SysGroupEntity::getId, groupRelationEntityList.stream()
+                                        .map(SysUserGroupRelationEntity::getGroupId).distinct().toList())
+                                .orderByAsc(SysGroupEntity::getSortCode)
+                );
+        if (CollUtil.isEmpty(groupEntityList)) {
+            return resultData;
+        }
+        groupEntityList.stream()
+                .sorted(Comparator.comparing(SysGroupEntity::getSortCode))
+                .forEach(e -> groupRelationEntityList.stream()
+                        .filter(x -> x.getGroupId().equals(e.getId()))
+                        .sorted(Comparator.comparing(SysUserGroupRelationEntity::getCreatedAt))
+                        .forEach(u -> sysUserEntityList.stream()
+                                .filter(x -> x.getId().equals(u.getUserId()))
+                                .findFirst()
+                                .ifPresent(a -> {
+                                    TransferUserReqBO bo = TransferUserReqBO.builder().build();
+                                    bo.setCustomerId(customerId);
+                                    bo.setUserId(a.getId());
+                                    bo.setUserName(a.getUserName());
+                                    bo.setGroupId(u.getGroupId());
+                                    resultData.add(bo);
+                                })));
+        return resultData;
+    }
+
+
     /*
     ----------------------------------------------------------------
                         私有方法 private methods

+ 88 - 149
src/main/java/com/jtzx/crm/module/sys/service/SysCustomerFollowAuditService.java

@@ -1,23 +1,21 @@
 package com.jtzx.crm.module.sys.service;
 
-import cc.uncarbon.framework.core.constant.HelioConstant;
+import cc.uncarbon.framework.core.context.UserContextHolder;
 import cc.uncarbon.framework.core.exception.BusinessException;
-import cc.uncarbon.framework.core.page.PageParam;
-import cc.uncarbon.framework.core.page.PageResult;
-import com.jtzx.crm.module.sys.entity.SysCustomerFollowAuditEntity;
-import com.jtzx.crm.module.sys.mapper.SysCustomerFollowAuditMapper;
-import com.jtzx.crm.module.sys.model.request.AdminSysCustomerFollowAuditInsertOrUpdateDTO;
-import com.jtzx.crm.module.sys.model.request.AdminSysCustomerFollowAuditListDTO;
-import com.jtzx.crm.module.sys.model.response.SysCustomerFollowAuditBO;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.text.CharSequenceUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.google.common.collect.Lists;
+import com.jtzx.crm.module.sys.entity.SysCustomerDataEntity;
+import com.jtzx.crm.module.sys.entity.SysCustomerFollowAuditEntity;
+import com.jtzx.crm.module.sys.mapper.SysCustomerDataMapper;
+import com.jtzx.crm.module.sys.mapper.SysCustomerFollowAuditMapper;
+import com.jtzx.crm.module.sys.model.response.SysCustomerFollowAuditBO;
+import com.jtzx.crm.module.sys.model.response.SysCustomerFollowAuditDataBO;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 
 import java.util.*;
 
@@ -32,124 +30,101 @@ public class SysCustomerFollowAuditService {
 
     private final SysCustomerFollowAuditMapper sysCustomerFollowAuditMapper;
 
+    private final SysCustomerDataMapper sysCustomerDataMapper;
 
     /**
-     * 后台管理-分页列表
+     * 赢单审核申请列表查询
      */
-    public PageResult<SysCustomerFollowAuditBO> adminList(PageParam pageParam, AdminSysCustomerFollowAuditListDTO dto) {
-        Page<SysCustomerFollowAuditEntity> entityPage = sysCustomerFollowAuditMapper.selectPage(
-                new Page<>(pageParam.getPageNum(), pageParam.getPageSize()),
+    public SysCustomerFollowAuditDataBO adminList(Integer auditStatus) {
+
+        if (!UserContextHolder.getUserContext().getRoles().contains("Admin")) {
+            throw new BusinessException(403, "无权操作");
+        }
+        if(!Arrays.asList(0,1,2).contains(auditStatus)){
+            throw new BusinessException(400, "审核参数错误");
+        }
+        SysCustomerFollowAuditDataBO resultData = SysCustomerFollowAuditDataBO.builder().build();
+        resultData.setAudit0(0);
+        resultData.setAudit1(0);
+        resultData.setAudit2(0);
+        List<SysCustomerFollowAuditEntity> entityPage = sysCustomerFollowAuditMapper.selectList(
                 new QueryWrapper<SysCustomerFollowAuditEntity>()
                         .lambda()
-                        // 认领人(跟进)id
-                        .eq(Objects.nonNull(dto.getClaimUserId()), SysCustomerFollowAuditEntity::getClaimUserId, dto.getClaimUserId())
-                        // 审核人id
-                        .like(CharSequenceUtil.isNotBlank(dto.getClaimUserName()), SysCustomerFollowAuditEntity::getClaimUserName, CharSequenceUtil.cleanBlank(dto.getClaimUserName()))
-                        // 认领人员所在的项目组id
-                        .eq(Objects.nonNull(dto.getClaimUserGroupId()), SysCustomerFollowAuditEntity::getClaimUserGroupId, dto.getClaimUserGroupId())
-                        // 跟进时间
-                        .eq(Objects.nonNull(dto.getClaimDatetime()), SysCustomerFollowAuditEntity::getClaimDatetime, dto.getClaimDatetime())
-                        // 客户表主id
-                        .eq(Objects.nonNull(dto.getCustomerId()), SysCustomerFollowAuditEntity::getCustomerId, dto.getCustomerId())
-                        // 客户名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getCustomerName()), SysCustomerFollowAuditEntity::getCustomerName, CharSequenceUtil.cleanBlank(dto.getCustomerName()))
-                        // 跟进状态id,赢单状态id固定-37,方案演示id固定-33
-                        .eq(Objects.nonNull(dto.getFollowId()), SysCustomerFollowAuditEntity::getFollowId, dto.getFollowId())
-                        // 跟进状态的名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getFollowName()), SysCustomerFollowAuditEntity::getFollowName, CharSequenceUtil.cleanBlank(dto.getFollowName()))
-                        // 联系人id(customer_person表主id)
-                        .eq(Objects.nonNull(dto.getCustomerPersonId()), SysCustomerFollowAuditEntity::getCustomerPersonId, dto.getCustomerPersonId())
-                        // 联系人名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getCustomerPersonName()), SysCustomerFollowAuditEntity::getCustomerPersonName, CharSequenceUtil.cleanBlank(dto.getCustomerPersonName()))
-                        // 职务id(param_base_data表主id)
-                        .eq(Objects.nonNull(dto.getPositionId()), SysCustomerFollowAuditEntity::getPositionId, dto.getPositionId())
-                        // 职务名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getPositionName()), SysCustomerFollowAuditEntity::getPositionName, CharSequenceUtil.cleanBlank(dto.getPositionName()))
-                        // 跟进内容
-                        .like(CharSequenceUtil.isNotBlank(dto.getFollowContent()), SysCustomerFollowAuditEntity::getFollowContent, CharSequenceUtil.cleanBlank(dto.getFollowContent()))
-                        // 产品id(param_base_data表主id)
-                        .eq(Objects.nonNull(dto.getProductId()), SysCustomerFollowAuditEntity::getProductId, dto.getProductId())
-                        // 产品名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getProductName()), SysCustomerFollowAuditEntity::getProductName, CharSequenceUtil.cleanBlank(dto.getProductName()))
-                        // 审核状态:0-待审核,1-已通过,2-已驳回
-                        .eq(Objects.nonNull(dto.getAuditStatus()), SysCustomerFollowAuditEntity::getAuditStatus, dto.getAuditStatus())
-                        // 审核人id
-                        .eq(Objects.nonNull(dto.getAuditUserId()), SysCustomerFollowAuditEntity::getAuditUserId, dto.getAuditUserId())
-                        // 审核人名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getAuditUserName()), SysCustomerFollowAuditEntity::getAuditUserName, CharSequenceUtil.cleanBlank(dto.getAuditUserName()))
-                        // 时间区间
-                        .between(Objects.nonNull(dto.getBeginAt()) && Objects.nonNull(dto.getEndAt()), SysCustomerFollowAuditEntity::getCreatedAt, dto.getBeginAt(), dto.getEndAt())
+                        .eq(SysCustomerFollowAuditEntity::getAuditUserId, UserContextHolder.getUserId())
                         // 排序
                         .orderByDesc(SysCustomerFollowAuditEntity::getCreatedAt)
         );
-
-        return this.entityPage2BOPage(entityPage);
-    }
-
-    /**
-     * 根据 ID 取详情
-     *
-     * @param id 主键ID
-     * @return null or BO
-     */
-    public SysCustomerFollowAuditBO getOneById(Long id) {
-        return this.getOneById(id, false);
+        if (auditStatus == null) {
+            auditStatus = 0;
+        }
+        List<SysCustomerFollowAuditBO> dataList = Lists.newArrayList();
+        if (CollUtil.isNotEmpty(entityPage)) {
+            resultData.setAudit0(entityPage.stream().filter(e -> e.getAuditStatus() == 0).toList().size());
+            resultData.setAudit1(entityPage.stream().filter(e -> e.getAuditStatus() == 1).toList().size());
+            resultData.setAudit2(entityPage.stream().filter(e -> e.getAuditStatus() == 2).toList().size());
+
+            Integer finalAuditStatus = auditStatus;
+            List<SysCustomerFollowAuditEntity> list = entityPage.stream()
+                    .filter(e -> Objects.equals(e.getAuditStatus(), finalAuditStatus))
+                    .toList();
+            List<SysCustomerFollowAuditBO> boList = this.entityList2BOs(list);
+            if (CollUtil.isNotEmpty(boList)) {
+                dataList.addAll(boList);
+            }
+        }
+        resultData.setAuditData(dataList);
+        return resultData;
     }
 
     /**
-     * 根据 ID 取详情
-     *
-     * @param id 主键ID
-     * @param throwIfInvalidId 是否在 ID 无效时抛出异常
-     * @return null or BO
+     * 赢单审核通过
+     * auditStatus 1-通过,2-不通过
+     * @param id
      */
-    public SysCustomerFollowAuditBO getOneById(Long id, boolean throwIfInvalidId) throws BusinessException {
+    public void auditSuccess(Long id, Integer auditStatus) {
+        if(!Arrays.asList(1,2).contains(auditStatus)){
+            throw new BusinessException(400, "审核参数错误");
+        }
+        if (!UserContextHolder.getUserContext().getRoles().contains("Admin")) {
+            throw new BusinessException(403, "无权操作");
+        }
         SysCustomerFollowAuditEntity entity = sysCustomerFollowAuditMapper.selectById(id);
-        if (throwIfInvalidId && entity == null) {
-            throw new BusinessException(400, "无效赢单跟进审核信息ID");
+        if (entity == null) {
+            throw new BusinessException(400, "赢单跟进审核信息不存在");
         }
 
-        return this.entity2BO(entity);
-    }
-
-    /**
-     * 后台管理-新增
-     */
-    @Transactional(rollbackFor = Exception.class)
-    public Long adminInsert(AdminSysCustomerFollowAuditInsertOrUpdateDTO dto) {
-        log.info("[后台管理-赢单跟进审核信息-新增] >> DTO={}", dto);
-        this.checkExistence(dto);
-
-        dto.setId(null);
-        SysCustomerFollowAuditEntity entity = new SysCustomerFollowAuditEntity();
-        BeanUtil.copyProperties(dto, entity);
-
-        sysCustomerFollowAuditMapper.insert(entity);
-
-        return entity.getId();
-    }
-
-    /**
-     * 后台管理-编辑
-     */
-    @Transactional(rollbackFor = Exception.class)
-    public void adminUpdate(AdminSysCustomerFollowAuditInsertOrUpdateDTO dto) {
-        log.info("[后台管理-赢单跟进审核信息-编辑] >> DTO={}", dto);
-        this.checkExistence(dto);
-
-        SysCustomerFollowAuditEntity entity = new SysCustomerFollowAuditEntity();
-        BeanUtil.copyProperties(dto, entity);
+        SysCustomerDataEntity sysCustomerDataEntity = sysCustomerDataMapper.selectById(entity.getCustomerId());
+        if (sysCustomerDataEntity == null) {
+            throw new BusinessException(400, "客户数据不存在");
+        }
 
         sysCustomerFollowAuditMapper.updateById(entity);
-    }
+        List<SysCustomerFollowAuditEntity> sysCustomerFollowAuditEntities =
+                sysCustomerFollowAuditMapper.selectList(
+                        new LambdaQueryWrapper<>(SysCustomerFollowAuditEntity.class)
+                                .select(
+                                        SysCustomerFollowAuditEntity::getId
+                                )
+                                .eq(SysCustomerFollowAuditEntity::getCustomerId, entity.getCustomerId())
+                );
+
+        if (CollUtil.isNotEmpty(sysCustomerFollowAuditEntities)) {
+            sysCustomerFollowAuditEntities.forEach(e -> {
+                e.setAuditStatus(auditStatus);
+                e.setAuditUserId(UserContextHolder.getUserId());
+                e.setAuditUserName(UserContextHolder.getUserName());
+                sysCustomerFollowAuditMapper.updateById(e);
+            });
+        }
+
+        // 审核通过,设置客户数据表的赢单信息,以及赢单审核信息
+        if (auditStatus == 1) {
+            sysCustomerDataEntity.setSuccessStatus(1);
+            sysCustomerDataEntity.setSuccessUserId(entity.getClaimUserId());
+            sysCustomerDataEntity.setSuccessUserName(entity.getClaimUserName());
+            sysCustomerDataMapper.updateById(sysCustomerDataEntity);
+        }
 
-    /**
-     * 后台管理-删除
-     */
-    @Transactional(rollbackFor = Exception.class)
-    public void adminDelete(Collection<Long> ids) {
-        log.info("[后台管理-赢单跟进审核信息-删除] >> ids={}", ids);
-        sysCustomerFollowAuditMapper.deleteByIds(ids);
     }
 
 
@@ -174,7 +149,7 @@ public class SysCustomerFollowAuditService {
         BeanUtil.copyProperties(entity, bo);
 
         // 可以在此处为BO填充字段
-
+        bo.setId(entity.getId());
         return bo;
     }
 
@@ -192,47 +167,11 @@ public class SysCustomerFollowAuditService {
         // 深拷贝
         List<SysCustomerFollowAuditBO> ret = new ArrayList<>(entityList.size());
         entityList.forEach(
-            entity -> ret.add(this.entity2BO(entity))
+                entity -> ret.add(this.entity2BO(entity))
         );
 
         return ret;
     }
 
-    /**
-     * 实体分页转 BO 分页
-     *
-     * @param entityPage 实体分页
-     * @return BO 分页
-     */
-    private PageResult<SysCustomerFollowAuditBO> entityPage2BOPage(Page<SysCustomerFollowAuditEntity> entityPage) {
-        return new PageResult<SysCustomerFollowAuditBO>()
-            .setCurrent(entityPage.getCurrent())
-            .setSize(entityPage.getSize())
-            .setTotal(entityPage.getTotal())
-            .setRecords(this.entityList2BOs(entityPage.getRecords()));
-    }
-
-    /**
-     * 检查是否已存在同名数据
-     *
-     * @param dto DTO
-     */
-    private void checkExistence(AdminSysCustomerFollowAuditInsertOrUpdateDTO dto) {
-        /*
-        可以根据自己业务需要,解禁这段代码,修改判断条件和文案
-
-        SysCustomerFollowAuditEntity existingEntity = sysCustomerFollowAuditMapper.selectOne(
-                new QueryWrapper<SysCustomerFollowAuditEntity>()
-                        .lambda()
-                        .select(SysCustomerFollowAuditEntity::getId)
-                        .eq(SysCustomerFollowAuditEntity::getTitle, dto.getTitle())
-                        .last(HelioConstant.CRUD.SQL_LIMIT_1)
-        );
-
-        if (existingEntity != null && !existingEntity.getId().equals(dto.getId())) {
-            throw new BusinessException(400, "已存在相同赢单跟进审核信息,请重新输入");
-        }
-        */
-    }
 
 }

+ 384 - 168
src/main/java/com/jtzx/crm/module/sys/service/SysCustomerFollowService.java

@@ -1,25 +1,30 @@
 package com.jtzx.crm.module.sys.service;
 
-import cc.uncarbon.framework.core.constant.HelioConstant;
-import cc.uncarbon.framework.core.exception.BusinessException;
-import cc.uncarbon.framework.core.page.PageParam;
-import cc.uncarbon.framework.core.page.PageResult;
-import com.jtzx.crm.module.sys.entity.SysCustomerFollowEntity;
-import com.jtzx.crm.module.sys.mapper.SysCustomerFollowMapper;
-import com.jtzx.crm.module.sys.model.request.AdminSysCustomerFollowInsertOrUpdateDTO;
-import com.jtzx.crm.module.sys.model.request.AdminSysCustomerFollowListDTO;
-import com.jtzx.crm.module.sys.model.response.SysCustomerFollowBO;
+import cc.uncarbon.framework.core.context.UserContextHolder;
+import cc.uncarbon.framework.crud.entity.HelioBaseEntity;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.text.CharSequenceUtil;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.google.common.collect.Lists;
+import com.jtzx.crm.module.sys.entity.*;
+import com.jtzx.crm.module.sys.mapper.*;
+import com.jtzx.crm.module.sys.model.request.AdminSysCustomerFollowInsertOrUpdateDTO;
+import com.jtzx.crm.module.sys.model.response.CustomerFollowOverViewBO;
+import com.jtzx.crm.module.sys.model.response.CustomerProductBO;
+import com.jtzx.crm.module.sys.model.response.CustomerProductOverViewBO;
+import com.jtzx.crm.module.sys.model.response.SysCustomerFollowDataBO;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.*;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
 
 
 /**
@@ -32,211 +37,422 @@ public class SysCustomerFollowService {
 
     private final SysCustomerFollowMapper sysCustomerFollowMapper;
 
+    private final SysCustomerDataMapper sysCustomerDataMapper;
 
-    /**
-     * 后台管理-分页列表
-     */
-    public PageResult<SysCustomerFollowBO> adminList(PageParam pageParam, AdminSysCustomerFollowListDTO dto) {
-        Page<SysCustomerFollowEntity> entityPage = sysCustomerFollowMapper.selectPage(
-                new Page<>(pageParam.getPageNum(), pageParam.getPageSize()),
-                new QueryWrapper<SysCustomerFollowEntity>()
-                        .lambda()
-                        // 认领人(跟进)id
-                        .eq(Objects.nonNull(dto.getClaimUserId()), SysCustomerFollowEntity::getClaimUserId, dto.getClaimUserId())
-                        // 认领人(跟进)名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getClaimUserName()), SysCustomerFollowEntity::getClaimUserName, CharSequenceUtil.cleanBlank(dto.getClaimUserName()))
-                        // 认领人员所在的项目组id
-                        .eq(Objects.nonNull(dto.getClaimUserGroupId()), SysCustomerFollowEntity::getClaimUserGroupId, dto.getClaimUserGroupId())
-                        // 跟进时间
-                        .eq(Objects.nonNull(dto.getClaimDatetime()), SysCustomerFollowEntity::getClaimDatetime, dto.getClaimDatetime())
-                        // 客户表主id
-                        .eq(Objects.nonNull(dto.getCustomerId()), SysCustomerFollowEntity::getCustomerId, dto.getCustomerId())
-                        // 客户名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getCustomerName()), SysCustomerFollowEntity::getCustomerName, CharSequenceUtil.cleanBlank(dto.getCustomerName()))
-                        // 产品id(param_base_data表主id)
-                        .eq(Objects.nonNull(dto.getProductId()), SysCustomerFollowEntity::getProductId, dto.getProductId())
-                        // 产品名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getProductName()), SysCustomerFollowEntity::getProductName, CharSequenceUtil.cleanBlank(dto.getProductName()))
-                        // 跟进状态id,赢单状态id固定-37,方案演示id固定-33
-                        .eq(Objects.nonNull(dto.getFollowId()), SysCustomerFollowEntity::getFollowId, dto.getFollowId())
-                        // 跟进状态的名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getFollowName()), SysCustomerFollowEntity::getFollowName, CharSequenceUtil.cleanBlank(dto.getFollowName()))
-                        // 是否赢单,0-否,1-是
-                        .eq(Objects.nonNull(dto.getSuccessStatus()), SysCustomerFollowEntity::getSuccessStatus, dto.getSuccessStatus())
-                        // 联系人id(customer_person表主id)
-                        .eq(Objects.nonNull(dto.getCustomerPersonId()), SysCustomerFollowEntity::getCustomerPersonId, dto.getCustomerPersonId())
-                        // 联系人名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getCustomerPersonName()), SysCustomerFollowEntity::getCustomerPersonName, CharSequenceUtil.cleanBlank(dto.getCustomerPersonName()))
-                        // 职务id(param_base_data表主id)
-                        .eq(Objects.nonNull(dto.getPositionId()), SysCustomerFollowEntity::getPositionId, dto.getPositionId())
-                        // 职务名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getPositionName()), SysCustomerFollowEntity::getPositionName, CharSequenceUtil.cleanBlank(dto.getPositionName()))
-                        // 跟进内容
-                        .like(CharSequenceUtil.isNotBlank(dto.getFollowContent()), SysCustomerFollowEntity::getFollowContent, CharSequenceUtil.cleanBlank(dto.getFollowContent()))
-                        // 预约待办类型,0-预约,1-待办,(follow_id=33时为预约,其它为待办),这个数据可以为null
-                        .eq(Objects.nonNull(dto.getOrderType()), SysCustomerFollowEntity::getOrderType, dto.getOrderType())
-                        // 待办时间
-                        .eq(Objects.nonNull(dto.getOrderDatetime()), SysCustomerFollowEntity::getOrderDatetime, dto.getOrderDatetime())
-                        // 预约,待办取消状态,0-未取消,1-已取消(预约的取消需要填写取消原因,待办的取消是一个开关,不需要填写原因)
-                        .eq(Objects.nonNull(dto.getOrderStatus()), SysCustomerFollowEntity::getOrderStatus, dto.getOrderStatus())
-                        // 预约取消原因
-                        .like(CharSequenceUtil.isNotBlank(dto.getCancelRemark()), SysCustomerFollowEntity::getCancelRemark, CharSequenceUtil.cleanBlank(dto.getCancelRemark()))
-                        // 时间区间
-                        .between(Objects.nonNull(dto.getBeginAt()) && Objects.nonNull(dto.getEndAt()), SysCustomerFollowEntity::getCreatedAt, dto.getBeginAt(), dto.getEndAt())
-                        // 排序
-                        .orderByDesc(SysCustomerFollowEntity::getCreatedAt)
-        );
-
-        return this.entityPage2BOPage(entityPage);
-    }
+    private final SysCustomerPersonMapper sysCustomerPersonMapper;
 
-    /**
-     * 根据 ID 取详情
-     *
-     * @param id 主键ID
-     * @return null or BO
-     */
-    public SysCustomerFollowBO getOneById(Long id) {
-        return this.getOneById(id, false);
-    }
+    private final SysParamBaseDataMapper sysParamBaseDataMapper;
 
-    /**
-     * 根据 ID 取详情
-     *
-     * @param id 主键ID
-     * @param throwIfInvalidId 是否在 ID 无效时抛出异常
-     * @return null or BO
-     */
-    public SysCustomerFollowBO getOneById(Long id, boolean throwIfInvalidId) throws BusinessException {
-        SysCustomerFollowEntity entity = sysCustomerFollowMapper.selectById(id);
-        if (throwIfInvalidId && entity == null) {
-            throw new BusinessException(400, "无效客户跟进数据信息ID");
-        }
+    private final SysCustomerFollowAuditMapper sysCustomerFollowAuditMapper;
+
+    private final SysUserRoleRelationMapper sysUserRoleRelationMapper;
+
+    private final SysUserMapper sysUserMapper;
 
-        return this.entity2BO(entity);
-    }
 
     /**
      * 后台管理-新增
      */
     @Transactional(rollbackFor = Exception.class)
-    public Long adminInsert(AdminSysCustomerFollowInsertOrUpdateDTO dto) {
+    public void adminInsert(AdminSysCustomerFollowInsertOrUpdateDTO dto) {
         log.info("[后台管理-客户跟进数据信息-新增] >> DTO={}", dto);
-        this.checkExistence(dto);
-
         dto.setId(null);
+        // 参数校验
+        this.checkParam(dto);
+        // 处理参数
+        this.handleParams(dto);
         SysCustomerFollowEntity entity = new SysCustomerFollowEntity();
         BeanUtil.copyProperties(dto, entity);
-
         sysCustomerFollowMapper.insert(entity);
-
-        return entity.getId();
+        if (dto.getOrderType() != null && dto.getOrderType() == 0 && dto.getOrderDatetime() != null) {
+            entity.setOrderStatus(0);
+            entity.setOrderDatetime(dto.getOrderDatetime());
+            if (!dto.getOrderDatetime().isAfter(LocalDateTime.now())) {
+                entity.setOrderStatus(1);
+            }
+            sysCustomerFollowMapper.updateById(entity);
+            if (dto.getOrderDatetime().isAfter(LocalDateTime.now())) {
+                //TODO 发送定时任务,时间到之后改为已结束
+            }
+        }
     }
 
+
     /**
-     * 后台管理-编辑
+     * 处理跟进总览
+     *
+     * @param customerId
+     * @return
      */
-    @Transactional(rollbackFor = Exception.class)
-    public void adminUpdate(AdminSysCustomerFollowInsertOrUpdateDTO dto) {
-        log.info("[后台管理-客户跟进数据信息-编辑] >> DTO={}", dto);
-        this.checkExistence(dto);
-
-        SysCustomerFollowEntity entity = new SysCustomerFollowEntity();
-        BeanUtil.copyProperties(dto, entity);
+    public CustomerFollowOverViewBO handleCustomerFollowOverViewData(Long customerId, Long userId) {
+        CustomerFollowOverViewBO customerFollowOverViewBO = CustomerFollowOverViewBO.builder().build();
+        customerFollowOverViewBO.setHistoryProductCount(0);
+        customerFollowOverViewBO.setHistoryPersonCount(0);
+        customerFollowOverViewBO.setHistoryFollowCount(0);
+        customerFollowOverViewBO.setSuccessCount(0);
+        customerFollowOverViewBO.setFailedCount(0);
+        List<SysCustomerFollowEntity> followEntityList =
+                sysCustomerFollowMapper.selectList(
+                        new LambdaQueryWrapper<>(SysCustomerFollowEntity.class)
+                                .select(
+                                        SysCustomerFollowEntity::getId,
+                                        SysCustomerFollowEntity::getProductId,
+                                        SysCustomerFollowEntity::getClaimUserId,
+                                        SysCustomerFollowEntity::getFollowId
+                                )
+                                .eq(SysCustomerFollowEntity::getCustomerId, customerId)
+                                .ne(userId != null, SysCustomerFollowEntity::getClaimUserId, userId)
+                );
+        if (CollUtil.isNotEmpty(followEntityList)) {
+            customerFollowOverViewBO.setHistoryProductCount(
+                    followEntityList.stream()
+                            .map(SysCustomerFollowEntity::getProductId)
+                            .distinct()
+                            .toList().size());
+            customerFollowOverViewBO.setHistoryPersonCount(
+                    followEntityList.stream()
+                            .map(SysCustomerFollowEntity::getClaimUserId)
+                            .distinct()
+                            .toList().size());
+            customerFollowOverViewBO.setHistoryFollowCount(
+                    followEntityList.stream()
+                            .map(SysCustomerFollowEntity::getId)
+                            .toList().size());
+            if (userId != null) {
+                customerFollowOverViewBO.setSuccessCount(
+                        followEntityList.stream()
+                                .filter(e -> e.getFollowId().equals(37L))// 赢单
+                                .toList().size());
+                customerFollowOverViewBO.setFailedCount(
+                        followEntityList.stream()
+                                .filter(e -> e.getFollowId().equals(36L)) //输单
+                                .toList().size());
+            }
+        }
+        return customerFollowOverViewBO;
 
-        sysCustomerFollowMapper.updateById(entity);
     }
 
+
     /**
-     * 后台管理-删除
+     * 查询公海客户产品信息总览
+     *
+     * @param customerId
+     * @return
      */
-    @Transactional(rollbackFor = Exception.class)
-    public void adminDelete(Collection<Long> ids) {
-        log.info("[后台管理-客户跟进数据信息-删除] >> ids={}", ids);
-        sysCustomerFollowMapper.deleteByIds(ids);
+    public List<CustomerProductOverViewBO> queryProductOverViewData(Long customerId) {
+
+        List<CustomerProductOverViewBO> productOverViewBOList = new ArrayList<>();
+        List<SysCustomerFollowEntity> followEntityList =
+                sysCustomerFollowMapper.selectList(
+                        new LambdaQueryWrapper<>(SysCustomerFollowEntity.class)
+                                .select(
+                                        SysCustomerFollowEntity::getProductId,
+                                        SysCustomerFollowEntity::getProductName
+                                )
+                                .eq(SysCustomerFollowEntity::getCustomerId, customerId));
+
+        if (CollUtil.isNotEmpty(followEntityList)) {
+            List<Long> productIdList = followEntityList.stream()
+                    .map(SysCustomerFollowEntity::getProductId).distinct().toList();
+
+            List<SysParamBaseDataEntity> productDataList =
+                    sysParamBaseDataMapper.selectList(
+                            new LambdaQueryWrapper<>(SysParamBaseDataEntity.class)
+                                    .select(
+                                            SysParamBaseDataEntity::getId,
+                                            SysParamBaseDataEntity::getTitle
+                                    )
+                                    .in(SysParamBaseDataEntity::getId, productIdList)
+                                    .orderByAsc(SysParamBaseDataEntity::getSortCode)
+                    );
+            if (CollUtil.isNotEmpty(productDataList)) {
+                productDataList.forEach(e -> {
+                    CustomerProductOverViewBO bo = CustomerProductOverViewBO.builder()
+                            .productId(e.getId())
+                            .productName(e.getTitle())
+                            .build();
+                    bo.setCount(
+                            followEntityList.stream()
+                                    .filter(x -> x.getProductId().equals(e.getId()))
+                                    .toList().size());
+                    productOverViewBOList.add(bo);
+                });
+            }
+        }
+        return productOverViewBOList;
     }
 
-
-    /*
-    ----------------------------------------------------------------
-                        私有方法 private methods
-    ----------------------------------------------------------------
+    /**
+     * 跟进产品数据信息
+     *
+     * @param customerId
+     * @param userId
+     * @return
      */
+    public List<CustomerProductBO> queryCustomerProductData(Long customerId, Long userId) {
+        List<CustomerProductBO> productBOList = new ArrayList<>();
+        List<SysCustomerFollowEntity> followEntityList =
+                sysCustomerFollowMapper.selectList(
+                        new LambdaQueryWrapper<>(SysCustomerFollowEntity.class)
+                                .eq(SysCustomerFollowEntity::getCustomerId, customerId)
+                                .eq(SysCustomerFollowEntity::getClaimUserId, userId)
+                );
+        if (CollUtil.isNotEmpty(followEntityList)) {
+            List<Long> productIdList = followEntityList.stream()
+                    .map(SysCustomerFollowEntity::getProductId).distinct().toList();
+
+            List<SysParamBaseDataEntity> productDataList =
+                    sysParamBaseDataMapper.selectList(
+                            new LambdaQueryWrapper<>(SysParamBaseDataEntity.class)
+                                    .select(
+                                            SysParamBaseDataEntity::getId,
+                                            SysParamBaseDataEntity::getTitle,
+                                            SysParamBaseDataEntity::getSortCode
+                                    )
+                                    .in(SysParamBaseDataEntity::getId, productIdList)
+                                    .orderByAsc(SysParamBaseDataEntity::getSortCode)
+                    );
+            if (CollUtil.isNotEmpty(productDataList)) {
+                productDataList.forEach(product -> {
+                    List<SysCustomerFollowEntity> list = followEntityList.stream()
+                            .filter(x -> x.getProductId().equals(product.getId()))
+                            .toList();
+
+                    CustomerProductBO bo = CustomerProductBO.builder().build();
+                    bo.setProductId(product.getId());
+                    bo.setProductName(product.getTitle());
+                    bo.setSortCode(product.getSortCode());
+                    bo.setCount(list.size());
+                    list.stream().collect(Collectors.groupingBy(SysCustomerFollowEntity::getClaimUserId))
+                            .forEach((id, entities) ->
+                                    entities.stream().max(Comparator.comparing(SysCustomerFollowEntity::getCreatedAt))
+                                            .ifPresent(entity -> {
+                                                bo.setFollowId(entity.getFollowId());
+                                                bo.setFollowName(entity.getFollowName());
+                                                bo.setCustomerPersonId(entity.getCustomerPersonId());
+                                                bo.setCustomerPersonName(entity.getCustomerPersonName());
+                                                bo.setLastFollowTime(entity.getCreatedAt());
+                                            }));
+                    productBOList.add(bo);
+
+                });
+            }
+        }
+        return productBOList;
+    }
 
     /**
-     * 实体转 BO
+     * 查询预约待办
      *
-     * @param entity 实体
-     * @return BO
+     * @param customerId
+     * @param userId
+     * @return
      */
-    private SysCustomerFollowBO entity2BO(SysCustomerFollowEntity entity) {
-        if (entity == null) {
-            return null;
+    public List<SysCustomerFollowDataBO> handleOrderData(Long customerId, Long userId) {
+        List<SysCustomerFollowDataBO> orderList = Lists.newArrayList();
+        List<SysCustomerFollowEntity> followEntityList =
+                sysCustomerFollowMapper.selectList(
+                        new LambdaQueryWrapper<>(SysCustomerFollowEntity.class)
+                                .eq(SysCustomerFollowEntity::getCustomerId, customerId)
+                                .eq(SysCustomerFollowEntity::getClaimUserId, userId)
+                                .eq(SysCustomerFollowEntity::getOrderStatus,0)//待开始的
+                                .isNotNull(SysCustomerFollowEntity::getOrderType)//预约待办不能为空的
+                                .orderByDesc(SysCustomerFollowEntity::getCreatedAt)
+                );
+        if (CollUtil.isNotEmpty(followEntityList)) {
+            orderList = followEntityList.stream().map(entity -> {
+                SysCustomerFollowDataBO bo = SysCustomerFollowDataBO.builder()
+                        .build();
+                BeanUtils.copyProperties(entity, bo);
+                return bo;
+            }).toList();
         }
+        return orderList;
+    }
 
-        SysCustomerFollowBO bo = new SysCustomerFollowBO();
-        BeanUtil.copyProperties(entity, bo);
 
-        // 可以在此处为BO填充字段
+    /**
+     * 处理参数
+     *
+     * @param dto
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public void handleParams(AdminSysCustomerFollowInsertOrUpdateDTO dto) {
+        //处理联系人
+        SysCustomerPersonEntity sysCustomerPersonEntity = sysCustomerPersonMapper.selectById(dto.getCustomerPersonId());
+        if (sysCustomerPersonEntity == null) {
+            throw new RuntimeException("参数错误,联系人不存在");
+        }
+        dto.setCustomerPersonName(sysCustomerPersonEntity.getName());
+        //处理产品
+        SysParamBaseDataEntity productDataEntity = sysParamBaseDataMapper.selectById(dto.getProductId());
+        if (productDataEntity == null) {
+            throw new RuntimeException("参数错误,产品不存在");
+        }
+        dto.setProductName(productDataEntity.getTitle());
+        //处理跟进状态
+        SysParamBaseDataEntity followDataEntity = sysParamBaseDataMapper.selectById(dto.getFollowId());
+        if (followDataEntity == null) {
+            throw new RuntimeException("参数错误,跟进状态不存在");
+        }
+        dto.setFollowName(followDataEntity.getTitle());
+        //处理职务
+        SysParamBaseDataEntity positionDataEntity = sysParamBaseDataMapper.selectById(dto.getPositionId());
+        if (positionDataEntity == null) {
+            throw new RuntimeException("参数错误,职务不存在");
+        }
+        dto.setPositionName(positionDataEntity.getTitle());
+        //处理客户
+        SysCustomerDataEntity sysCustomerDataEntity = sysCustomerDataMapper.selectById(dto.getCustomerId());
+        if (sysCustomerDataEntity == null) {
+            throw new RuntimeException("参数错误,客户不存在");
+        }
+        dto.setClaimUserGroupId(sysCustomerDataEntity.getClaimUserGroupId());
+        //省市数据
+        dto.setCustomerName(sysCustomerDataEntity.getName());
+        dto.setStageId(sysCustomerDataEntity.getStageId());
+        dto.setStageName(sysCustomerDataEntity.getStageName());
+        dto.setProvinceId(sysCustomerDataEntity.getProvinceId());
+        dto.setProvinceName(sysCustomerDataEntity.getProvinceName());
+        dto.setCityId(sysCustomerDataEntity.getCityId());
+        dto.setCityName(sysCustomerDataEntity.getCityName());
+        dto.setFollowId(UserContextHolder.getUserId()); // 处理认领人(跟进)id
+        dto.setFollowName(UserContextHolder.getUserName()); // 处理认领人(跟进)name
+        //处理赢单
+        if (dto.getFollowId() == 37) {
+            dto.setSuccessStatus(1);
+            // 处理客户表的赢单字段
+//            sysCustomerDataEntity.setSuccessStatus(1); //这个状态不在这里使用,赢单需要审核,只有审核通过后才能改这个状态,这里只把赢单人先设置
+//            sysCustomerDataEntity.setSuccessUserId(UserContextHolder.getUserId());
+//            sysCustomerDataEntity.setSuccessUserName(UserContextHolder.getUserName());
+//            sysCustomerDataMapper.updateById(sysCustomerDataEntity);
+            //发送赢单审核
+            this.addFollowAuditData(sysCustomerDataEntity, followDataEntity,
+                    sysCustomerPersonEntity, productDataEntity, positionDataEntity, dto.getFollowContent());
+        }
 
-        return bo;
     }
 
     /**
-     * 实体 List 转 BO List
+     * 添加赢单跟进审核数据
      *
-     * @param entityList 实体 List
-     * @return BO List
+     * @param sysCustomerDataEntity
      */
-    private List<SysCustomerFollowBO> entityList2BOs(List<SysCustomerFollowEntity> entityList) {
-        if (CollUtil.isEmpty(entityList)) {
-            return Collections.emptyList();
+    @Transactional(rollbackFor = Exception.class)
+    public void addFollowAuditData(SysCustomerDataEntity sysCustomerDataEntity,
+                                   SysParamBaseDataEntity followDataEntity,
+                                   SysCustomerPersonEntity sysCustomerPersonEntity,
+                                   SysParamBaseDataEntity productDataEntity,
+                                   SysParamBaseDataEntity positionDataEntity,
+                                   String followContent) {
+        //先查询管理员数据
+        List<SysUserRoleRelationEntity> adminUserList =
+                sysUserRoleRelationMapper.selectList(
+                        new LambdaQueryWrapper<>(SysUserRoleRelationEntity.class)
+                                .select(SysUserRoleRelationEntity::getUserId)
+                                .eq(SysUserRoleRelationEntity::getRoleValue, "Admin")
+                );
+        if (CollUtil.isEmpty(adminUserList)) {
+            throw new RuntimeException("参数错误,管理员不存在");
         }
 
-        // 深拷贝
-        List<SysCustomerFollowBO> ret = new ArrayList<>(entityList.size());
-        entityList.forEach(
-            entity -> ret.add(this.entity2BO(entity))
-        );
-
-        return ret;
+        List<Long> userIds =
+                adminUserList.stream()
+                        .map(SysUserRoleRelationEntity::getUserId)
+                        .distinct().toList();
+        List<SysUserEntity> sysUserEntities = sysUserMapper.selectByIds(userIds);
+        if (CollUtil.isEmpty(sysUserEntities)) {
+            throw new RuntimeException("参数错误,管理员不存在");
+        }
+        adminUserList.forEach(adminUser -> {
+            SysCustomerFollowAuditEntity entity =
+                    this.getFollowAuditEntity(sysCustomerDataEntity, followDataEntity, sysCustomerPersonEntity,
+                            productDataEntity, positionDataEntity, followContent);
+            entity.setAuditUserId(adminUser.getUserId()); // 设置审核人id
+            sysUserEntities.stream().findFirst().ifPresent(sysUserEntity -> entity.setAuditUserName(sysUserEntity.getUserName()));
+            sysCustomerFollowAuditMapper.insert(entity);
+        });
     }
 
     /**
-     * 实体分页转 BO 分页
+     * 获取跟进审核数据
      *
-     * @param entityPage 实体分页
-     * @return BO 分页
+     * @param sysCustomerDataEntity
+     * @param sysCustomerPersonEntity
+     * @param productDataEntity
+     * @param positionDataEntity
+     * @param followContent
+     * @return
      */
-    private PageResult<SysCustomerFollowBO> entityPage2BOPage(Page<SysCustomerFollowEntity> entityPage) {
-        return new PageResult<SysCustomerFollowBO>()
-            .setCurrent(entityPage.getCurrent())
-            .setSize(entityPage.getSize())
-            .setTotal(entityPage.getTotal())
-            .setRecords(this.entityList2BOs(entityPage.getRecords()));
+    public SysCustomerFollowAuditEntity getFollowAuditEntity(SysCustomerDataEntity sysCustomerDataEntity,
+                                                             SysParamBaseDataEntity followDataEntity,
+                                                             SysCustomerPersonEntity sysCustomerPersonEntity,
+                                                             SysParamBaseDataEntity productDataEntity,
+                                                             SysParamBaseDataEntity positionDataEntity,
+                                                             String followContent) {
+        SysCustomerFollowAuditEntity entity = SysCustomerFollowAuditEntity.builder().build();
+        entity.setClaimUserId(sysCustomerDataEntity.getClaimUserId());
+        entity.setClaimUserName(sysCustomerDataEntity.getClaimUserName());
+        entity.setClaimUserGroupId(sysCustomerDataEntity.getClaimUserGroupId());
+        entity.setClaimDatetime(LocalDateTime.now());
+        entity.setCustomerId(sysCustomerDataEntity.getId());
+        entity.setCustomerName(sysCustomerDataEntity.getName());
+        entity.setFollowId(followDataEntity.getId());
+        entity.setFollowName(followDataEntity.getTitle());
+        entity.setCustomerPersonId(sysCustomerPersonEntity.getId());
+        entity.setCustomerPersonName(sysCustomerPersonEntity.getName());
+        entity.setPositionId(positionDataEntity.getId());
+        entity.setPositionName(positionDataEntity.getTitle());
+        entity.setFollowContent(followContent);
+        entity.setProductId(productDataEntity.getId());
+        entity.setProductName(productDataEntity.getTitle());
+        entity.setAuditStatus(0);
+//        entity.setAuditUserId(0L);
+//        entity.setAuditUserName("");
+        return entity;
     }
 
     /**
-     * 检查是否已存在同名数据
+     * 校验参数
      *
-     * @param dto DTO
+     * @param dto
      */
-    private void checkExistence(AdminSysCustomerFollowInsertOrUpdateDTO dto) {
-        /*
-        可以根据自己业务需要,解禁这段代码,修改判断条件和文案
-
-        SysCustomerFollowEntity existingEntity = sysCustomerFollowMapper.selectOne(
-                new QueryWrapper<SysCustomerFollowEntity>()
-                        .lambda()
-                        .select(SysCustomerFollowEntity::getId)
-                        .eq(SysCustomerFollowEntity::getTitle, dto.getTitle())
-                        .last(HelioConstant.CRUD.SQL_LIMIT_1)
-        );
-
-        if (existingEntity != null && !existingEntity.getId().equals(dto.getId())) {
-            throw new BusinessException(400, "已存在相同客户跟进数据信息,请重新输入");
-        }
-        */
-    }
 
+    @Transactional(rollbackFor = Exception.class)
+    public void checkParam(AdminSysCustomerFollowInsertOrUpdateDTO dto) {
+
+        if (dto.getCustomerId() == null) {
+            throw new RuntimeException("参数错误,客户不能为空");
+        }
+        if (dto.getProductId() == null) {
+            throw new RuntimeException("参数错误,产品不能为空");
+        }
+        if (dto.getFollowId() == null) {
+            throw new RuntimeException("参数错误,跟进状态不能为空");
+        }
+        if (dto.getCustomerPersonId() == null) {
+            throw new RuntimeException("参数错误,联系人不能为空");
+        }
+        if (dto.getPositionId() == null) {
+            throw new RuntimeException("参数错误,职务不能为空");
+        }
+        if (StrUtil.isEmpty(dto.getFollowContent())) {
+            throw new RuntimeException("参数错误,跟进内容不能为空");
+        }
+
+        if (dto.getOrderType() != null && dto.getOrderDatetime() == null) {
+            throw new RuntimeException("参数错误,预约待办时间不能为空");
+        }
+
+        if (dto.getOrderDatetime() != null && dto.getOrderDatetime().isBefore(LocalDateTime.now())) {
+            throw new RuntimeException("参数错误,预约待办时间不能在当前时间之前");
+        }
+
+        if (dto.getFollowId() == 33) {
+            if (dto.getOrderType() == null || dto.getOrderType() == 1) {
+                throw new RuntimeException("参数错误,方案演示时,预约待办类型不能为空或待办");
+            }
+        }
+    }
 }

+ 92 - 37
src/main/java/com/jtzx/crm/module/sys/service/SysCustomerOperLogService.java

@@ -5,14 +5,21 @@ import cc.uncarbon.framework.core.page.PageParam;
 import cc.uncarbon.framework.core.page.PageResult;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.text.CharSequenceUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.google.common.collect.Lists;
 import com.jtzx.crm.module.sys.entity.SysCustomerOperLogEntity;
+import com.jtzx.crm.module.sys.entity.SysGroupEntity;
 import com.jtzx.crm.module.sys.mapper.SysCustomerOperLogMapper;
+import com.jtzx.crm.module.sys.mapper.SysGroupMapper;
 import com.jtzx.crm.module.sys.model.request.AdminSysCustomerOperLogInsertOrUpdateDTO;
 import com.jtzx.crm.module.sys.model.request.AdminSysCustomerOperLogListDTO;
+import com.jtzx.crm.module.sys.model.response.BindUserBO;
+import com.jtzx.crm.module.sys.model.response.SelectBO;
 import com.jtzx.crm.module.sys.model.response.SysCustomerOperLogBO;
+import com.jtzx.crm.module.sys.model.response.SysCustomerOperLogDataBO;
+import com.jtzx.crm.module.sys.util.DateSelectUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -31,50 +38,98 @@ public class SysCustomerOperLogService {
 
     private final SysCustomerOperLogMapper sysCustomerOperLogMapper;
 
+    private final SysGroupMapper sysGroupMapper;
 
     /**
-     * 后台管理-分页列表
+     * 操作日志列表查询
      */
-    public PageResult<SysCustomerOperLogBO> adminList(PageParam pageParam, AdminSysCustomerOperLogListDTO dto) {
+    public SysCustomerOperLogDataBO adminList(AdminSysCustomerOperLogListDTO dto, Boolean dateSelectStatus, Boolean groupSelectStatus) {
         Page<SysCustomerOperLogEntity> entityPage = sysCustomerOperLogMapper.selectPage(
-                new Page<>(pageParam.getPageNum(), pageParam.getPageSize()),
+                new Page<>(dto.getPageNum(), dto.getPageSize()),
                 new QueryWrapper<SysCustomerOperLogEntity>()
                         .lambda()
                         // 客户表主id
                         .eq(Objects.nonNull(dto.getCustomerId()), SysCustomerOperLogEntity::getCustomerId, dto.getCustomerId())
-                        // 客户名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getCustomerName()), SysCustomerOperLogEntity::getCustomerName, CharSequenceUtil.cleanBlank(dto.getCustomerName()))
                         // 操作人id
                         .eq(Objects.nonNull(dto.getOperUserId()), SysCustomerOperLogEntity::getOperUserId, dto.getOperUserId())
-                        // 操作人名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getOperName()), SysCustomerOperLogEntity::getOperName, CharSequenceUtil.cleanBlank(dto.getOperName()))
-                        // 操作类型,0-认领,1-跟进,2-转让,3-转到公海,11-新增,12-修改,13-删除
-                        .eq(Objects.nonNull(dto.getOperAction()), SysCustomerOperLogEntity::getOperAction, dto.getOperAction())
-                        // 操作时间
-                        .eq(Objects.nonNull(dto.getOperDatetime()), SysCustomerOperLogEntity::getOperDatetime, dto.getOperDatetime())
-                        // 操作人员所在的项目组id
-                        .eq(Objects.nonNull(dto.getOperUserGroupId()), SysCustomerOperLogEntity::getOperUserGroupId, dto.getOperUserGroupId())
-                        // 省份id(省份表主id)
-                        .eq(Objects.nonNull(dto.getProvinceId()), SysCustomerOperLogEntity::getProvinceId, dto.getProvinceId())
-                        // 省份名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getProvinceName()), SysCustomerOperLogEntity::getProvinceName, CharSequenceUtil.cleanBlank(dto.getProvinceName()))
-                        // 城市id(城市表主id)
-                        .eq(Objects.nonNull(dto.getCityId()), SysCustomerOperLogEntity::getCityId, dto.getCityId())
-                        // 城市名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getCityName()), SysCustomerOperLogEntity::getCityName, CharSequenceUtil.cleanBlank(dto.getCityName()))
-                        // 跟进状态id,赢单状态id固定-37,方案演示id固定-33
-                        .eq(Objects.nonNull(dto.getFollowId()), SysCustomerOperLogEntity::getFollowId, dto.getFollowId())
-                        // 跟进状态的名称
-                        .like(CharSequenceUtil.isNotBlank(dto.getFollowName()), SysCustomerOperLogEntity::getFollowName, CharSequenceUtil.cleanBlank(dto.getFollowName()))
-                        // 操作内容,的数据内容json格式保存
-                        .like(CharSequenceUtil.isNotBlank(dto.getContent()), SysCustomerOperLogEntity::getContent, CharSequenceUtil.cleanBlank(dto.getContent()))
-                        // 时间区间
-                        .between(Objects.nonNull(dto.getBeginAt()) && Objects.nonNull(dto.getEndAt()), SysCustomerOperLogEntity::getCreatedAt, dto.getBeginAt(), dto.getEndAt())
+                        .ge(dto.getStartDate() != null, SysCustomerOperLogEntity::getCreatedAt, dto.getStartDate())
+                        .le(dto.getEndDate() != null, SysCustomerOperLogEntity::getCreatedAt, dto.getEndDate())
                         // 排序
                         .orderByDesc(SysCustomerOperLogEntity::getCreatedAt)
         );
+        SysCustomerOperLogDataBO resultData = SysCustomerOperLogDataBO.builder().build();
+        PageResult<SysCustomerOperLogBO> pageResult = this.entityPage2BOPage(entityPage);
+        //数据
+        resultData.setData(pageResult);
+        // 时间
+        resultData.setDateData(Lists.newArrayList());
+        if (dateSelectStatus != null && dateSelectStatus) {
+            resultData.setDateData(DateSelectUtil.getDateData());
+        }
+        // 操作人
+        List<BindUserBO> memberData = Lists.newArrayList();
+        // 小组
+        List<SelectBO> groupData = Lists.newArrayList();
+
+        List<SysCustomerOperLogEntity> logEntityList =
+                sysCustomerOperLogMapper.selectList(
+                        new LambdaQueryWrapper<>(SysCustomerOperLogEntity.class)
+                                .select(
+                                        SysCustomerOperLogEntity::getId,
+                                        SysCustomerOperLogEntity::getCustomerId,
+                                        SysCustomerOperLogEntity::getOperUserId,
+                                        SysCustomerOperLogEntity::getOperName,
+                                        SysCustomerOperLogEntity::getOperUserGroupId
+                                )
+                                .eq(SysCustomerOperLogEntity::getCustomerId, dto.getCustomerId())
+                                .orderByDesc(SysCustomerOperLogEntity::getCreatedAt)
+                );
+        if (CollUtil.isNotEmpty(logEntityList)) {
+
+            logEntityList.forEach(
+                    entity -> {
+                        if (memberData.stream().map(BindUserBO::getId).noneMatch(entity.getOperUserId()::equals)) {
+                            BindUserBO member = BindUserBO.builder()
+                                    .id(entity.getOperUserId())
+                                    .username(entity.getOperName())
+                                    .groupId(entity.getOperUserGroupId())
+                                    .build();
+                            memberData.add(member);
+                        }
+                    }
+            );
+            // 小组
+            if (groupSelectStatus != null && groupSelectStatus) {
+                List<Long> operUserGroupIdList =
+                        logEntityList.stream()
+                                .map(SysCustomerOperLogEntity::getOperUserGroupId)
+                                .distinct().toList();
+                List<SysGroupEntity> groupEntityList =
+                        sysGroupMapper.selectList(
+                                new LambdaQueryWrapper<>(SysGroupEntity.class)
+                                        .select(
+                                                SysGroupEntity::getId,
+                                                SysGroupEntity::getTitle
+                                        )
+                                        .in(SysGroupEntity::getId, operUserGroupIdList)
+                                        .orderByAsc(SysGroupEntity::getSortCode)
+                        );
+                if (CollUtil.isNotEmpty(groupEntityList)) {
+                    groupEntityList.forEach(
+                            entity ->
+                                    groupData.add(SelectBO.builder()
+                                            .id(entity.getId())
+                                            .name(entity.getTitle())
+                                            .build()));
+                }
+            }
 
-        return this.entityPage2BOPage(entityPage);
+        }
+        // 操作人
+        resultData.setMemberData(memberData);
+        // 小组
+        resultData.setGroupData(groupData);
+        return resultData;
     }
 
     /**
@@ -90,7 +145,7 @@ public class SysCustomerOperLogService {
     /**
      * 根据 ID 取详情
      *
-     * @param id 主键ID
+     * @param id               主键ID
      * @param throwIfInvalidId 是否在 ID 无效时抛出异常
      * @return null or BO
      */
@@ -183,7 +238,7 @@ public class SysCustomerOperLogService {
         // 深拷贝
         List<SysCustomerOperLogBO> ret = new ArrayList<>(entityList.size());
         entityList.forEach(
-            entity -> ret.add(this.entity2BO(entity))
+                entity -> ret.add(this.entity2BO(entity))
         );
 
         return ret;
@@ -197,10 +252,10 @@ public class SysCustomerOperLogService {
      */
     private PageResult<SysCustomerOperLogBO> entityPage2BOPage(Page<SysCustomerOperLogEntity> entityPage) {
         return new PageResult<SysCustomerOperLogBO>()
-            .setCurrent(entityPage.getCurrent())
-            .setSize(entityPage.getSize())
-            .setTotal(entityPage.getTotal())
-            .setRecords(this.entityList2BOs(entityPage.getRecords()));
+                .setCurrent(entityPage.getCurrent())
+                .setSize(entityPage.getSize())
+                .setTotal(entityPage.getTotal())
+                .setRecords(this.entityList2BOs(entityPage.getRecords()));
     }
 
     /**

+ 11 - 4
src/main/java/com/jtzx/crm/module/sys/service/SysCustomerPersonService.java

@@ -5,12 +5,14 @@ import cc.uncarbon.framework.core.exception.BusinessException;
 import cc.uncarbon.framework.core.page.PageResult;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.jtzx.crm.module.sys.entity.*;
 import com.jtzx.crm.module.sys.mapper.*;
 import com.jtzx.crm.module.sys.model.request.AdminSysCustomerPersonInsertOrUpdateDTO;
+import com.jtzx.crm.module.sys.model.request.CustomerPersonReqDTO;
 import com.jtzx.crm.module.sys.model.response.SysCustomerPersonBO;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -45,16 +47,21 @@ public class SysCustomerPersonService {
     /**
      * 后台管理-联系人列表
      */
-    public List<SysCustomerPersonBO> adminList(Long customerId, Long positionId,Long userId) {
+    public List<SysCustomerPersonBO> adminList(CustomerPersonReqDTO dto) {
         List<SysCustomerPersonEntity> entityPage = sysCustomerPersonMapper.selectList(
                 new QueryWrapper<SysCustomerPersonEntity>()
                         .lambda()
                         // 客户表主id
-                        .eq(SysCustomerPersonEntity::getCustomerId, customerId)
+                        .eq(SysCustomerPersonEntity::getCustomerId, dto.getCustomerId())
                         //创建人过滤
-                        .eq(userId!=null,SysCustomerPersonEntity::getCreatedBy,userId)
+                        .eq(dto.getUserId()!=null,SysCustomerPersonEntity::getCreatedBy,dto.getUserId())
                         // 职务id(param_base_data表主id)
-                        .eq(positionId != null, SysCustomerPersonEntity::getPositionId, positionId)
+                        .eq(dto.getPositionId() != null, SysCustomerPersonEntity::getPositionId, dto.getPositionId())
+                        .and(StrUtil.isNotEmpty(dto.getQueryStr()),z->z.like(SysCustomerPersonEntity::getName,dto.getQueryStr())
+                                .or().like(SysCustomerPersonEntity::getPhoneNo,dto.getQueryStr())
+                                .or().like(SysCustomerPersonEntity::getOfficePhoneNo, dto.getQueryStr())
+                                .or().like(SysCustomerPersonEntity::getCreatedBy, dto.getQueryStr())
+                        )
         );
         return this.entityList2BOs(entityPage);
     }

+ 3 - 1
src/main/java/com/jtzx/crm/module/sys/service/SysParamService.java

@@ -28,6 +28,7 @@ public class SysParamService {
 
     /**
      * 查询参数配置数据
+     *
      * @return
      */
     public SysParamBO queryParams() {
@@ -38,6 +39,7 @@ public class SysParamService {
             sysParamEntity.setDayBackTopCount(0);
             sysParamEntity.setBackPublicDayCount(0);
             sysParamEntity.setTitle("公海设置");
+            sysParamMapper.insert(sysParamEntity);
         }
         return this.entity2BO(sysParamEntity);
     }
@@ -103,7 +105,6 @@ public class SysParamService {
 
         SysParamBO bo = new SysParamBO();
         BeanUtil.copyProperties(entity, bo);
-
         // 可以在此处为BO填充字段
         bo.setStageData(
                 sysParamBaseDataService.queryStage());
@@ -115,6 +116,7 @@ public class SysParamService {
                 sysParamBaseDataService.queryFollowStatus());
         bo.setRegionData(
                 dictProvinceRegionService.listUsed());
+        bo.setId(entity.getId());
         return bo;
     }
 

+ 15 - 12
src/main/java/com/jtzx/crm/module/sys/util/DateSelectUtil.java

@@ -17,18 +17,20 @@ public class DateSelectUtil {
         List<DateSelectBO> dateData = Lists.newArrayList();
         dateData.add(getBO("全部",0,null));
         dateData.add(getBO("今天",0, DateField.DAY_OF_YEAR));
-        dateData.add(getBO("本周",1,DateField.DAY_OF_WEEK));
-        dateData.add(getBO("最近1个月",1,DateField.MONTH));
-        dateData.add(getBO("最近3个月",3,DateField.MONTH));
-        dateData.add(getBO("最近半年",6,DateField.MONTH));
-        dateData.add(getBO("自定义",0,null));
+        dateData.add(getBO("昨天",1, DateField.DAY_OF_YEAR));
+        dateData.add(getBO("近3天",3, DateField.DAY_OF_YEAR));
+        dateData.add(getBO("近1周",7, DateField.DAY_OF_YEAR));
+        dateData.add(getBO("近1月",1,DateField.MONTH));
+        dateData.add(getBO("近3月",3,DateField.MONTH));
+        dateData.add(getBO("近半年",6,DateField.MONTH));
+        dateData.add(getBO("自定义",null,null));
         return dateData;
     }
 
     public static void main(String[] args) {
 //        DateSelectBO bo = getBO("本周", 7, DateField.DAY_OF_WEEK);
-//        DateSelectBO bo = getBO("最近1个月",1,DateField.MONTH);
-        DateSelectBO bo = getBO("今天",0,DateField.DAY_OF_YEAR);
+        DateSelectBO bo = getBO("最近3个月",3,DateField.MONTH);
+//        DateSelectBO bo = getBO("近1周",7,DateField.DAY_OF_YEAR);
         System.out.println(JSONUtil.toJsonStr(bo));
     }
 
@@ -45,7 +47,7 @@ public class DateSelectUtil {
         bo.setName(name);
         bo.setSortCode(number);
         bo.setSelectStatus(false);
-        if (dateField == null) {
+        if (dateField == null && number == null) {
             bo.setSelectStatus(true);
         } else {
             //取当天的最后一秒,往前计算开始时间
@@ -53,11 +55,12 @@ public class DateSelectUtil {
             LocalDateTime endDateTime = DateUtil.toLocalDateTime(endDay);
             bo.setEndDate(endDateTime);
 
-            if(dateField.equals(DateField.DAY_OF_WEEK)){
-                DateTime dateTime = DateUtil.beginOfWeek(endDay);
+
+            if(dateField != null && dateField.equals(DateField.DAY_OF_WEEK)){
+                DateTime dateTime = DateUtil.beginOfWeek(DateUtil.date());
                 bo.setStartDate(DateUtil.toLocalDateTime(dateTime));
             }else {
-                bo.setStartDate(getStartDate(number, dateField, endDay));
+                bo.setStartDate(getStartDate(number, dateField, DateUtil.date()));
             }
         }
         return bo;
@@ -66,7 +69,7 @@ public class DateSelectUtil {
 
     public static LocalDateTime getStartDate(Integer number, DateField dateField, DateTime endDay) {
         DateTime startDate = DateUtil.offset(endDay, dateField, -number);
-        String str = DateUtil.formatDate(startDate)+" 00:00:00";
+        String str = DateUtil.formatDateTime(startDate);
         return DateUtil.toLocalDateTime(DateUtil.parse(str));
     }
 }