CRM:完善联系人的编辑、详情

This commit is contained in:
YunaiV 2024-02-20 23:32:26 +08:00
parent 66a34a6d90
commit 7dd35f3295
10 changed files with 81 additions and 101 deletions

View File

@ -75,6 +75,8 @@ public interface LogRecordConstants {
String CRM_CONTACT_DELETE_SUCCESS = "删除了联系人【{{#contactName}}】";
String CRM_CONTACT_TRANSFER_SUB_TYPE = "转移联系人";
String CRM_CONTACT_TRANSFER_SUCCESS = "将联系人【{{#contact.name}}】的负责人从【{getAdminUserById{#contact.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】";
String CRM_CONTACT_FOLLOW_UP_SUB_TYPE = "联系人跟进";
String CRM_CONTACT_FOLLOW_UP_SUCCESS = "联系人跟进【{{#contactName}}】";
// ======================= CRM_BUSINESS 商机 =======================

View File

@ -118,7 +118,7 @@ public class CrmContactController {
@Operation(summary = "获得联系人的精简列表")
@PreAuthorize("@ss.hasPermission('crm:contact:query')")
public CommonResult<List<CrmContactRespVO>> getSimpleContactList() {
List<CrmContactDO> list = contactService.getSimpleContactList(getLoginUserId());
List<CrmContactDO> list = contactService.getContactList(getLoginUserId());
return success(convertList(list, contact -> // 只返回 idname 字段
new CrmContactRespVO().setId(contact.getId()).setName(contact.getName())));
}

View File

@ -27,6 +27,7 @@ public class CrmContactSaveReqVO {
private String name;
@Schema(description = "客户编号", example = "10795")
@NotNull(message = "客户编号不能为空")
@DiffLogField(name = "客户", function = CrmCustomerParseFunction.NAME)
private Long customerId;

View File

@ -1,35 +0,0 @@
package cn.iocoder.yudao.module.crm.convert.contact;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactRespVO;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* CRM 联系人 Convert
*
* @author 芋道源码
*/
@Mapper
public interface CrmContactConvert {
CrmContactConvert INSTANCE = Mappers.getMapper(CrmContactConvert.class);
@Mapping(target = "bizId", source = "reqVO.id")
CrmPermissionTransferReqBO convert(CrmContactTransferReqVO reqVO, Long userId);
@Mapping(target = "id", source = "reqBO.bizId")
CrmContactDO convert(CrmUpdateFollowUpReqBO reqBO);
default List<CrmContactDO> convertList(List<CrmUpdateFollowUpReqBO> list) {
return CollectionUtils.convertList(list, INSTANCE::convert);
}
}

View File

@ -22,12 +22,6 @@ import java.util.List;
@Mapper
public interface CrmContactMapper extends BaseMapperX<CrmContactDO> {
default int updateOwnerUserIdById(Long id, Long ownerUserId) {
return update(new LambdaUpdateWrapper<CrmContactDO>()
.eq(CrmContactDO::getId, id)
.set(CrmContactDO::getOwnerUserId, ownerUserId));
}
default int updateOwnerUserIdByCustomerId(Long customerId, Long ownerUserId) {
return update(new LambdaUpdateWrapper<CrmContactDO>()
.eq(CrmContactDO::getCustomerId, customerId)

View File

@ -6,9 +6,9 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReq
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
import jakarta.validation.Valid;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@ -54,7 +54,7 @@ public interface CrmContactService {
void transferContact(CrmContactTransferReqVO reqVO, Long userId);
/**
* 更新客户联系人负责人
* 更新指定客户联系人负责人
*
* @param customerId 客户编号
* @param ownerUserId 用户编号
@ -64,9 +64,20 @@ public interface CrmContactService {
/**
* 更新联系人相关跟进信息
*
* @param updateFollowUpReqBOList 跟进信息
* @param id 编号
* @param contactNextTime 下次联系时间
* @param contactLastContent 最后联系内容
*/
void updateContactFollowUpBatch(List<CrmUpdateFollowUpReqBO> updateFollowUpReqBOList);
void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent);
/**
* 更新联系人相关跟进信息
*
* @param ids 编号数组
* @param contactNextTime 下次联系时间
* @param contactLastContent 最后联系内容
*/
void updateContactFollowUpBatch(Collection<Long> ids, LocalDateTime contactNextTime, String contactLastContent);
/**
* 获得联系人
@ -103,20 +114,13 @@ public interface CrmContactService {
return convertMap(getContactList(ids), CrmContactDO::getId);
}
/**
* 获得联系人列表
*
* @return 联系人列表
*/
List<CrmContactDO> getContactList();
/**
* 获取联系人列表校验权限
*
* @param userId 用户编号
* @return 联系人列表
*/
List<CrmContactDO> getSimpleContactList(Long userId);
List<CrmContactDO> getContactList(Long userId);
/**
* 获得联系人分页

View File

@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusines
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper;
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
@ -17,9 +16,9 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm
import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import com.mzt.logapi.context.LogRecordContext;
import com.mzt.logapi.service.impl.DiffParseFunction;
@ -30,14 +29,15 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;
import static java.util.Collections.singletonList;
/**
@ -73,7 +73,7 @@ public class CrmContactServiceImpl implements CrmContactService {
success = CRM_CONTACT_CREATE_SUCCESS)
public Long createContact(CrmContactSaveReqVO createReqVO, Long userId) {
createReqVO.setId(null);
// 1. 校验
// 1. 校验关联数据
validateRelationDataExists(createReqVO);
// 2. 插入联系人
@ -102,8 +102,9 @@ public class CrmContactServiceImpl implements CrmContactService {
success = CRM_CONTACT_UPDATE_SUCCESS)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
public void updateContact(CrmContactSaveReqVO updateReqVO) {
// 1. 校验存在
// 1.1 校验存在
CrmContactDO oldContact = validateContactExists(updateReqVO.getId());
// 1.2 校验关联数据
validateRelationDataExists(updateReqVO);
// 2. 更新联系人
@ -123,15 +124,15 @@ public class CrmContactServiceImpl implements CrmContactService {
private void validateRelationDataExists(CrmContactSaveReqVO saveReqVO) {
// 1. 校验客户
if (saveReqVO.getCustomerId() != null && customerService.getCustomer(saveReqVO.getCustomerId()) == null) {
throw exception(CUSTOMER_NOT_EXISTS);
customerService.validateCustomer(saveReqVO.getCustomerId());
}
// 2. 校验负责人
if (saveReqVO.getOwnerUserId() != null && adminUserApi.getUser(saveReqVO.getOwnerUserId()) == null) {
throw exception(USER_NOT_EXISTS);
if (saveReqVO.getOwnerUserId() != null) {
adminUserApi.validateUser(saveReqVO.getOwnerUserId());
}
// 3. 直属上级
if (saveReqVO.getParentId() != null && contactMapper.selectById(saveReqVO.getParentId()) == null) {
throw exception(CONTACT_NOT_EXISTS);
if (saveReqVO.getParentId() != null) {
validateContactExists(saveReqVO.getParentId());
}
// 4. 如果有关联商机则需要校验存在
if (saveReqVO.getBusinessId() != null && businessService.getBusiness(saveReqVO.getBusinessId()) == null) {
@ -165,11 +166,11 @@ public class CrmContactServiceImpl implements CrmContactService {
}
private CrmContactDO validateContactExists(Long id) {
CrmContactDO contactDO = contactMapper.selectById(id);
if (contactDO == null) {
CrmContactDO contact = contactMapper.selectById(id);
if (contact == null) {
throw exception(CONTACT_NOT_EXISTS);
}
return contactDO;
return contact;
}
@Override
@ -182,10 +183,10 @@ public class CrmContactServiceImpl implements CrmContactService {
CrmContactDO contact = validateContactExists(reqVO.getId());
// 2.1 数据权限转移
permissionService.transferPermission(
CrmContactConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()));
permissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_CONTACT.getType(),
reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel()));
// 2.2 设置新的负责人
contactMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
contactMapper.updateById(new CrmContactDO().setId(reqVO.getId()).setOwnerUserId(reqVO.getNewOwnerUserId()));
// 3. 记录转移日志
LogRecordContext.putVariable("contact", contact);
@ -194,11 +195,30 @@ public class CrmContactServiceImpl implements CrmContactService {
@Override
public void updateOwnerUserIdByCustomerId(Long customerId, Long ownerUserId) {
contactMapper.updateOwnerUserIdByCustomerId(customerId, ownerUserId);
// TODO @puhui999操作日志数据权限
}
@Override
public void updateContactFollowUpBatch(List<CrmUpdateFollowUpReqBO> updateFollowUpReqBOList) {
contactMapper.updateBatch(CrmContactConvert.INSTANCE.convertList(updateFollowUpReqBOList));
@LogRecord(type = CRM_CONTACT_TYPE, subType = CRM_CONTACT_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}",
success = CRM_CONTACT_FOLLOW_UP_SUCCESS)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.WRITE)
public void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) {
// 1.1 校验存在
CrmContactDO contact = validateContactExists(id);
// 2. 更新联系人的跟进信息
contactMapper.updateById(new CrmContactDO().setId(id).setContactNextTime(contactNextTime)
.setContactLastTime(LocalDateTime.now()).setContactLastContent(contactLastContent));
// 3. 记录操作日志上下文
LogRecordContext.putVariable("contactName", contact.getName());
}
@Override
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#ids", level = CrmPermissionLevelEnum.WRITE)
public void updateContactFollowUpBatch(Collection<Long> ids, LocalDateTime contactNextTime, String contactLastContent) {
contactMapper.updateBatch(convertList(ids, id -> new CrmContactDO().setId(id).setContactLastTime(LocalDateTime.now())
.setContactNextTime(contactNextTime).setContactLastContent(contactLastContent)));
}
//======================= 查询相关 =======================
@ -226,12 +246,7 @@ public class CrmContactServiceImpl implements CrmContactService {
}
@Override
public List<CrmContactDO> getContactList() {
return contactMapper.selectList();
}
@Override
public List<CrmContactDO> getSimpleContactList(Long userId) {
public List<CrmContactDO> getContactList(Long userId) {
CrmContactPageReqVO reqVO = new CrmContactPageReqVO();
reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页
return contactMapper.selectPage(reqVO, userId).getList();

View File

@ -132,9 +132,9 @@ public interface CrmCustomerService {
/**
* 校验客户是否存在
*
* @param customerId 客户 id
* @param id 编号
*/
void validateCustomer(Long customerId);
void validateCustomer(Long id);
/**
* 客户转移

View File

@ -164,7 +164,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
// 2. 更新客户的跟进信息
customerMapper.updateById(new CrmCustomerDO().setId(id).setFollowUpStatus(true).setContactNextTime(contactNextTime)
.setContactLastTime(LocalDateTime.now()));
.setContactLastTime(LocalDateTime.now()).setContactLastContent(contactLastContent));
// 3. 记录操作日志上下文
LogRecordContext.putVariable("customerName", customer.getName());
@ -521,11 +521,11 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
/**
* 校验客户是否存在
*
* @param customerId 客户 id
* @param id 客户 id
*/
@Override
public void validateCustomer(Long customerId) {
validateCustomerExists(customerId);
public void validateCustomer(Long id) {
validateCustomerExists(id);
}
private void validateCustomerOwnerExists(CrmCustomerDO customer, Boolean pool) {

View File

@ -68,41 +68,40 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService {
@Override
@CrmPermission(bizTypeValue = "#createReqVO.bizType", bizId = "#createReqVO.bizId", level = CrmPermissionLevelEnum.WRITE)
public Long createFollowUpRecord(CrmFollowUpRecordSaveReqVO createReqVO) {
// 创建更进记录
CrmFollowUpRecordDO followUpRecord = BeanUtils.toBean(createReqVO, CrmFollowUpRecordDO.class);
crmFollowUpRecordMapper.insert(followUpRecord);
// 1. 创建更进记录
CrmFollowUpRecordDO record = BeanUtils.toBean(createReqVO, CrmFollowUpRecordDO.class);
crmFollowUpRecordMapper.insert(record);
// 2. 更新 bizId 对应的记录
CrmUpdateFollowUpReqBO updateFollowUpReqBO = new CrmUpdateFollowUpReqBO().setBizId(followUpRecord.getBizId())
// 2. 更新 bizId 对应的记录
CrmUpdateFollowUpReqBO updateFollowUpReqBO = new CrmUpdateFollowUpReqBO().setBizId(record.getBizId())
.setContactLastTime(LocalDateTime.now())
.setContactNextTime(followUpRecord.getNextTime()).setContactLastContent(followUpRecord.getContent());
if (ObjUtil.equal(CrmBizTypeEnum.CRM_BUSINESS.getType(), followUpRecord.getBizType())) { // 更新商机跟进信息
.setContactNextTime(record.getNextTime()).setContactLastContent(record.getContent());
if (ObjUtil.equal(CrmBizTypeEnum.CRM_BUSINESS.getType(), record.getBizType())) { // 更新商机跟进信息
businessService.updateBusinessFollowUpBatch(Collections.singletonList(updateFollowUpReqBO));
}
if (ObjUtil.equal(CrmBizTypeEnum.CRM_CLUE.getType(), followUpRecord.getBizType())) { // 更新线索跟进信息
clueService.updateClueFollowUp(followUpRecord.getId(), followUpRecord.getNextTime(), followUpRecord.getContent());
if (ObjUtil.equal(CrmBizTypeEnum.CRM_CLUE.getType(), record.getBizType())) { // 更新线索跟进信息
clueService.updateClueFollowUp(record.getBizId(), record.getNextTime(), record.getContent());
}
if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTACT.getType(), followUpRecord.getBizType())) { // 更新联系人跟进信息
contactService.updateContactFollowUpBatch(Collections.singletonList(updateFollowUpReqBO));
if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTACT.getType(), record.getBizType())) { // 更新联系人跟进信息
contactService.updateContactFollowUp(record.getBizId(), record.getNextTime(), record.getContent());
}
if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTRACT.getType(), followUpRecord.getBizType())) { // 更新合同跟进信息
if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTRACT.getType(), record.getBizType())) { // 更新合同跟进信息
contractService.updateContractFollowUp(updateFollowUpReqBO);
}
if (ObjUtil.equal(CrmBizTypeEnum.CRM_CUSTOMER.getType(), followUpRecord.getBizType())) { // 更新客户跟进信息
customerService.updateCustomerFollowUp(followUpRecord.getBizId(), followUpRecord.getNextTime(), followUpRecord.getContent());
if (ObjUtil.equal(CrmBizTypeEnum.CRM_CUSTOMER.getType(), record.getBizType())) { // 更新客户跟进信息
customerService.updateCustomerFollowUp(record.getBizId(), record.getNextTime(), record.getContent());
}
// 3.1 更新 contactIds 对应的记录不更新 lastTime lastContent
if (CollUtil.isNotEmpty(createReqVO.getContactIds())) {
contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(),
contactId -> updateFollowUpReqBO.setBizId(contactId).setContactLastTime(null).setContactLastContent(null)));
contactService.updateContactFollowUpBatch(createReqVO.getContactIds(), null, null);
}
// 3.2 需要更新 businessIds 对应的记录不更新 lastTime lastContent
if (CollUtil.isNotEmpty(createReqVO.getBusinessIds())) {
businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(),
businessId -> updateFollowUpReqBO.setBizId(businessId).setContactLastTime(null).setContactLastContent(null)));
}
return followUpRecord.getId();
return record.getId();
}
@Override