diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java index a3acd04f6..f1087c4ec 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java @@ -1,13 +1,22 @@ package cn.iocoder.yudao.module.crm.controller.admin.clue; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.clue.CrmClueService; +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +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; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -19,10 +28,15 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.io.IOException; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -34,6 +48,13 @@ public class CrmClueController { @Resource private CrmClueService clueService; + @Resource + private CrmCustomerService customerService; + + @Resource + private AdminUserApi adminUserApi; + @Resource + private DeptApi deptApi; @PostMapping("/create") @Operation(summary = "创建线索") @@ -73,7 +94,7 @@ public class CrmClueController { @PreAuthorize("@ss.hasPermission('crm:clue:query')") public CommonResult> getCluePage(@Valid CrmCluePageReqVO pageVO) { PageResult pageResult = clueService.getCluePage(pageVO, getLoginUserId()); - return success(BeanUtils.toBean(pageResult, CrmClueRespVO.class)); + return success(new PageResult<>(buildClueDetailList(pageResult.getList()), pageResult.getTotal())); } @GetMapping("/export-excel") @@ -84,8 +105,32 @@ public class CrmClueController { pageReqVO.setPageSize(PAGE_SIZE_NONE); List list = clueService.getCluePage(pageReqVO, getLoginUserId()).getList(); // 导出 Excel - List datas = BeanUtils.toBean(list, CrmClueRespVO.class); - ExcelUtils.write(response, "线索.xls", "数据", CrmClueRespVO.class, datas); + ExcelUtils.write(response, "线索.xls", "数据", CrmClueRespVO.class, buildClueDetailList(list)); + } + + private List buildClueDetailList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1.1 获取客户列表 + Map customerMap = customerService.getCustomerMap( + convertSet(list, CrmClueDO::getCustomerId)); + // 1.2 获取创建人、负责人列表 + Map userMap = adminUserApi.getUserMap(convertListByFlatMap(list, + contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); + Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); + // 2. 转换成 VO + return BeanUtils.toBean(list, CrmClueRespVO.class, clueVO -> { + // 2.1 设置客户名称 + MapUtils.findAndThen(customerMap, clueVO.getCustomerId(), customer -> clueVO.setCustomerName(customer.getName())); + // 2.2 设置创建人、负责人名称 + MapUtils.findAndThen(userMap, NumberUtils.parseLong(clueVO.getCreator()), + user -> clueVO.setCreatorName(user.getNickname())); + MapUtils.findAndThen(userMap, clueVO.getOwnerUserId(), user -> { + clueVO.setOwnerUserName(user.getNickname()); + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> clueVO.setOwnerUserDeptName(dept.getName())); + }); + }); } @PutMapping("/transfer") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java index b36c0a51d..880e818ef 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java @@ -8,12 +8,9 @@ import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - @Schema(description = "管理后台 - 线索 Response VO") @Data @ToString(callSuper = true) @@ -34,19 +31,25 @@ public class CrmClueRespVO { private Boolean followUpStatus; @Schema(description = "最后跟进时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @ExcelProperty("最后跟进时间") private LocalDateTime contactLastTime; + @Schema(description = "最后跟进内容", example = "吃饭、睡觉、打逗逗") + @ExcelProperty("最后跟进内容") + private String contactLastContent; + @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @ExcelProperty("下次联系时间") private LocalDateTime contactNextTime; @Schema(description = "负责人编号") - @ExcelProperty("负责人的用户编号") - // TODO 这里需要导出成负责人的名字 private Long ownerUserId; + @Schema(description = "负责人名字", example = "25682") + @ExcelProperty("负责人名字") + private String ownerUserName; + @Schema(description = "负责人部门") + @ExcelProperty("负责人部门") + private String ownerUserDeptName; @Schema(description = "转化状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") @ExcelProperty(value = "转化状态", converter = DictConvert.class) @@ -54,9 +57,10 @@ public class CrmClueRespVO { private Boolean transformStatus; @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "520") - // TODO 这里需要导出成客户名称 - @ExcelProperty("客户编号") private Long customerId; + @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "客户名称") + @ExcelProperty("客户名称") + private String customerName; @Schema(description = "手机号", example = "18000000000") @ExcelProperty("手机号") @@ -109,8 +113,19 @@ public class CrmClueRespVO { @ExcelProperty("备注") private String remark; + @Schema(description = "创建人", example = "1024") + @ExcelProperty("创建人") + private String creator; + @Schema(description = "创建人名字", example = "芋道源码") + @ExcelProperty("创建人名字") + private String creatorName; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("创建时间") private LocalDateTime createTime; + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("更新时间") + private LocalDateTime updateTime; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 3c1806d51..b89eb9feb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -56,6 +56,7 @@ public class CrmCustomerController { private CrmCustomerService customerService; @Resource private CrmCustomerPoolConfigService customerPoolConfigService; + @Resource private DeptApi deptApi; @Resource diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java index 44a628503..5ff910e1a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java @@ -40,9 +40,13 @@ public class CrmClueDO extends BaseDO { */ private Boolean followUpStatus; /** - * 最后跟进时间 TODO 添加跟进记录时更新该值 + * 最后跟进时间 */ private LocalDateTime contactLastTime; + /** + * 最后跟进内容 + */ + private String contactLastContent; /** * 下次联系时间 */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 209b54fbc..56f760795 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -35,6 +35,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -81,7 +82,8 @@ public class CrmClueServiceImpl implements CrmClueService { } // 2. 插入 - CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class).setId(null); + CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class) + .setContactLastTime(LocalDateTime.now()); clueMapper.insert(clue); // 3. 创建数据权限 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java index 919cc293c..300ca86a2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; @@ -127,13 +128,20 @@ public interface CrmContractService { Long getContractCountByCustomerId(Long customerId); /** - * 根据商机ID获取关联客户的合同数量 + * 根据商机编号,获取关联客户的合同数量 * * @param businessId 商机编号 * @return 数量 */ Long getContractCountByBusinessId(Long businessId); + /** + * 根据合同编号,获得合同的产品列表 + * + * @param contactId 合同编号 + * @return 产品列表 + */ + List getContractProductListByContractId(Long contactId); /** * 获得待审核合同数量 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index cd1f5ece3..5e675e0ed 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -10,6 +10,9 @@ import jakarta.validation.Valid; import java.util.Collection; import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * 客户 Service 接口 @@ -58,6 +61,16 @@ public interface CrmCustomerService { */ List getCustomerList(Collection ids); + /** + * 获得客户 Map + * + * @param ids 客户编号数组 + * @return 客户 Map + */ + default Map getCustomerMap(Collection ids) { + return convertMap(getCustomerList(ids), CrmCustomerDO::getId); + } + /** * 获得客户分页 *