📖 CRM:code review crm 联系人新增操作日志

This commit is contained in:
YunaiV 2024-01-07 18:19:08 +08:00
parent 450cd1baf1
commit 19d5a0c2aa
23 changed files with 163 additions and 187 deletions

View File

@ -24,7 +24,8 @@ public interface ErrorCodeConstants {
// ========== 联系人管理 1-020-003-000 ==========
ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在");
ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode( 1_020_003_001, "联系人商机关联不存在");
ErrorCode CONTACT_CONTRACT_LINK_EXISTS = new ErrorCode( 1_020_003_002, "联系人已关联合同,不能删除");
ErrorCode CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS = new ErrorCode( 1_020_003_002, "联系人已关联合同,不能删除");
// ========== 回款 1-020-004-000 ==========
ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在");

View File

@ -1,8 +1,6 @@
package cn.iocoder.yudao.module.crm.controller.admin.business;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
@ -29,7 +27,6 @@ import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -99,7 +96,7 @@ public class CrmBusinessController {
@GetMapping("/page-by-customer")
@Operation(summary = "获得商机分页,基于指定客户")
public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPageByCustomer(@Valid CrmBusinessPageReqVO pageReqVO) {
if(pageReqVO.getCustomerId() == null){
if (pageReqVO.getCustomerId() == null) {
throw exception(CUSTOMER_NOT_EXISTS);
}
PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomerId(pageReqVO);

View File

@ -43,8 +43,7 @@ import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
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.common.util.collection.CollectionUtils.*;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CONTACT;
@ -60,15 +59,14 @@ public class CrmContactController {
private CrmContactService contactService;
@Resource
private CrmCustomerService customerService;
@Resource
private CrmContactBusinessService contactBusinessLinkService;
@Resource
private AdminUserApi adminUserApi;
@Resource
private OperateLogApi operateLogApi;
@Resource
private CrmContactBusinessService contactBusinessLinkService;
@PostMapping("/create")
@Operation(summary = "创建联系人")
@PreAuthorize("@ss.hasPermission('crm:contact:create')")
@ -116,10 +114,12 @@ public class CrmContactController {
}
@GetMapping("/simple-all-list")
@Operation(summary = "获得联系人列表")
@Operation(summary = "获得联系人的精简列表")
@PreAuthorize("@ss.hasPermission('crm:contact:query')")
public CommonResult<List<CrmContactSimpleRespVO>> getSimpleContactList() {
return success(contactService.simpleContactList());
public CommonResult<List<CrmContactRespVO>> getSimpleContactList() {
List<CrmContactDO> list = contactService.getContactList();
return success(convertList(list, contact -> // 只返回 idname 字段
new CrmContactRespVO().setId(contact.getId()).setName(contact.getName())));
}
@GetMapping("/page")
@ -149,6 +149,7 @@ public class CrmContactController {
ExcelUtils.write(response, "联系人.xls", "数据", CrmContactRespVO.class,
buildContactDetailPage(pageResult).getList());
}
@GetMapping("/operate-log-page")
@Operation(summary = "获得客户操作日志")
@PreAuthorize("@ss.hasPermission('crm:customer:query')")
@ -159,6 +160,7 @@ public class CrmContactController {
reqVO.setBizId(bizId);
return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class)));
}
/**
* 构建详细的联系人分页结果
*

View File

@ -1,24 +1,16 @@
package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
import cn.iocoder.yudao.framework.common.validation.Mobile;
import cn.iocoder.yudao.framework.common.validation.Telephone;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.mzt.logapi.starter.annotation.DiffLogField;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotNull;
import lombok.*;
import org.springframework.format.annotation.DateTimeFormat;
import lombok.Data;
import lombok.ToString;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - CRM 联系人 Response VO")
@Data
@ToString(callSuper = true)
@ -28,16 +20,16 @@ public class CrmContactRespVO {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
private Long id;
@ExcelProperty(value = "姓名",order = 1)
@Schema(description = "姓名", example = "芋艿")
@ExcelProperty(value = "姓名", order = 1)
private String name;
@Schema(description = "客户编号", example = "10795")
private Long customerId;
@Schema(description = "性别")
@ExcelProperty(value = "性别", converter = DictConvert.class, order = 3)
@DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX)
@Schema(description = "性别")
private Integer sex;
@Schema(description = "职位")
@ -52,71 +44,69 @@ public class CrmContactRespVO {
@Schema(description = "直属上级", example = "23457")
private Long parentId;
@Schema(description = "手机号",example = "1387171766")
@ExcelProperty(value = "手机号",order = 4)
@Schema(description = "手机号", example = "1387171766")
@ExcelProperty(value = "手机号", order = 4)
private String mobile;
@Schema(description = "电话",example = "021-0029922")
@ExcelProperty(value = "电话",order = 4)
@Schema(description = "电话", example = "021-0029922")
@ExcelProperty(value = "电话", order = 4)
private String telephone;
@ExcelProperty(value = "QQ",order = 4)
@Schema(description = "QQ",example = "197272662")
@Schema(description = "QQ", example = "197272662")
@ExcelProperty(value = "QQ", order = 4)
private Long qq;
@ExcelProperty(value = "微信",order = 4)
@Schema(description = "微信",example = "zzz3883")
@Schema(description = "微信", example = "zzz3883")
@ExcelProperty(value = "微信", order = 4)
private String wechat;
@Schema(description = "电子邮箱",example = "1111@22.com")
@ExcelProperty(value = "邮箱",order = 4)
@Schema(description = "电子邮箱", example = "1111@22.com")
@ExcelProperty(value = "邮箱", order = 4)
private String email;
@Schema(description = "地区编号", example = "20158")
private Integer areaId;
@ExcelProperty(value = "地址",order = 5)
@Schema(description = "地址")
@ExcelProperty(value = "地址", order = 5)
private String detailAddress;
@Schema(description = "备注", example = "你说的对")
@ExcelProperty(value = "备注",order = 6)
@ExcelProperty(value = "备注", order = 6)
private String remark;
@Schema(description = "负责人用户编号", example = "14334")
@NotNull(message = "负责人不能为空")
private Long ownerUserId;
@Schema(description = "最后跟进时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ExcelProperty(value = "最后跟进时间",order = 6)
@ExcelProperty(value = "最后跟进时间", order = 6)
private LocalDateTime contactLastTime;
@Schema(description = "下次联系时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
@ExcelProperty(value = "下次联系时间",order = 6)
@ExcelProperty(value = "下次联系时间", order = 6)
private LocalDateTime contactNextTime;
@Schema(description = "创建人", example = "25682")
private String creator;
@Schema(description = "创建人名字", example = "test")
@ExcelProperty(value = "创建人",order = 8)
@ExcelProperty(value = "创建人", order = 8)
private String creatorName;
@ExcelProperty(value = "客户名称",order = 2)
@ExcelProperty(value = "客户名称", order = 2)
@Schema(description = "客户名字", example = "test")
private String customerName;
@Schema(description = "负责人", example = "test")
@ExcelProperty(value = "负责人",order = 7)
@ExcelProperty(value = "负责人", order = 7)
private String ownerUserName;
@Schema(description = "直属上级名",example = "芋头")
@ExcelProperty(value = "直属上级",order = 4)
@Schema(description = "直属上级名", example = "芋头")
@ExcelProperty(value = "直属上级", order = 4)
private String parentName;
@Schema(description = "地区名",example = "上海上海市浦东新区")
@ExcelProperty(value = "地区",order = 5)
@Schema(description = "地区名", example = "上海上海市浦东新区")
@ExcelProperty(value = "地区", order = 5)
private String areaName;
}

View File

@ -2,17 +2,12 @@ package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
import cn.iocoder.yudao.framework.common.validation.Mobile;
import cn.iocoder.yudao.framework.common.validation.Telephone;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelProperty;
import cn.iocoder.yudao.module.crm.framework.operatelog.core.*;
import com.mzt.logapi.starter.annotation.DiffLogField;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@ -22,10 +17,9 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@Schema(description = "管理后台 - CRM 联系人创建/更新 Request VO")
@Data
@ToString(callSuper = true)
public class CrmContactSaveReqVO {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
@Schema(description = "主键", example = "3167")
private Long id;
@Schema(description = "姓名", example = "芋艿")
@ -34,12 +28,11 @@ public class CrmContactSaveReqVO {
private String name;
@Schema(description = "客户编号", example = "10795")
@DiffLogField(name = "姓名",function = "getCustomerById")
@DiffLogField(name = "姓名", function = CrmCustomerParseFunction.NAME)
private Long customerId;
@DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX)
@Schema(description = "性别")
@DiffLogField(name = "性别",function = "getSexById")
@DiffLogField(name = "性别", function = CrmSexParseFunction.NAME)
private Integer sex;
@Schema(description = "职位")
@ -47,33 +40,32 @@ public class CrmContactSaveReqVO {
private String post;
@Schema(description = "是否关键决策人")
@DictFormat(DictTypeConstants.BOOLEAN_STRING)
@DiffLogField(name = "关键决策人", function = "getBooleanById")
@DiffLogField(name = "关键决策人", function = CrmBooleanParseFunction.NAME)
private Boolean master;
@Schema(description = "直属上级", example = "23457")
@DiffLogField(name = "直属上级",function = "getContactById")
@DiffLogField(name = "直属上级", function = CrmContactParseFunction.NAME)
private Long parentId;
@Schema(description = "手机号",example = "1387171766")
@Schema(description = "手机号", example = "1387171766")
@Mobile
@DiffLogField(name = "手机号")
private String mobile;
@Schema(description = "电话",example = "021-0029922")
@Schema(description = "电话", example = "021-0029922")
@Telephone
@DiffLogField(name = "电话")
private String telephone;
@Schema(description = "QQ",example = "197272662")
@Schema(description = "QQ", example = "197272662")
@DiffLogField(name = "QQ")
private Long qq;
@Schema(description = "微信",example = "zzz3883")
@Schema(description = "微信", example = "zzz3883")
@DiffLogField(name = "微信")
private String wechat;
@Schema(description = "电子邮箱",example = "1111@22.com")
@Schema(description = "电子邮箱", example = "1111@22.com")
@DiffLogField(name = "邮箱")
@Email
private String email;
@ -92,7 +84,7 @@ public class CrmContactSaveReqVO {
@Schema(description = "负责人用户编号", example = "14334")
@NotNull(message = "负责人不能为空")
@DiffLogField(name = "负责人",function = "getUserById")
@DiffLogField(name = "负责人", function = CrmSysUserParseFunction.NAME)
private Long ownerUserId;
@Schema(description = "最后跟进时间")
@ -105,6 +97,7 @@ public class CrmContactSaveReqVO {
@DiffLogField(name = "下次联系时间")
private LocalDateTime contactNextTime;
@Schema(description = "关联商机ID", example = "122233")
private Long businessId;
@Schema(description = "关联商机 ID", example = "122233")
private Long businessId; // 注意该字段用于在商机详情界面新建联系人自动进行关联
}

View File

@ -1,18 +0,0 @@
package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.ToString;
@Schema(description = "管理后台 - CRM 联系人的精简 Response VO")
@Data
@ToString(callSuper = true)
public class CrmContactSimpleRespVO {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
private Long id;
@Schema(description = "姓名", example = "芋艿")
private String name;
}

View File

@ -5,6 +5,9 @@ import cn.iocoder.yudao.framework.common.validation.Mobile;
import cn.iocoder.yudao.framework.common.validation.Telephone;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLevelEnum;
import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmIndustryParseFunction;
import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmLevelParseFunction;
import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmSourceParseFunction;
import com.mzt.logapi.starter.annotation.DiffLogField;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
@ -31,17 +34,17 @@ public class CrmCustomerBaseVO {
private String name;
@Schema(description = "所属行业", example = "1")
@DiffLogField(name = "所属行业", function = "getIndustryById")
@DiffLogField(name = "所属行业", function = CrmIndustryParseFunction.NAME)
@DictFormat(CRM_CUSTOMER_INDUSTRY)
private Integer industryId;
@Schema(description = "客户等级", example = "2")
@DiffLogField(name = "客户等级", function = "getLevel")
@DiffLogField(name = "客户等级", function = CrmLevelParseFunction.NAME)
@InEnum(CrmCustomerLevelEnum.class)
private Integer level;
@Schema(description = "客户来源", example = "3")
@DiffLogField(name = "客户来源", function = "getSource")
@DiffLogField(name = "客户来源", function = CrmSourceParseFunction.NAME)
private Integer source;
@Schema(description = "手机", example = "18000000000")

View File

@ -29,8 +29,6 @@ public interface CrmContactConvert {
CrmContactConvert INSTANCE = Mappers.getMapper(CrmContactConvert.class);
CrmContactDO convert(CrmContactSaveReqVO bean);
CrmContactRespVO convert(CrmContactDO bean);
List<CrmContactRespVO> convertList(List<CrmContactDO> list);

View File

@ -60,4 +60,8 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> {
return selectJoinList(CrmContractDO.class, mpjLambdaWrapperX);
}
default Long selectCountByContactId(Long contactId) {
return selectCount(CrmContractDO::getContactId, contactId);
}
}

View File

@ -12,10 +12,12 @@ import org.springframework.stereotype.Component;
*
* @author HUIHUI
*/
@Slf4j
@Component
@Slf4j
public class CrmBooleanParseFunction implements IParseFunction {
public static final String NAME = "getBooleanById";
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
@ -23,7 +25,7 @@ public class CrmBooleanParseFunction implements IParseFunction {
@Override
public String functionName() {
return "getBooleanById";
return NAME;
}
@Override

View File

@ -3,8 +3,6 @@ package cn.iocoder.yudao.module.crm.framework.operatelog.core;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.mzt.logapi.service.IParseFunction;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
@ -15,10 +13,12 @@ import org.springframework.stereotype.Component;
*
* @author HUIHUI
*/
@Slf4j
@Component
@Slf4j
public class CrmContactParseFunction implements IParseFunction {
public static final String NAME = "getContactById";
@Resource
private CrmContactService contactService;
@ -29,7 +29,7 @@ public class CrmContactParseFunction implements IParseFunction {
@Override
public String functionName() {
return "getContactById";
return NAME;
}
@Override

View File

@ -1,28 +1,27 @@
package cn.iocoder.yudao.module.crm.framework.operatelog.core;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
import com.mzt.logapi.service.IParseFunction;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Optional;
/**
* 行业的 {@link IParseFunction} 实现类
*
* @author HUIHUI
*/
@Slf4j
@Component
@Slf4j
public class CrmCustomerParseFunction implements IParseFunction {
public static final String NAME = "getCustomerById";
@Resource
private CrmCustomerService customerService;
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
@ -30,7 +29,7 @@ public class CrmCustomerParseFunction implements IParseFunction {
@Override
public String functionName() {
return "getCustomerById";
return NAME;
}
@Override

View File

@ -13,10 +13,12 @@ import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_I
*
* @author HUIHUI
*/
@Slf4j
@Component
@Slf4j
public class CrmIndustryParseFunction implements IParseFunction {
public static final String NAME = "getIndustryById";
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
@ -24,7 +26,7 @@ public class CrmIndustryParseFunction implements IParseFunction {
@Override
public String functionName() {
return "getIndustryById";
return NAME;
}
@Override

View File

@ -13,10 +13,12 @@ import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_L
*
* @author HUIHUI
*/
@Slf4j
@Component
@Slf4j
public class CrmLevelParseFunction implements IParseFunction {
public static final String NAME = "getLevel";
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
@ -24,7 +26,7 @@ public class CrmLevelParseFunction implements IParseFunction {
@Override
public String functionName() {
return "getLevel";
return NAME;
}
@Override

View File

@ -7,17 +7,17 @@ import com.mzt.logapi.service.IParseFunction;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY;
/**
* 行业的 {@link IParseFunction} 实现类
*
* @author HUIHUI
*/
@Slf4j
@Component
@Slf4j
public class CrmSexParseFunction implements IParseFunction {
public static final String NAME = "getSexById";
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
@ -25,7 +25,7 @@ public class CrmSexParseFunction implements IParseFunction {
@Override
public String functionName() {
return "getSexById";
return NAME;
}
@Override

View File

@ -13,10 +13,12 @@ import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_S
*
* @author HUIHUI
*/
@Slf4j
@Component
@Slf4j
public class CrmSourceParseFunction implements IParseFunction {
public static final String NAME = "getSource";
@Override
public boolean executeBefore() {
return true; // 先转换值后对比
@ -24,7 +26,7 @@ public class CrmSourceParseFunction implements IParseFunction {
@Override
public String functionName() {
return "getSource";
return NAME;
}
@Override

View File

@ -1,10 +1,8 @@
package cn.iocoder.yudao.module.crm.framework.operatelog.core;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
import com.mzt.logapi.service.IParseFunction;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
@ -15,10 +13,12 @@ import org.springframework.stereotype.Component;
*
* @author HUIHUI
*/
@Slf4j
@Component
@Slf4j
public class CrmSysUserParseFunction implements IParseFunction {
public static final String NAME = "getUserById";
@Resource
private AdminUserApi adminUserApi;
@ -29,7 +29,7 @@ public class CrmSysUserParseFunction implements IParseFunction {
@Override
public String functionName() {
return "getUserById";
return NAME;
}
@Override

View File

@ -27,6 +27,13 @@ public interface CrmContactBusinessService {
*/
void deleteContactBusinessList(@Valid CrmContactBusinessReqVO deleteReqVO);
/**
* 删除联系人与商机的关联基于联系人编号
*
* @param contactId 联系人编号
*/
void deleteContactBusinessByContactId(Long contactId);
/**
* 获得联系人与商机的关联列表基于联系人编号
*
@ -35,7 +42,4 @@ public interface CrmContactBusinessService {
*/
List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId);
void deleteContactBusinessByContactId(Long contactId);
}

View File

@ -75,14 +75,14 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService
deleteReqVO.getContactId(), deleteReqVO.getBusinessIds());
}
@Override
public List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId) {
return contactBusinessMapper.selectListByContactId(contactId);
}
@Override
public void deleteContactBusinessByContactId(Long contactId) {
contactBusinessMapper.delete(CrmContactBusinessDO::getContactId,contactId);
}
@Override
public List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId) {
return contactBusinessMapper.selectListByContactId(contactId);
}
}

View File

@ -56,6 +56,13 @@ public interface CrmContactService {
*/
List<CrmContactDO> getContactList(Collection<Long> ids, Long userId);
/**
* 获得联系人列表
*
* @return 联系人列表
*/
List<CrmContactDO> getContactList();
/**
* 获得联系人分页
*
@ -85,10 +92,4 @@ public interface CrmContactService {
*/
void transferContact(CrmContactTransferReqVO reqVO, Long userId);
/**
* 获取联系人简单列表
* @return 联系人
*/
List<CrmContactSimpleRespVO> simpleContactList();
}

View File

@ -2,14 +2,14 @@ package cn.iocoder.yudao.module.crm.service.contact;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessReqVO;
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.business.CrmBusinessDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper;
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
@ -28,18 +28,14 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
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.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CONTACT;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ERROR_CODE_DUPLICATE;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;
import static java.util.Collections.singletonList;
/**
* CRM 联系人 Service 实现类
@ -52,46 +48,42 @@ public class CrmContactServiceImpl implements CrmContactService {
@Resource
private CrmContactMapper contactMapper;
@Resource
private CrmCustomerService customerService;
@Resource
private CrmPermissionService crmPermissionService;
private CrmPermissionService permissionService;
@Resource
private AdminUserApi adminUserApi;
@Resource
private CrmContractService crmContractService;
private CrmContractService contractService;
@Resource
private CrmContactBusinessService contactBusinessService;
@Resource
private CrmBusinessService businessService;
@Resource
private AdminUserApi adminUserApi;
@Override
@Transactional(rollbackFor = Exception.class)
@LogRecord(type = CRM_CONTACT, subType = "创建联系人[{{#contactName}}]", bizNo = "{{#contactId}}", success = "创建了联系人")
@LogRecord(type = CRM_CONTACT, subType = "创建联系人", bizNo = "{{#contactId}}", success = "创建了联系人[{{#contactName}}]")
public Long createContact(CrmContactSaveReqVO createReqVO, Long userId) {
// 1. 校验
validateRelationDataExists(createReqVO);
// 2. 插入联系人
CrmContactDO contact = CrmContactConvert.INSTANCE.convert(createReqVO);
int contactId = contactMapper.insert(contact);
CrmContactDO contact = BeanUtils.toBean(createReqVO, CrmContactDO.class);
contactMapper.insert(contact);
// 3. 创建数据权限
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
permissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
.setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()).setBizId(contact.getId())
.setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
//4.若传businessId自动关联商机
Optional.ofNullable(createReqVO.getBusinessId()).ifPresent(businessId -> {
CrmBusinessDO crmBusinessDO = businessService.getBusiness(createReqVO.getBusinessId());
if(crmBusinessDO == null){
throw exception(BUSINESS_NOT_EXISTS);
}
CrmContactBusinessReqVO crmContactBusinessReqVO = new CrmContactBusinessReqVO();
crmContactBusinessReqVO.setContactId(contact.getId());
crmContactBusinessReqVO.setBusinessIds(List.of(businessId));
contactBusinessService.createContactBusinessList(crmContactBusinessReqVO);
});
// 4. 如果有关联商机则需要创建关联
if (createReqVO.getBusinessId() != null) {
contactBusinessService.createContactBusinessList(new CrmContactBusinessReqVO()
.setContactId(contact.getId()).setBusinessIds(singletonList(createReqVO.getBusinessId())));
}
// 5. 记录操作日志
LogRecordContext.putVariable("contactId", contact.getId());
@ -109,7 +101,7 @@ public class CrmContactServiceImpl implements CrmContactService {
validateRelationDataExists(updateReqVO);
// 2. 更新联系人
CrmContactDO updateObj = CrmContactConvert.INSTANCE.convert(updateReqVO);
CrmContactDO updateObj = BeanUtils.toBean(updateReqVO, CrmContactDO.class);
contactMapper.updateById(updateObj);
// 3. 记录操作日志
@ -134,24 +126,29 @@ public class CrmContactServiceImpl implements CrmContactService {
if (saveReqVO.getParentId() != null && contactMapper.selectById(saveReqVO.getParentId()) == null) {
throw exception(CONTACT_NOT_EXISTS);
}
// 4. 如果有关联商机则需要校验存在
if (saveReqVO.getBusinessId() != null && businessService.getBusiness(saveReqVO.getBusinessId()) == null) {
throw exception(BUSINESS_NOT_EXISTS);
}
}
@Override
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
@Transactional(rollbackFor = Exception.class)
public void deleteContact(Long id) {
//1. 校验存在
// 1.1 校验存在
validateContactExists(id);
//2.校验是否关联合同
CrmContractDO crmContractDO = crmContractService.getContractByContactId(id);
if(crmContractDO != null){
throw exception(CONTACT_CONTRACT_LINK_EXISTS);
// 1.2 校验是否关联合同
if (contractService.getContractCountByContactId(id) > 0) {
throw exception(CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS);
}
//3.删除联系人
// 2. 删除联系人
contactMapper.deleteById(id);
//4.删除数据权限
crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CONTACT.getType(), id);
//5.删除商机关联
// 4.1 删除数据权限
permissionService.deletePermission(CrmBizTypeEnum.CRM_CONTACT.getType(), id);
// 4.2 删除商机关联
contactBusinessService.deleteContactBusinessByContactId(id);
// TODO @puhui999删除跟进记录
}
@ -178,6 +175,11 @@ public class CrmContactServiceImpl implements CrmContactService {
return contactMapper.selectBatchIds(ids, userId);
}
@Override
public List<CrmContactDO> getContactList() {
return contactMapper.selectList();
}
@Override
public PageResult<CrmContactDO> getContactPage(CrmContactPageReqVO pageReqVO, Long userId) {
return contactMapper.selectPage(pageReqVO, userId);
@ -197,7 +199,7 @@ public class CrmContactServiceImpl implements CrmContactService {
validateContactExists(reqVO.getId());
// 2.1 数据权限转移
crmPermissionService.transferPermission(
permissionService.transferPermission(
CrmContactConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()));
// 2.2 设置新的负责人
contactMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
@ -205,12 +207,4 @@ public class CrmContactServiceImpl implements CrmContactService {
// 3. TODO 记录转移日志
}
@Override
public List<CrmContactSimpleRespVO> simpleContactList() {
CrmContactPageReqVO pageReqVO = new CrmContactPageReqVO();
pageReqVO.setPageSize(PAGE_SIZE_NONE);
List<CrmContactDO> list =contactMapper.selectPage(pageReqVO, getLoginUserId()).getList();
return BeanUtils.toBean(list, CrmContactSimpleRespVO.class);
}
}

View File

@ -88,10 +88,11 @@ public interface CrmContractService {
void transferContract(CrmContractTransferReqVO reqVO, Long userId);
/**
* 查询合同基于联系人
* 查询属于某个联系人的合同数量
*
* @param contactId 联系人ID
* @return 合同
*/
CrmContractDO getContractByContactId(Long contactId);
Long getContractCountByContactId(Long contactId);
}

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.crm.service.contract;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractCreateReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
@ -137,8 +136,8 @@ public class CrmContractServiceImpl implements CrmContractService {
}
@Override
public CrmContractDO getContractByContactId(Long contactId) {
return contractMapper.selectOne(CrmContractDO::getContactId, contactId);
public Long getContractCountByContactId(Long contactId) {
return contractMapper.selectCountByContactId(contactId);
}
// TODO @合同待定需要新增一个 ContractConfigDO 合同配置重点是到期提醒