diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAContractController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAContractController.java index a3a703ff..a206f799 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAContractController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/BpmOAContractController.java @@ -37,7 +37,6 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti * OA 合同审批 Controller * * @author 符溶馨 - */ @Tag(name = "管理后台 - OA 合同审批") @RestController @@ -68,7 +67,6 @@ public class BpmOAContractController { @Operation(summary = "获得合同审批") @Parameter(name = "id", description = "编号", required = true, example = "1024") public CommonResult getContract(@RequestParam("id") Long id) { - BpmOAContractDO contract = contractService.getContract(id); BpmOAContractRespVO respVO = BpmOAContractConvert.INSTANCE.convert(contract); if (respVO != null) { @@ -137,15 +135,12 @@ public class BpmOAContractController { return success(contractService.getContractPage(pageReqVO)); } - @GetMapping("/getListByDeptId") - @Operation(summary = "获得同部门的销售合同") - public CommonResult> getListByDeptId() { - - // 获取同部门所有用户id - List userIds = userApi.getUserIdsByUserIdGroupByDept(getLoginUserId()).getCheckedData(); - - List contracts = contractService.getListByDeptId(userIds); - + @GetMapping("/getList") + @Operation(summary = "获取下属和自己的合同列表") + public CommonResult> getList(@RequestParam(required = false) String relation, + @RequestParam(required = false) Integer contractType, + @RequestParam(required = false) String contractName) { + List contracts = contractService.getList(relation, contractType, contractName); return success(BeanUtils.toBean(contracts, BpmOAContractRespVO.class)); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/invoice/BpmOAInvoiceRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/invoice/BpmOAInvoiceRespVO.java index ad6dd51f..844e5c9b 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/invoice/BpmOAInvoiceRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/vo/invoice/BpmOAInvoiceRespVO.java @@ -26,6 +26,9 @@ public class BpmOAInvoiceRespVO extends BpmOABaseRespVO { @Schema(description = "合同名称", requiredMode = Schema.RequiredMode.NOT_REQUIRED) private String contractName; + @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + private String contractNo; + @Schema(description = "关联合同流程实例编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED) private String contractInstanceId; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAInvoiceMapper.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAInvoiceMapper.java index 909deaef..63d9dc99 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAInvoiceMapper.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/BpmOAInvoiceMapper.java @@ -16,32 +16,17 @@ import java.util.Objects; public interface BpmOAInvoiceMapper extends BaseMapperX { default PageResult selectPage(BpmOAInvoicePageReqVO pageReqVO, - Long userId) { + List userIds) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); query.selectAll(BpmOAInvoiceDO.class); query.selectAs(BpmOAContractDO::getContractName, BpmOAInvoiceRespVO::getContractName); query.selectAs(BpmOAContractDO::getCustomerName, BpmOAInvoiceRespVO::getCustomerName); + query.selectAs(BpmOAContractDO::getContractNo, BpmOAInvoiceRespVO::getContractNo); query.leftJoin(BpmOAContractDO.class, "c", BpmOAContractDO::getId, BpmOAInvoiceDO::getContractId); query.apply(Objects.nonNull(pageReqVO.getContractName()), "c.contract_name LIKE CONCAT('%', {0}, '%')", pageReqVO.getContractName()); query.apply(Objects.nonNull(pageReqVO.getCustomerName()), "c.customer_name LIKE CONCAT('%', {0}, '%')", pageReqVO.getCustomerName()); - if ("my".equals(pageReqVO.getRelation())) { - query.eq(BpmOAContractDO::getUserId, userId); - }else if ("sub".equals(pageReqVO.getRelation())){ - query.innerJoin("(" + - "\tSELECT DISTINCT\n" + - "\t\tu.id \n" + - "\tFROM\n" + - "\t\tsystem_users u\n" + - "\t\tINNER JOIN system_dept d ON d.leader_user_id = "+ userId +"\n" + - "\t\tINNER JOIN system_dept d1 ON d1.flag LIKE CONCAT( '%', d.id, '-' ) \n" + - "\t\tOR d1.flag LIKE CONCAT( '%-', d.id, '-%' ) \n" + - "\t\tOR d1.flag LIKE CONCAT( '-', d.id, '%' ) \n" + - "\tWHERE\n" + - "\t\tu.dept_id = d1.id \n" + - "\t\tAND u.STATUS = 0 \n" + - "\t) subordinate ON subordinate.id = t.user_id"); - } + query.in(BpmOAInvoiceDO::getUserId, userIds); query.orderByDesc(BpmOAInvoiceDO::getCreateTime); return selectJoinPage(pageReqVO, BpmOAInvoiceRespVO.class, query); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAContractService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAContractService.java index d37dab78..7d45129d 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAContractService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAContractService.java @@ -127,4 +127,11 @@ public interface BpmOAContractService { * @param contractIds */ void updateSettlementFlagByIds(List contractIds); + + /** + * 获取下属和自己的合同列表 + * + * @return + */ + List getList(String relation, Integer contractType, String contractName); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAContractServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAContractServiceImpl.java index 4dd9d5dc..6c793a8c 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAContractServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAContractServiceImpl.java @@ -2,9 +2,7 @@ package cn.iocoder.yudao.module.bpm.service.oa; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.util.NumberUtil; import cn.iocoder.yudao.framework.common.enums.ShopCommonEnum; -import cn.iocoder.yudao.framework.common.exception.ErrorCode; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.UploadUserFile; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -18,6 +16,7 @@ import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAContractMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.service.task.BpmHistoryProcessInstanceService; import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; +import cn.iocoder.yudao.module.hrm.api.crmbusiness.BusinessApi; import cn.iocoder.yudao.module.hrm.api.crmcontract.ContractApi; import cn.iocoder.yudao.module.hrm.api.crmcontract.dto.CrmContractProductDTO; import cn.iocoder.yudao.module.hrm.api.crmcustomer.CrmCustomerApi; @@ -25,8 +24,6 @@ import cn.iocoder.yudao.module.hrm.api.crmcustomer.dto.CrmCustomerDTO; import cn.iocoder.yudao.module.hrm.api.userlivetree.UserLiveTreeApi; import cn.iocoder.yudao.module.product.api.storeproduct.StoreProductApi; import cn.iocoder.yudao.module.product.api.storeproductattrvalue.StoreProductAttrValueApi; -import cn.iocoder.yudao.module.product.api.storeproductattrvalue.dto.StoreProductAttrValueApiDTO; -import cn.iocoder.yudao.module.product.api.storeproductattrvalue.vo.StoreProductAttrValueApiVO; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; @@ -107,7 +104,8 @@ public class BpmOAContractServiceImpl extends BpmOABaseService implements BpmOAC @Resource private CrmCustomerApi customerApi; - + @Resource + private BusinessApi businessApi; @Resource private UserLiveTreeApi userLiveTreeApi; @@ -206,13 +204,15 @@ public class BpmOAContractServiceImpl extends BpmOABaseService implements BpmOAC ProcessInstance instance = processInstanceService.getProcessInstance(processInstanceId); if (instance.isEnded()) { - // 审批通过后,更新客户成交信息 customerApi.updateCustomerPurchaseTotal(new CrmCustomerDTO() .setId(contract.getCustomerId()) .setDealStatus(ShopCommonEnum.IS_STATUS_1.getValue()) .setDealTime(LocalDateTime.now()) .setPurchaseTotal(contract.getContractMoney())); + + // 审批通过后,更新商机状态 + businessApi.updateIsEnd(contract.getBusinessId(), ShopCommonEnum.IS_STATUS_1.getValue()); } } @@ -354,6 +354,27 @@ public class BpmOAContractServiceImpl extends BpmOABaseService implements BpmOAC .in(BpmOAContractDO::getId, contractIds)); } + @Override + public List getList(String relation, Integer contractType, String contractName) { + List userIds = new ArrayList<>(); + Long id = getLoginUserId(); + if ("my".equals(relation)) { + userIds.add(id); + } else if ("sub".equals(relation)) { + // 查询当前用户 所有下级用户编号 + userIds.addAll(userLiveTreeApi.getItemIdsByUserId(id).getCheckedData()); + } + userIds.add(id); + if (CollUtil.isNotEmpty(userIds)) { + return contractMapper.selectList(new LambdaQueryWrapperX() + .in(BpmOAContractDO::getUserId, userIds) + .eqIfPresent(BpmOAContractDO::getContractType, contractType) + .likeIfPresent(BpmOAContractDO::getContractName, contractName) + .eq(BpmOAContractDO::getResult, BpmProcessInstanceResultEnum.APPROVE.getResult())); + } + return Collections.emptyList(); + } + public static BigDecimal calculatePercentageChange(Object today, Object yesterday) { // 转换为 BigDecimal 进行高精度计算 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAInvoiceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAInvoiceServiceImpl.java index 4261a384..c73672be 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAInvoiceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/BpmOAInvoiceServiceImpl.java @@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAInvoiceDO; import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAInvoiceMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.service.task.BpmHistoryProcessInstanceService; +import cn.iocoder.yudao.module.hrm.api.userlivetree.UserLiveTreeApi; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.stereotype.Service; @@ -22,6 +23,7 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -36,11 +38,10 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; * OA 开票申请 Service 实现类 * * @author 符溶馨 - */ @Service @Validated -public class BpmOAInvoiceServiceImpl extends BpmOABaseService implements BpmOAInvoiceService{ +public class BpmOAInvoiceServiceImpl extends BpmOABaseService implements BpmOAInvoiceService { /** * OA 开票申请对应的流程定义 KEY @@ -61,6 +62,8 @@ public class BpmOAInvoiceServiceImpl extends BpmOABaseService implements BpmOAIn @Resource private RedissonClient redissonClient; + @Resource + private UserLiveTreeApi userLiveTreeApi; @Override @Transactional(rollbackFor = Exception.class) @@ -74,7 +77,7 @@ public class BpmOAInvoiceServiceImpl extends BpmOABaseService implements BpmOAIn .setUserId(userId) .setStatus(0) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); - invoiceMapper.insert(invoice) ; + invoiceMapper.insert(invoice); // 发起 BPM 流程 Map processInstanceVariables = new HashMap<>(); @@ -90,10 +93,10 @@ public class BpmOAInvoiceServiceImpl extends BpmOABaseService implements BpmOAIn historyProcessInstanceService.createHistoryProcessInstance(processInstanceId, createReqVO.getProcessInstanceId()); } - List fileItems = createReqVO.getFileItems() ; + List fileItems = createReqVO.getFileItems(); //这里的逻辑,如果fileItems不为空,且有数据,那么说明是上传了附件的,则需要更工作流文件表对应的实例Id if (fileItems != null && !fileItems.isEmpty()) { - uploadBpmFileProcessInstanceId(processInstanceId,fileItems) ; + uploadBpmFileProcessInstanceId(processInstanceId, fileItems); } return invoice.getId(); @@ -184,8 +187,14 @@ public class BpmOAInvoiceServiceImpl extends BpmOABaseService implements BpmOAIn @Override public PageResult getInvoicePage(BpmOAInvoicePageReqVO pageReqVO) { - - return invoiceMapper.selectPage(pageReqVO, getLoginUserId()); + Long loginUserId = getLoginUserId(); + List userIds = new ArrayList<>(); + if ("my".equals(pageReqVO.getRelation())) { + userIds.add(loginUserId); + } else { + userIds = userLiveTreeApi.getItemIdsByUserId(loginUserId).getCheckedData(); + } + return invoiceMapper.selectPage(pageReqVO, userIds); } @Override diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/hrm/api/crmbusiness/BusinessApi.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/hrm/api/crmbusiness/BusinessApi.java index 17470fc1..2995a14d 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/hrm/api/crmbusiness/BusinessApi.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/hrm/api/crmbusiness/BusinessApi.java @@ -28,4 +28,9 @@ public interface BusinessApi { @Operation(summary = "获得商机所绑定产品信息") @Parameter(name = "businessId", description = "商机编号", required = true) CommonResult> getBusinessProduct(@RequestParam("businessId") Long businessId); + + @GetMapping(PREFIX + "/updateIsEnd") + @Operation(summary = "更新商机状态") + @Parameter(name = "id", description = "ID", required = true) + CommonResult updateIsEnd(@RequestParam("id") Long id, @RequestParam("isEnd") Integer isEnd); } diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java index 1b19aaba..1c03818b 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java @@ -16,5 +16,6 @@ public interface ErrorCodeConstants { ErrorCode ACHIEVEMENT_NOT_EXISTS = new ErrorCode(200009, "业绩目标不存在"); ErrorCode NOT_EDITABLE_UNTIL_SALES_TARGET_HAS_BEEN_APPLIED = new ErrorCode(200010, "未申请销售目标前不可编辑"); ErrorCode THIS_CUSTOMER_ALREADY_EXISTS_IN_THE_SYSTEM_AND_CANNOT_BE_ENTERED_REPEATEDLY = new ErrorCode(200011, "系统已存在该客户,不可重复录入"); + ErrorCode THIS_CUSTOMER_ALREADY_EXISTS_IN_THE_SYSTEM_DO_YOU_WANT_TO_CONTINUE_ADDING = new ErrorCode(200012, "系统已存在该客户,是否继续添加"); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/api/crmbusiness/BusinessApiImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/api/crmbusiness/BusinessApiImpl.java index c5f69870..7cfd29b0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/api/crmbusiness/BusinessApiImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/api/crmbusiness/BusinessApiImpl.java @@ -12,7 +12,6 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; - import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -38,4 +37,10 @@ public class BusinessApiImpl implements BusinessApi { List businessProductList = businessService.getBusinessProductListByBusinessId(businessId); return success(BeanUtils.toBean(businessProductList, CrmBusinessProductDTO.class)); } + + @Override + public CommonResult updateIsEnd(Long id, Integer isEnd) { + businessService.updateIsEnd(id, isEnd); + return success(true); + } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/crmcustomer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/crmcustomer/CrmCustomerController.java index 9c4f5451..72d371c9 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/crmcustomer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/crmcustomer/CrmCustomerController.java @@ -12,15 +12,13 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.tags.Tag; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.util.Arrays; import java.util.List; @@ -105,12 +103,12 @@ public class CrmCustomerController { @Operation(summary = "导出客户 Excel") // @PreAuthorize("@ss.hasPermission('crm:customer:export')") public void exportCustomerExcel(@Valid CrmCustomerPageReqVO pageReqVO, - HttpServletResponse response) throws IOException { + HttpServletResponse response) throws IOException { pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); List list = customerService.getCustomerPage(pageReqVO).getList(); // 导出 Excel ExcelUtils.write(response, "客户.xls", "数据", CrmCustomerRespVO.class, - BeanUtils.toBean(list, CrmCustomerRespVO.class)); + BeanUtils.toBean(list, CrmCustomerRespVO.class)); } @GetMapping("/get-import-template") @@ -136,11 +134,11 @@ public class CrmCustomerController { @Parameter(name = "averageType", description = "分配方式") }) public CommonResult importExcel(@RequestParam("file") MultipartFile file, - @RequestParam("deptId") String deptId, @RequestParam("adminIds") String adminIds, - @RequestParam("averageType") Integer averageType) throws Exception { + @RequestParam("averageType") Integer averageType, + @RequestParam(value = "repeatConfirmationFlag", defaultValue = "0") Integer repeatConfirmationFlag) throws Exception { List list = ExcelUtils.read(file, CrmCustomerImportVO.class); - return success(customerService.importList(list, deptId,adminIds,averageType)); + return success(customerService.importList(list, adminIds, averageType, repeatConfirmationFlag)); } @PostMapping("/recover") @@ -172,6 +170,4 @@ public class CrmCustomerController { } - - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/crmcustomer/vo/CrmCustomerPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/crmcustomer/vo/CrmCustomerPageReqVO.java index 43bbf430..f44db228 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/crmcustomer/vo/CrmCustomerPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/crmcustomer/vo/CrmCustomerPageReqVO.java @@ -16,6 +16,8 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class CrmCustomerPageReqVO extends PageParam { + @Schema(description = "是否去重 0否 1是 默认否", example = "0") + private Integer distinctFlag = 0; @Schema(description = "客户名称", example = "李四") private String name; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/crmcustomer/vo/CrmCustomerRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/crmcustomer/vo/CrmCustomerRespVO.java index 739a111a..d91bd6f4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/crmcustomer/vo/CrmCustomerRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/crmcustomer/vo/CrmCustomerRespVO.java @@ -133,4 +133,6 @@ public class CrmCustomerRespVO { @Schema(description = "负责人") private String createName; + @Schema(description = "相同客户自增排序") + private Integer sortNum; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/crmcustomer/vo/CrmCustomerSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/crmcustomer/vo/CrmCustomerSaveReqVO.java index b8f6ddb5..00fb926b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/crmcustomer/vo/CrmCustomerSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/crmcustomer/vo/CrmCustomerSaveReqVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.crm.controller.admin.crmcustomer.vo; import io.swagger.v3.oas.annotations.media.Schema; -import javax.validation.constraints.NotEmpty; import lombok.Data; +import javax.validation.constraints.NotEmpty; import java.math.BigDecimal; import java.time.LocalDateTime; @@ -108,6 +108,7 @@ public class CrmCustomerSaveReqVO { @Schema(description = "跟进状态", example = "1") private Integer followStatus; - + @Schema(description = "重复客户依旧添加 0否 1是 默认否", example = "1") + private Integer repeatConfirmationFlag; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/crmclues/CrmCluesDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/crmclues/CrmCluesDO.java index 04dffe69..bcab4652 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/crmclues/CrmCluesDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/crmclues/CrmCluesDO.java @@ -61,7 +61,7 @@ public class CrmCluesDO extends BaseDO { */ private Integer industry; /** - * 客户标签 + * 客户标签 */ private String tags; /** @@ -107,11 +107,11 @@ public class CrmCluesDO extends BaseDO { private LocalDateTime collectTime; /** * 跟进状态1|新客 -2|待再次沟通 -3|有意向 -4|已加微信 -5|转商机 -0|无效 + * 2|待再次沟通 + * 3|有意向 + * 4|已加微信 + * 5|转商机 + * 0|无效 */ private Integer followStatus; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/crmcustomer/CrmCustomerDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/crmcustomer/CrmCustomerDO.java index 837e0653..bedb397a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/crmcustomer/CrmCustomerDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/crmcustomer/CrmCustomerDO.java @@ -78,7 +78,10 @@ public class CrmCustomerDO extends BaseDO { * 负责人ID */ private Long ownerUserId; - + /** + * 相同客户自增排序 + */ + private Integer sortNum; /** * 省份id */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/crmcustomer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/crmcustomer/CrmCustomerMapper.java index 6460d4ac..00e6b7d4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/crmcustomer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/crmcustomer/CrmCustomerMapper.java @@ -27,7 +27,7 @@ public interface CrmCustomerMapper extends BaseMapperX { return selectPage(reqVO, new LambdaQueryWrapperX() //.eq(CustomerTypesEnum.OPEN.getValue().equals(reqVO.getType()),) - .inIfPresent(CrmCustomerDO::getOwnerUserId,ids) + .inIfPresent(CrmCustomerDO::getOwnerUserId, ids) .likeIfPresent(CrmCustomerDO::getName, reqVO.getName()) .eqIfPresent(CrmCustomerDO::getMobile, reqVO.getMobile()) .eqIfPresent(CrmCustomerDO::getTelephone, reqVO.getTelephone()) @@ -41,7 +41,17 @@ public interface CrmCustomerMapper extends BaseMapperX { .orderByDesc(CrmCustomerDO::getId)); } - IPage selectPageList(@Param("page") IPage page, @Param("dto") CrmCustomerPageReqVO pageReqVO, @Param("ids") List ids); + IPage selectPageList2(@Param("page") IPage page, @Param("dto") CrmCustomerPageReqVO pageReqVO, @Param("ids") List ids); List selectStatistic(@Param("userIds") List userIds, @Param("createTime") LocalDateTime[] createTime); + + IPage selectPageList(@Param("page") IPage page, @Param("dto") CrmCustomerPageReqVO pageReqVO, @Param("ids") List ids); + + /** + * 获取重复客户的所有负责人名称 + * + * @param name + * @return + */ + List getRepeatOwnerUserName(@Param("name") String name); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/crminvoice/CrmInvoiceMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/crminvoice/CrmInvoiceMapper.java index 5626dd86..85370baf 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/crminvoice/CrmInvoiceMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/crminvoice/CrmInvoiceMapper.java @@ -10,8 +10,11 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.crmcontract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.crmcontractreceivables.CrmContractReceivablesDO; import cn.iocoder.yudao.module.crm.dal.dataobject.crmcustomer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.crminvoice.CrmInvoiceDO; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.github.yulichang.wrapper.MPJLambdaWrapper; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -26,6 +29,7 @@ public interface CrmInvoiceMapper extends BaseMapperX { default PageResult selectPage2(CrmInvoicePageReqVO reqVO, List ids) { Long loginAdminId = SecurityFrameworkUtils.getLoginUserId(); + return selectJoinPage(reqVO, CrmInvoiceRespVO.class, new MPJLambdaWrapper() .selectAll(CrmInvoiceDO.class) .selectAs(CrmCustomerDO::getName,CrmInvoiceRespVO::getCustomerName) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/rpc/config/RpcConfiguration.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/rpc/config/RpcConfiguration.java index f63794ba..a5d3507e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/rpc/config/RpcConfiguration.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/rpc/config/RpcConfiguration.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.framework.rpc.config; import cn.iocoder.yudao.module.bpm.api.oa.BpmOAContractApi; import cn.iocoder.yudao.module.bpm.api.oa.BpmOAReceiptApi; import cn.iocoder.yudao.module.bpm.api.oa.BpmOASalesPerformanceApi; +import cn.iocoder.yudao.module.hrm.api.crmbusiness.BusinessApi; import cn.iocoder.yudao.module.product.api.storeproduct.StoreProductApi; import cn.iocoder.yudao.module.product.api.storeproductattrvalue.StoreProductAttrValueApi; import cn.iocoder.yudao.module.system.api.auth.AdminOauthUserOtherInfoApi; @@ -19,6 +20,6 @@ import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) @EnableFeignClients(clients = {DeptApi.class, DictDataApi.class, AdminUserApi.class, StoreProductApi.class, StoreProductAttrValueApi.class, SmsSendApi.class, MailSendApi.class, NoticeApi.class, - BpmOAContractApi.class, BpmOAReceiptApi.class, BpmOASalesPerformanceApi.class, AdminOauthUserOtherInfoApi.class, SubscribeMessageSendApi.class, RoleApi.class}) + BpmOAContractApi.class, BpmOAReceiptApi.class, BpmOASalesPerformanceApi.class, AdminOauthUserOtherInfoApi.class, SubscribeMessageSendApi.class, RoleApi.class, BusinessApi.class}) public class RpcConfiguration { } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/salesperformance/FollowUpCluesJob.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/salesperformance/FollowUpCluesJob.java new file mode 100644 index 00000000..26a9f7da --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/salesperformance/FollowUpCluesJob.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.crm.job.salesperformance; + +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; +import cn.iocoder.yudao.module.crm.service.crmclues.CrmCluesService; +import com.xxl.job.core.biz.model.ReturnT; +import com.xxl.job.core.handler.annotation.XxlJob; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +@Component +@Slf4j +public class FollowUpCluesJob { + + // TODO: 2024/11/04 - 每天晚上2点 执行一次 判断三天内是否有跟进 + @Resource + private CrmCluesService cluesService; + + @XxlJob("followUpClues") + @TenantJob // --- ⚠️ 这个注解 会将租户列表拉出来 完了后逐个租户执行 定时任务需要注意 + public ReturnT execute() { + log.info("开始 线索跟进任务"); + cluesService.autoConfirmJob(); + log.info("结束 线索跟进任务"); + return ReturnT.SUCCESS; + } +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmanalysis/CustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmanalysis/CustomerServiceImpl.java index 5a9851e5..8d5bf933 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmanalysis/CustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmanalysis/CustomerServiceImpl.java @@ -137,7 +137,7 @@ public class CustomerServiceImpl implements CustomerService { pageResult1.getList().forEach(v -> { - String per = "0"; + String per = "0.00"; if (customerMap.get(v.getId()) == null) { v.setCustomerCount(0L); v.setSuccessCount(0L); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmbusiness/CrmBusinessService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmbusiness/CrmBusinessService.java index 7e31454f..e4e4739d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmbusiness/CrmBusinessService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmbusiness/CrmBusinessService.java @@ -72,4 +72,12 @@ public interface CrmBusinessService { * @param transferVO */ void transfer(@Valid CrmBusinessTransferVO transferVO); + + /** + * 更新商机状态 + * + * @param id + * @param isEnd + */ + void updateIsEnd(Long id, Integer isEnd); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmbusiness/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmbusiness/CrmBusinessServiceImpl.java index 00db0811..fbcafa7e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmbusiness/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmbusiness/CrmBusinessServiceImpl.java @@ -205,6 +205,14 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { } } + @Override + public void updateIsEnd(Long id, Integer isEnd) { + CrmBusinessDO businessDO = new CrmBusinessDO(); + businessDO.setId(id); + businessDO.setIsEnd(isEnd); + businessMapper.updateById(businessDO); + } + private void createBusinessProductList(Long businessId, List list) { list.forEach(o -> o.setBusinessId(businessId)); businessProductMapper.insertBatch(list); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmclues/CrmCluesService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmclues/CrmCluesService.java index 941b94c7..053a2a34 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmclues/CrmCluesService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmclues/CrmCluesService.java @@ -57,27 +57,31 @@ public interface CrmCluesService { /** * 放入线索池 + * * @param id */ void openClues(Long id); /** * 领取线索 + * * @param id */ void receiveClues(Long id); /** * 线索转换成客户 + * * @param createReqVO */ void createCustomer(CrmCustomerSaveReqVO createReqVO); /** * 线索导入 + * * @param importUsers 导入文件 - * @param deptId 部门ID - * @param adminIds 用户ID + * @param deptId 部门ID + * @param adminIds 用户ID * @param averageType 导入类型 * @return */ @@ -85,14 +89,21 @@ public interface CrmCluesService { /** * 转移线索 + * * @param transferVO */ void transfer(CrmCluesTransferVO transferVO); /** * 获取指定用户的线索统计信息 + * * @param ownerUserIds 用户ID * @return 线索统计信息列表 */ List getCluesStatisticsByUserIds(List ownerUserIds, LocalDateTime[] createTime); + + /** + * 线索跟进任务 + */ + void autoConfirmJob(); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmclues/CrmCluesServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmclues/CrmCluesServiceImpl.java index cfb95f09..0555b462 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmclues/CrmCluesServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmclues/CrmCluesServiceImpl.java @@ -33,15 +33,11 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Random; +import java.util.*; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.CLUES_NOT_EXISTS; -import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.THIS_CUSTOMER_ALREADY_EXISTS_IN_THE_SYSTEM_AND_CANNOT_BE_ENTERED_REPEATEDLY; /** * 线索 Service 实现类 @@ -120,7 +116,7 @@ public class CrmCluesServiceImpl implements CrmCluesService { } else if (RelationEnum.SUB.getValue().equals(pageReqVO.getRelation())) { ids = userLiveTreeService.getItemIdsByUserId(adminId); } - if (CollUtil.isEmpty(ids)){ + if (CollUtil.isEmpty(ids)) { return PageResult.empty(); } IPage mpPage = MyBatisUtils.buildPage(pageReqVO); @@ -158,15 +154,14 @@ public class CrmCluesServiceImpl implements CrmCluesService { if (crmCluesDO == null) { throw exception(CLUES_NOT_EXISTS); } - if(CluesStatusEnum.STATUS_1.getValue().equals(crmCluesDO.getStatus())){ - throw exception(new ErrorCode(202411160,"已经转化成客户!")); + if (CluesStatusEnum.STATUS_1.getValue().equals(crmCluesDO.getStatus())) { + throw exception(new ErrorCode(202411160, "已经转化成客户!")); } // 判断客户名称是否唯一 - Long count = customerMapper.selectCount(new LambdaQueryWrapper() - .eq(CrmCustomerDO::getName, createReqVO.getName())); - if (count > 0) { - throw exception(THIS_CUSTOMER_ALREADY_EXISTS_IN_THE_SYSTEM_AND_CANNOT_BE_ENTERED_REPEATEDLY); - } + List repeatOwnerUserNameList = customerMapper.getRepeatOwnerUserName(createReqVO.getName()); + if (CollUtil.isNotEmpty(repeatOwnerUserNameList) && createReqVO.getRepeatConfirmationFlag() == 0) { + List items = repeatOwnerUserNameList.stream().distinct().collect(Collectors.toList()); + throw exception(new ErrorCode(200012, "该客户已被:" + String.join(",", items) + "添加过,是否继续添加?")); } createReqVO.setId(null); CrmCustomerDO customerDO = BeanUtils.toBean(createReqVO, CrmCustomerDO.class); customerDO.setOwnerUserId(SecurityFrameworkUtils.getLoginUserId()); @@ -286,4 +281,19 @@ public class CrmCluesServiceImpl implements CrmCluesService { return cluesMapper.selectStatisticsByUserIds(ownerUserIds, createTime); } + @Override + public void autoConfirmJob() { + // 获取负责人不为0 并且跟进记录为3天以外的数据 + List crmCluesDOS = cluesMapper.selectList(new LambdaQueryWrapper() + .ne(CrmCluesDO::getOwnerUserId, 0) + .in(CrmCluesDO::getStatus, Arrays.asList(CluesStatusEnum.STATUS_0.getValue(), CluesStatusEnum.STATUS_NEG_1.getValue())) + .le(CrmCluesDO::getFollowTime, LocalDateTime.now().minusDays(3))); + for (CrmCluesDO crmCluesDO : crmCluesDOS) { + crmCluesDO.setOwnerUserId(0L); + } + if (CollUtil.isNotEmpty(crmCluesDOS)) { + cluesMapper.updateBatch(crmCluesDOS); + } + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmcustomer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmcustomer/CrmCustomerService.java index 093f73a9..26663337 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmcustomer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmcustomer/CrmCustomerService.java @@ -82,12 +82,11 @@ public interface CrmCustomerService { /** * 客户导入 * @param importUsers 导入文件 - * @param deptId 部门ID * @param adminIds 用户ID * @param averageType 导入类型 * @return */ - CustomerImportRespVO importList(List importUsers, String deptId, String adminIds, Integer averageType); + CustomerImportRespVO importList(List importUsers, String adminIds, Integer averageType,Integer repeatConfirmationFlag); /** diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmcustomer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmcustomer/CrmCustomerServiceImpl.java index 3f3872f2..a4b742af 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmcustomer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmcustomer/CrmCustomerServiceImpl.java @@ -32,8 +32,6 @@ import cn.iocoder.yudao.module.system.api.mail.dto.MailSendSingleReqDTO; import cn.iocoder.yudao.module.system.api.sms.SmsSendApi; import cn.iocoder.yudao.module.system.api.sms.dto.send.SmsSendSingleReqDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserApiDTO; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserApiVO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import org.springframework.stereotype.Service; @@ -42,15 +40,11 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Random; +import java.util.*; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; -import static cn.iocoder.yudao.module.hrm.enums.ErrorCodeConstants.THIS_CUSTOMER_ALREADY_EXISTS_IN_THE_SYSTEM_AND_CANNOT_BE_ENTERED_REPEATEDLY; /** * 客户 Service 实现类 @@ -88,17 +82,18 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) public Long createCustomer(CrmCustomerSaveReqVO createReqVO) { - // 插入 // 判断客户名称是否唯一 - Long count = customerMapper.selectCount(new LambdaQueryWrapper() - .eq(CrmCustomerDO::getName, createReqVO.getName())); - if (count > 0) { - throw exception(THIS_CUSTOMER_ALREADY_EXISTS_IN_THE_SYSTEM_AND_CANNOT_BE_ENTERED_REPEATEDLY); + List repeatOwnerUserNameList = customerMapper.getRepeatOwnerUserName(createReqVO.getName()); + if (CollUtil.isNotEmpty(repeatOwnerUserNameList) && createReqVO.getRepeatConfirmationFlag() == 0) { + List items = repeatOwnerUserNameList.stream().distinct().collect(Collectors.toList()); + throw exception(new ErrorCode(200012, "该客户已被:" + String.join(",", items) + "添加过,是否继续添加?")); } CrmCustomerDO customer = BeanUtils.toBean(createReqVO, CrmCustomerDO.class); customer.setCollectTime(LocalDateTime.now()); customer.setFollowTime(LocalDateTime.now()); + // 由于这里是 size 而排序是从0开始的 所以这里递增一个直接用size即可 + customer.setSortNum(repeatOwnerUserNameList.size()); customer.setOwnerUserId(SecurityFrameworkUtils.getLoginUserId()); customerMapper.insert(customer); @@ -126,8 +121,17 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { public void updateCustomer(CrmCustomerSaveReqVO updateReqVO) { // 校验存在 CrmCustomerDO customerDO = validateCustomerExists(updateReqVO.getId()); + List repeatOwnerUserNameList = customerMapper.getRepeatOwnerUserName(updateReqVO.getName()); + if (!customerDO.getName().equals(updateReqVO.getName()) + && CollUtil.isNotEmpty(repeatOwnerUserNameList) + && updateReqVO.getRepeatConfirmationFlag() == 0) { + List items = repeatOwnerUserNameList.stream().distinct().collect(Collectors.toList()); + throw exception(new ErrorCode(200012, "该客户已被:" + String.join(",", items) + "添加过,是否继续添加?")); } + // 更新 CrmCustomerDO updateObj = BeanUtils.toBean(updateReqVO, CrmCustomerDO.class); + // 由于这里是 size 而排序是从0开始的 所以这里递增一个直接用size即可 + updateObj.setSortNum(repeatOwnerUserNameList.size()); customerMapper.updateById(updateObj); //插入日志 @@ -255,7 +259,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { if (CollUtil.isEmpty(ids)) { return PageResult.empty(); } - return customerMapper.selectPage(pageReqVO, ids); + IPage pageResult; + if (pageReqVO.getDistinctFlag() == 0) { + return customerMapper.selectPage(pageReqVO, ids); + } else { + IPage mpPage = MyBatisUtils.buildPage(pageReqVO); + pageResult = customerMapper.selectPageList(mpPage, pageReqVO, ids); + } + return new PageResult<>(pageResult.getRecords(), pageResult.getTotal()); } @@ -276,42 +287,46 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { return PageResult.empty(); } IPage mpPage = MyBatisUtils.buildPage(pageReqVO); - IPage pageResult = customerMapper.selectPageList(mpPage, pageReqVO, ids); + IPage pageResult = customerMapper.selectPageList2(mpPage, pageReqVO, ids); return new PageResult<>(pageResult.getRecords(), pageResult.getTotal()); } @Override - public CustomerImportRespVO importList(List importUsers, String deptId, String adminIds, - Integer averageType) { + public CustomerImportRespVO importList(List importUsers, String adminIds, + Integer averageType, Integer repeatConfirmationFlag) { CustomerImportRespVO respVO = CustomerImportRespVO.builder().createNames(new ArrayList<>()) .failureNames(new LinkedHashMap<>()).build(); //处理客户归属方案 //如果只选择了机构没有选择用户直接获取当前部门下的用户 List userList = new ArrayList<>(); - if (StrUtil.isNotEmpty(deptId) && StrUtil.isEmpty(adminIds)) { - List adminUserDOS = adminUserApi.getUserList(new AdminUserApiDTO().setDeptId(Long.valueOf(deptId)).setNextDept(1)).getCheckedData(); - userList = adminUserDOS.stream().map(AdminUserApiVO::getId).collect(Collectors.toList()); - if (userList.isEmpty()) { - throw exception(new ErrorCode(202409080, "当前部门下没有用户,清重新选择")); - } - } else { + if (StrUtil.isNotEmpty(adminIds)) { userList = StrUtil.split(adminIds, ",").stream().map(Long::parseLong).collect(Collectors.toList()); } - - int i = 1; int j = 0; int adminCount = userList.size(); + List customerList = new ArrayList<>(); + // -- 查询重复 + Map map = new HashMap<>(); + if (repeatConfirmationFlag == 0) { + List nameList = importUsers.stream().map(CrmCustomerImportVO::getName).filter(StrUtil::isNotEmpty).distinct().collect(Collectors.toList()); + if (CollUtil.isNotEmpty(nameList)) { + List crmCustomerDOS = customerMapper.selectList(new LambdaQueryWrapper() + .in(CrmCustomerDO::getName, nameList)); + map = crmCustomerDOS.stream().collect(Collectors.groupingBy(CrmCustomerDO::getName, Collectors.summingInt(e -> 1))); + } + } for (CrmCustomerImportVO importVO : importUsers) { if (StrUtil.isEmpty(importVO.getName())) { respVO.getFailureNames().put("第" + i + "行:", "客户名称为空,已经被过滤掉"); continue; } - Long count = customerMapper.selectCount(new LambdaQueryWrapper() - .eq(CrmCustomerDO::getName, importVO.getName())); - if (count > 0) { - respVO.getFailureNames().put("第" + i + "行:", "客户名称已经存在,已经被过滤掉"); - continue; + if (repeatConfirmationFlag == 0) { + Integer num = map.get(importVO.getName()); + if (num != null && num > 1) { + respVO.getFailureNames().put("第" + i + "行:", "客户名称重复,已经被过滤掉"); + continue; + } } CrmCustomerDO customer = BeanUtils.toBean(importVO, CrmCustomerDO.class); Long adminId = 0L; @@ -329,11 +344,22 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { int num = random.nextInt(adminCount); adminId = userList.get(num); } + Integer num = map.get(importVO.getName()); + if (num != null && num > 1) { + map.put(importVO.getName(), num + 1); + } else if (num == null) { + num = 0; + map.put(importVO.getName(), num); + } + customer.setSortNum(num); customer.setOwnerUserId(adminId); - customerMapper.insert(customer); + customerList.add(customer); respVO.getCreateNames().add("第" + i + "行:导入成功用户名->" + importVO.getName()); i++; } + if (!customerList.isEmpty()) { + customerMapper.insertBatch(customerList); + } return respVO; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmcustomercontacts/CrmCustomerContactsServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmcustomercontacts/CrmCustomerContactsServiceImpl.java index 8b626279..d1713e1d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmcustomercontacts/CrmCustomerContactsServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crmcustomercontacts/CrmCustomerContactsServiceImpl.java @@ -92,9 +92,6 @@ public class CrmCustomerContactsServiceImpl implements CrmCustomerContactsServic } else if (RelationEnum.SUB.getValue().equals(pageReqVO.getRelation())) { ids = userLiveTreeService.getItemIdsByUserId(adminId); } - if (CollUtil.isEmpty(ids)){ - return PageResult.empty(); - } IPage mpPage = MyBatisUtils.buildPage(pageReqVO); IPage pageResult = customerContactsMapper.selectPageList(mpPage, pageReqVO, ids); return new PageResult<>(pageResult.getRecords(), pageResult.getTotal()); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crminvoice/CrmInvoiceServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crminvoice/CrmInvoiceServiceImpl.java index 54a2acbd..59f65c1e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crminvoice/CrmInvoiceServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/crminvoice/CrmInvoiceServiceImpl.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.enums.ShopCommonEnum; import cn.iocoder.yudao.framework.common.exception.ErrorCode; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.crm.controller.admin.crmcontract.vo.CheckInfoVO; import cn.iocoder.yudao.module.crm.controller.admin.crminvoice.vo.CrmInvoicePageReqVO; @@ -28,6 +29,7 @@ import cn.iocoder.yudao.module.hrm.enums.*; import cn.iocoder.yudao.module.system.api.mail.MailSendApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; import lombok.extern.slf4j.Slf4j; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/crmclues/CrmCluesMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/crmclues/CrmCluesMapper.xml index 990365c9..663db18c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/crmclues/CrmCluesMapper.xml +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/crmclues/CrmCluesMapper.xml @@ -18,6 +18,7 @@ left join system_users b ON b.id = a.owner_user_id a.deleted = 0 + and a.status != 1 and a.name like concat('%', #{dto.name}, '%') diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/crmcustomer/CrmCustomerMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/crmcustomer/CrmCustomerMapper.xml index 4fcd69a9..d017ec19 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/crmcustomer/CrmCustomerMapper.xml +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/crmcustomer/CrmCustomerMapper.xml @@ -9,7 +9,7 @@ 文档可见:https://www.yixiang.co/MyBatis/x-plugins/ --> - + + diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/crminvoice/CrminvoiceMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/crminvoice/CrminvoiceMapper.xml new file mode 100644 index 00000000..8c89f537 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/crminvoice/CrminvoiceMapper.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/storeproduct/StoreProductServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/storeproduct/StoreProductServiceImpl.java index c9edee88..0c97f845 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/storeproduct/StoreProductServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/storeproduct/StoreProductServiceImpl.java @@ -667,9 +667,9 @@ public class StoreProductServiceImpl extends ServiceImpl