crm: 增加联系人,基于客户的读取接口

This commit is contained in:
YunaiV 2023-11-29 22:33:47 +08:00
parent 1a93e3a110
commit 53b8e37f36
16 changed files with 276 additions and 262 deletions

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.crm.controller.admin.contact; package cn.iocoder.yudao.module.crm.controller.admin.contact;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.NumberUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
@ -10,10 +11,10 @@ import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert; import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO; 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.dal.dataobject.customer.CrmCustomerDO;
import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.crm.service.contact.ContactService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 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.api.user.dto.AdminUserRespDTO;
@ -30,7 +31,9 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid; import javax.validation.Valid;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream; import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@ -40,18 +43,17 @@ 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.operatelog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
// TODO @zyacrm 所有的类dou带 Crm 前缀因为它的名字太通用了可能和后续的 erp 之类的冲突
@Tag(name = "管理后台 - CRM 联系人") @Tag(name = "管理后台 - CRM 联系人")
@RestController @RestController
@RequestMapping("/crm/contact") @RequestMapping("/crm/contact")
@Validated @Validated
@Slf4j @Slf4j
public class ContactController { public class CrmContactController {
@Resource @Resource
private ContactService contactService; private CrmContactService contactService;
@Resource @Resource
private CrmCustomerService crmCustomerService; private CrmCustomerService customerService;
@Resource @Resource
private AdminUserApi adminUserApi; private AdminUserApi adminUserApi;
@ -59,14 +61,14 @@ public class ContactController {
@PostMapping("/create") @PostMapping("/create")
@Operation(summary = "创建联系人") @Operation(summary = "创建联系人")
@PreAuthorize("@ss.hasPermission('crm:contact:create')") @PreAuthorize("@ss.hasPermission('crm:contact:create')")
public CommonResult<Long> createContact(@Valid @RequestBody ContactCreateReqVO createReqVO) { public CommonResult<Long> createContact(@Valid @RequestBody CrmContactCreateReqVO createReqVO) {
return success(contactService.createContact(createReqVO, getLoginUserId())); return success(contactService.createContact(createReqVO, getLoginUserId()));
} }
@PutMapping("/update") @PutMapping("/update")
@Operation(summary = "更新联系人") @Operation(summary = "更新联系人")
@PreAuthorize("@ss.hasPermission('crm:contact:update')") @PreAuthorize("@ss.hasPermission('crm:contact:update')")
public CommonResult<Boolean> updateContact(@Valid @RequestBody ContactUpdateReqVO updateReqVO) { public CommonResult<Boolean> updateContact(@Valid @RequestBody CrmContactUpdateReqVO updateReqVO) {
contactService.updateContact(updateReqVO); contactService.updateContact(updateReqVO);
return success(true); return success(true);
} }
@ -84,8 +86,8 @@ public class ContactController {
@Operation(summary = "获得联系人") @Operation(summary = "获得联系人")
@Parameter(name = "id", description = "编号", required = true, example = "1024") @Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('crm:contact:query')") @PreAuthorize("@ss.hasPermission('crm:contact:query')")
public CommonResult<ContactRespVO> getContact(@RequestParam("id") Long id) { public CommonResult<CrmContactRespVO> getContact(@RequestParam("id") Long id) {
ContactDO contact = contactService.getContact(id); CrmContactDO contact = contactService.getContact(id);
if (contact == null) { if (contact == null) {
throw exception(ErrorCodeConstants.CONTACT_NOT_EXISTS); throw exception(ErrorCodeConstants.CONTACT_NOT_EXISTS);
} }
@ -93,63 +95,69 @@ public class ContactController {
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(CollUtil.removeNull(Lists.newArrayList( Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(CollUtil.removeNull(Lists.newArrayList(
NumberUtil.parseLong(contact.getCreator()), contact.getOwnerUserId()))); NumberUtil.parseLong(contact.getCreator()), contact.getOwnerUserId())));
// 2. 获取客户信息 // 2. 获取客户信息
List<CrmCustomerDO> customerList = crmCustomerService.getCustomerList(Collections.singletonList(contact.getCustomerId())); List<CrmCustomerDO> customerList = customerService.getCustomerList(Collections.singletonList(contact.getCustomerId()));
// 3. 直属上级 // 3. 直属上级
List<ContactDO> parentContactList = contactService.getContactList(Collections.singletonList(contact.getParentId())); List<CrmContactDO> parentContactList = contactService.getContactList(Collections.singletonList(contact.getParentId()));
return success(ContactConvert.INSTANCE.convert(contact, userMap, customerList, parentContactList)); return success(ContactConvert.INSTANCE.convert(contact, userMap, customerList, parentContactList));
} }
@GetMapping("/simple-all-list") @GetMapping("/simple-all-list")
@Operation(summary = "获得联系人列表") @Operation(summary = "获得联系人列表")
@PreAuthorize("@ss.hasPermission('crm:contact:query')") @PreAuthorize("@ss.hasPermission('crm:contact:query')")
public CommonResult<List<ContactSimpleRespVO>> getContactList() { public CommonResult<List<CrmContactSimpleRespVO>> getSimpleContactList() {
List<ContactDO> list = contactService.getContactList(); List<CrmContactDO> list = contactService.getContactList();
return success(ContactConvert.INSTANCE.convertAllList(list)); return success(ContactConvert.INSTANCE.convertAllList(list));
} }
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得联系人分页") @Operation(summary = "获得联系人分页")
@PreAuthorize("@ss.hasPermission('crm:contact:query')") @PreAuthorize("@ss.hasPermission('crm:contact:query')")
public CommonResult<PageResult<ContactRespVO>> getContactPage(@Valid ContactPageReqVO pageVO) { public CommonResult<PageResult<CrmContactRespVO>> getContactPage(@Valid CrmContactPageReqVO pageVO) {
PageResult<ContactDO> pageResult = contactService.getContactPage(pageVO); PageResult<CrmContactDO> pageResult = contactService.getContactPage(pageVO);
if (CollUtil.isEmpty(pageResult.getList())) { return success(convertDetailContactPage(pageResult));
return success(PageResult.empty(pageResult.getTotal()));
} }
return success(convertFieldValue2Name(pageResult));
@GetMapping("/page-by-customer")
@Operation(summary = "获得联系人分页,基于指定客户")
public CommonResult<PageResult<CrmContactRespVO>> getContactPageByCustomer(@Valid CrmContactPageReqVO pageVO) {
Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空");
PageResult<CrmContactDO> pageResult = contactService.getContactPageByCustomer(pageVO);
return success(convertDetailContactPage(pageResult));
} }
@GetMapping("/export-excel") @GetMapping("/export-excel")
@Operation(summary = "导出联系人 Excel") @Operation(summary = "导出联系人 Excel")
@PreAuthorize("@ss.hasPermission('crm:contact:export')") @PreAuthorize("@ss.hasPermission('crm:contact:export')")
@OperateLog(type = EXPORT) @OperateLog(type = EXPORT)
public void exportContactExcel(@Valid ContactPageReqVO exportReqVO, public void exportContactExcel(@Valid CrmContactPageReqVO exportReqVO,
HttpServletResponse response) throws IOException { HttpServletResponse response) throws IOException {
exportReqVO.setPageNo(PageParam.PAGE_SIZE_NONE); exportReqVO.setPageNo(PageParam.PAGE_SIZE_NONE);
PageResult<ContactDO> pageResult = contactService.getContactPage(exportReqVO); PageResult<CrmContactDO> pageResult = contactService.getContactPage(exportReqVO);
PageResult<ContactRespVO> exportPage = convertFieldValue2Name(pageResult); ExcelUtils.write(response, "联系人.xls", "数据", CrmContactRespVO.class,
ExcelUtils.write(response, "crm 联系人.xls", "数据", ContactRespVO.class, exportPage.getList()); convertDetailContactPage(pageResult).getList());
} }
// TODO 芋艿后续会合并下
/** /**
* 翻译字段名称 * 转换成详细的联系人分页即读取关联信息
* *
* @param pageResult 联系人分页参数 * @param pageResult 联系人分页
* @return List<ContactRespVO> * @return 详细的联系人分页
*/ */
private PageResult<ContactRespVO> convertFieldValue2Name(PageResult<ContactDO> pageResult) { private PageResult<CrmContactRespVO> convertDetailContactPage(PageResult<CrmContactDO> pageResult) {
List<ContactDO> contactDOList = pageResult.getList(); List<CrmContactDO> contactList = pageResult.getList();
if (CollUtil.isEmpty(contactList)) {
return PageResult.empty(pageResult.getTotal());
}
// 1. 获取客户列表 // 1. 获取客户列表
List<CrmCustomerDO> crmCustomerDOList = crmCustomerService.getCustomerList(convertSet(contactDOList, ContactDO::getCustomerId)); List<CrmCustomerDO> crmCustomerDOList = customerService.getCustomerList(
convertSet(contactList, CrmContactDO::getCustomerId));
// 2. 获取创建人责任人列表 // 2. 获取创建人责任人列表
List<Long> userIdsList = convertListByFlatMap(contactDOList, item -> Stream.of(NumberUtils.parseLong(item.getCreator()), item.getOwnerUserId()) Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(contactList,
.filter(Objects::nonNull)); // TODO @zyna里面已经忽略 null contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId())));
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIdsList);
// 3. 直属上级 // 3. 直属上级
Set<Long> contactIdsList = convertSet(contactDOList, ContactDO::getParentId); List<CrmContactDO> parentContactList = contactService.getContactList(
List<ContactDO> contactList = contactService.getContactList(contactIdsList); convertSet(contactList, CrmContactDO::getParentId));
return ContactConvert.INSTANCE.convertPage(pageResult, userMap, crmCustomerDOList, contactList); return ContactConvert.INSTANCE.convertPage(pageResult, userMap, crmCustomerDOList, parentContactList);
} }
} }

View File

@ -25,7 +25,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
*/ */
@Data @Data
@ExcelIgnoreUnannotated @ExcelIgnoreUnannotated
public class ContactBaseVO { public class CrmContactBaseVO {
@ExcelProperty(value = "姓名",order = 1) @ExcelProperty(value = "姓名",order = 1)
@Schema(description = "姓名", example = "芋艿") @Schema(description = "姓名", example = "芋艿")

View File

@ -9,6 +9,6 @@ import lombok.ToString;
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
public class ContactCreateReqVO extends ContactBaseVO { public class CrmContactCreateReqVO extends CrmContactBaseVO {
} }

View File

@ -10,10 +10,8 @@ import lombok.ToString;
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
public class ContactPageReqVO extends PageParam { public class CrmContactPageReqVO extends PageParam {
// 客户
// 姓名
// 手机电话座机QQ微信邮箱
@Schema(description = "姓名", example = "芋艿") @Schema(description = "姓名", example = "芋艿")
private String name; private String name;
@ -34,4 +32,5 @@ public class ContactPageReqVO extends PageParam {
@Schema(description = "微信", example = "zzZ98373") @Schema(description = "微信", example = "zzZ98373")
private String wechat; private String wechat;
} }

View File

@ -11,7 +11,7 @@ import java.time.LocalDateTime;
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
@ExcelIgnoreUnannotated @ExcelIgnoreUnannotated
public class ContactRespVO extends ContactBaseVO { public class CrmContactRespVO extends CrmContactBaseVO {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167") @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
private Long id; private Long id;
@ -46,4 +46,5 @@ public class ContactRespVO extends ContactBaseVO {
@Schema(description = "地区名", example = "上海上海市浦东新区") @Schema(description = "地区名", example = "上海上海市浦东新区")
@ExcelProperty(value = "地区", order = 5) @ExcelProperty(value = "地区", order = 5)
private String areaName; private String areaName;
} }

View File

@ -4,10 +4,10 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.ToString; import lombok.ToString;
@Schema(description = "管理后台 - CRM 联系人 Response VO") @Schema(description = "管理后台 - CRM 联系人的精简 Response VO")
@Data @Data
@ToString(callSuper = true) @ToString(callSuper = true)
public class ContactSimpleRespVO { public class CrmContactSimpleRespVO {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167") @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
private Long id; private Long id;

View File

@ -11,7 +11,7 @@ import javax.validation.constraints.NotNull;
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
public class ContactUpdateReqVO extends ContactBaseVO { public class CrmContactUpdateReqVO extends CrmContactBaseVO {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167") @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
@NotNull(message = "主键不能为空") @NotNull(message = "主键不能为空")

View File

@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.crm.convert.contact;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO; 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.dal.dataobject.customer.CrmCustomerDO;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
@ -20,7 +20,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
/** /**
* crm联系人 Convert * CRM 联系人 Convert
* *
* @author 芋道源码 * @author 芋道源码
*/ */
@ -29,22 +29,22 @@ public interface ContactConvert {
ContactConvert INSTANCE = Mappers.getMapper(ContactConvert.class); ContactConvert INSTANCE = Mappers.getMapper(ContactConvert.class);
ContactDO convert(ContactCreateReqVO bean); CrmContactDO convert(CrmContactCreateReqVO bean);
ContactDO convert(ContactUpdateReqVO bean); CrmContactDO convert(CrmContactUpdateReqVO bean);
ContactRespVO convert(ContactDO bean); CrmContactRespVO convert(CrmContactDO bean);
List<ContactRespVO> convertList(List<ContactDO> list); List<CrmContactRespVO> convertList(List<CrmContactDO> list);
PageResult<ContactRespVO> convertPage(PageResult<ContactDO> page); PageResult<CrmContactRespVO> convertPage(PageResult<CrmContactDO> page);
default PageResult<ContactRespVO> convertPage(PageResult<ContactDO> pageResult, Map<Long, AdminUserRespDTO> userMap, default PageResult<CrmContactRespVO> convertPage(PageResult<CrmContactDO> pageResult, Map<Long, AdminUserRespDTO> userMap,
List<CrmCustomerDO> customerList, List<ContactDO> parentContactList) { List<CrmCustomerDO> customerList, List<CrmContactDO> parentContactList) {
List<ContactRespVO> list = converList(pageResult.getList(), userMap, customerList, parentContactList); List<CrmContactRespVO> list = converList(pageResult.getList(), userMap, customerList, parentContactList);
return convertPage(pageResult).setList(list); return convertPage(pageResult).setList(list);
} }
List<ContactSimpleRespVO> convertAllList(List<ContactDO> list); List<CrmContactSimpleRespVO> convertAllList(List<CrmContactDO> list);
@Mappings({ @Mappings({
@Mapping(target = "bizId", source = "reqVO.id"), @Mapping(target = "bizId", source = "reqVO.id"),
@ -60,21 +60,21 @@ public interface ContactConvert {
* @param crmCustomerDOList 客户 * @param crmCustomerDOList 客户
* @return ContactRespVO * @return ContactRespVO
*/ */
default ContactRespVO convert(ContactDO contactDO, Map<Long, AdminUserRespDTO> userMap, List<CrmCustomerDO> crmCustomerDOList, default CrmContactRespVO convert(CrmContactDO contactDO, Map<Long, AdminUserRespDTO> userMap, List<CrmCustomerDO> crmCustomerDOList,
List<ContactDO> contactList) { List<CrmContactDO> contactList) {
ContactRespVO contactVO = convert(contactDO); CrmContactRespVO contactVO = convert(contactDO);
setUserInfo(contactVO, userMap); setUserInfo(contactVO, userMap);
Map<Long, CrmCustomerDO> ustomerMap = crmCustomerDOList.stream().collect(Collectors.toMap(CrmCustomerDO::getId, v -> v)); Map<Long, CrmCustomerDO> ustomerMap = crmCustomerDOList.stream().collect(Collectors.toMap(CrmCustomerDO::getId, v -> v));
Map<Long, ContactDO> contactMap = contactList.stream().collect(Collectors.toMap(ContactDO::getId, v -> v)); Map<Long, CrmContactDO> contactMap = contactList.stream().collect(Collectors.toMap(CrmContactDO::getId, v -> v));
findAndThen(ustomerMap, contactDO.getCustomerId(), customer -> contactVO.setCustomerName(customer.getName())); findAndThen(ustomerMap, contactDO.getCustomerId(), customer -> contactVO.setCustomerName(customer.getName()));
findAndThen(contactMap, contactDO.getParentId(), contact -> contactVO.setParentName(contact.getName())); findAndThen(contactMap, contactDO.getParentId(), contact -> contactVO.setParentName(contact.getName()));
return contactVO; return contactVO;
} }
default List<ContactRespVO> converList(List<ContactDO> contactList, Map<Long, AdminUserRespDTO> userMap, default List<CrmContactRespVO> converList(List<CrmContactDO> contactList, Map<Long, AdminUserRespDTO> userMap,
List<CrmCustomerDO> customerList, List<ContactDO> parentContactList) { List<CrmCustomerDO> customerList, List<CrmContactDO> parentContactList) {
List<ContactRespVO> result = convertList(contactList); List<CrmContactRespVO> result = convertList(contactList);
Map<Long, ContactDO> parentContactMap = convertMap(parentContactList, ContactDO::getId); Map<Long, CrmContactDO> parentContactMap = convertMap(parentContactList, CrmContactDO::getId);
Map<Long, CrmCustomerDO> customerMap = convertMap(customerList, CrmCustomerDO::getId); Map<Long, CrmCustomerDO> customerMap = convertMap(customerList, CrmCustomerDO::getId);
result.forEach(item -> { result.forEach(item -> {
setUserInfo(item, userMap); setUserInfo(item, userMap);
@ -94,7 +94,7 @@ public interface ContactConvert {
* @param contactRespVO 联系人Response VO * @param contactRespVO 联系人Response VO
* @param userMap 用户信息 map * @param userMap 用户信息 map
*/ */
static void setUserInfo(ContactRespVO contactRespVO, Map<Long, AdminUserRespDTO> userMap) { static void setUserInfo(CrmContactRespVO contactRespVO, Map<Long, AdminUserRespDTO> userMap) {
contactRespVO.setAreaName(AreaUtils.format(contactRespVO.getAreaId())); contactRespVO.setAreaName(AreaUtils.format(contactRespVO.getAreaId()));
findAndThen(userMap, contactRespVO.getOwnerUserId(), user -> { findAndThen(userMap, contactRespVO.getOwnerUserId(), user -> {
contactRespVO.setOwnerUserName(user == null ? "" : user.getNickname()); contactRespVO.setOwnerUserName(user == null ? "" : user.getNickname());

View File

@ -21,7 +21,7 @@ import java.time.LocalDateTime;
@Builder @Builder
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class ContactDO extends BaseDO { public class CrmContactDO extends BaseDO {
/** /**
* 主键 * 主键
@ -63,7 +63,7 @@ public class ContactDO extends BaseDO {
/** /**
* 直属上级 * 直属上级
* *
* 关联 {@link ContactDO#id} * 关联 {@link CrmContactDO#id}
*/ */
private Long parentId; private Long parentId;
/** /**

View File

@ -1,44 +0,0 @@
package cn.iocoder.yudao.module.crm.dal.mysql.contact;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO;
import org.apache.ibatis.annotations.Mapper;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
/**
* crm联系人 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface ContactMapper extends BaseMapperX<ContactDO> {
default PageResult<ContactDO> selectPage(ContactPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<ContactDO>()
.eqIfPresent(ContactDO::getMobile, reqVO.getMobile())
.eqIfPresent(ContactDO::getTelephone, reqVO.getTelephone())
.eqIfPresent(ContactDO::getEmail, reqVO.getEmail())
.eqIfPresent(ContactDO::getCustomerId, reqVO.getCustomerId())
.likeIfPresent(ContactDO::getName, reqVO.getName())
.eqIfPresent(ContactDO::getQq, reqVO.getQq())
.eqIfPresent(ContactDO::getWechat, reqVO.getWechat())
.orderByDesc(ContactDO::getId));
}
default List<ContactDO> selectList(ContactPageReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<ContactDO>()
.eqIfPresent(ContactDO::getMobile, reqVO.getMobile())
.eqIfPresent(ContactDO::getTelephone, reqVO.getTelephone())
.eqIfPresent(ContactDO::getEmail, reqVO.getEmail())
.eqIfPresent(ContactDO::getCustomerId, reqVO.getCustomerId())
.likeIfPresent(ContactDO::getName, reqVO.getName())
.eqIfPresent(ContactDO::getQq, reqVO.getQq())
.eqIfPresent(ContactDO::getWechat, reqVO.getWechat())
.orderByDesc(ContactDO::getId));
}
}

View File

@ -0,0 +1,43 @@
package cn.iocoder.yudao.module.crm.dal.mysql.contact;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
import org.apache.ibatis.annotations.Mapper;
/**
* CRM 联系人 Mapper
*
* @author 芋道源码
*/
@Mapper
public interface CrmContactMapper extends BaseMapperX<CrmContactDO> {
// TODO @puhui999数据权限
default PageResult<CrmContactDO> selectPage(CrmContactPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<CrmContactDO>()
.eqIfPresent(CrmContactDO::getMobile, reqVO.getMobile())
.eqIfPresent(CrmContactDO::getTelephone, reqVO.getTelephone())
.eqIfPresent(CrmContactDO::getEmail, reqVO.getEmail())
.eqIfPresent(CrmContactDO::getCustomerId, reqVO.getCustomerId())
.likeIfPresent(CrmContactDO::getName, reqVO.getName())
.eqIfPresent(CrmContactDO::getQq, reqVO.getQq())
.eqIfPresent(CrmContactDO::getWechat, reqVO.getWechat())
.orderByDesc(CrmContactDO::getId));
}
default PageResult<CrmContactDO> selectPageByCustomer(CrmContactPageReqVO pageVO) {
return selectPage(pageVO, new LambdaQueryWrapperX<CrmContactDO>()
.eq(CrmContactDO::getCustomerId, pageVO.getCustomerId())
.likeIfPresent(CrmContactDO::getName, pageVO.getName())
.eqIfPresent(CrmContactDO::getMobile, pageVO.getMobile())
.eqIfPresent(CrmContactDO::getTelephone, pageVO.getTelephone())
.eqIfPresent(CrmContactDO::getEmail, pageVO.getEmail())
.eqIfPresent(CrmContactDO::getQq, pageVO.getQq())
.eqIfPresent(CrmContactDO::getWechat, pageVO.getWechat())
.orderByDesc(CrmContactDO::getId));
}
}

View File

@ -1,80 +0,0 @@
package cn.iocoder.yudao.module.crm.service.contact;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.ContactCreateReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.ContactPageReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.ContactUpdateReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
/**
* crm联系人 Service 接口
*
* @author 芋道源码
*/
public interface ContactService {
/**
* 创建crm联系人
*
* @param createReqVO 创建信息
* @param userId 用户编号
* @return 编号
*/
Long createContact(@Valid ContactCreateReqVO createReqVO, Long userId);
/**
* 更新crm联系人
*
* @param updateReqVO 更新信息
*/
void updateContact(@Valid ContactUpdateReqVO updateReqVO);
/**
* 删除crm联系人
*
* @param id 编号
*/
void deleteContact(Long id);
/**
* 获得crm联系人
*
* @param id 编号
* @return crm联系人
*/
ContactDO getContact(Long id);
/**
* 获得crm联系人列表
*
* @param ids 编号
* @return crm联系人列表
*/
List<ContactDO> getContactList(Collection<Long> ids);
/**
* 获得crm联系人分页
*
* @param pageReqVO 分页查询
* @return crm联系人分页
*/
PageResult<ContactDO> getContactPage(ContactPageReqVO pageReqVO);
/**
* 获得crm联系人列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return crm联系人列表
*/
List<ContactDO> getContactList(ContactPageReqVO exportReqVO);
/**
* 获取所有联系人列表只返回姓名和id
* @return 所有联系人列表
*/
List<ContactDO> getContactList();
}

View File

@ -0,0 +1,87 @@
package cn.iocoder.yudao.module.crm.service.contact;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactCreateReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactUpdateReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
/**
* CRM 联系人 Service 接口
*
* @author 芋道源码
*/
public interface CrmContactService {
/**
* 创建联系人
*
* @param createReqVO 创建信息
* @param userId 用户编号
* @return 编号
*/
Long createContact(@Valid CrmContactCreateReqVO createReqVO, Long userId);
/**
* 更新联系人
*
* @param updateReqVO 更新信息
*/
void updateContact(@Valid CrmContactUpdateReqVO updateReqVO);
/**
* 删除联系人
*
* @param id 编号
*/
void deleteContact(Long id);
/**
* 获得联系人
*
* @param id 编号
* @return 联系人
*/
CrmContactDO getContact(Long id);
/**
* 获得联系人列表
*
* @param ids 编号
* @return 联系人列表
*/
List<CrmContactDO> getContactList(Collection<Long> ids);
/**
* 获得联系人分页
*
* 数据权限基于 {@link CrmContactDO}
*
* @param pageReqVO 分页查询
* @return 联系人分页
*/
PageResult<CrmContactDO> getContactPage(CrmContactPageReqVO pageReqVO);
/**
* 获得联系人分页基于指定客户
*
* 数据权限基于 {@link CrmCustomerDO} 读取
*
* @param pageVO 分页查询
* @return 联系人分页
*/
PageResult<CrmContactDO> getContactPageByCustomer(CrmContactPageReqVO pageVO);
/**
* 获取所有联系人列表
*
* @return 所有联系人列表
*/
List<CrmContactDO> getContactList();
}

View File

@ -3,13 +3,13 @@ package cn.iocoder.yudao.module.crm.service.contact;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil; import cn.hutool.core.collection.ListUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.ContactBaseVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBaseVO;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.ContactCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactCreateReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.ContactPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.ContactUpdateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactUpdateReqVO;
import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert; import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
import cn.iocoder.yudao.module.crm.dal.mysql.contact.ContactMapper; import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper;
import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission;
import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.framework.enums.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.enums.CrmPermissionLevelEnum;
@ -24,7 +24,6 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Collection; import java.util.Collection;
import java.util.List; 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.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTACT_NOT_EXISTS; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTACT_NOT_EXISTS;
@ -32,16 +31,16 @@ import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;
/** /**
* crm联系人 Service 实现类 * CRM 联系人 Service 实现类
* *
* @author 芋道源码 * @author 芋道源码
*/ */
@Service @Service
@Validated @Validated
public class ContactServiceImpl implements ContactService { public class CrmContactServiceImpl implements CrmContactService {
@Resource @Resource
private ContactMapper contactMapper; private CrmContactMapper contactMapper;
@Resource @Resource
private CrmCustomerService customerService; private CrmCustomerService customerService;
@ -52,36 +51,53 @@ public class ContactServiceImpl implements ContactService {
private AdminUserApi adminUserApi; private AdminUserApi adminUserApi;
@Override @Override
public Long createContact(ContactCreateReqVO createReqVO, Long userId) { @Transactional(rollbackFor = Exception.class)
//@todo public Long createContact(CrmContactCreateReqVO createReqVO, Long userId) {
//校验 // 1.1 校验
validateDataExist(createReqVO); validateRelationDataExists(createReqVO);
// 插入 // 1.2 插入
ContactDO contact = ContactConvert.INSTANCE.convert(createReqVO); CrmContactDO contact = ContactConvert.INSTANCE.convert(createReqVO);
contactMapper.insert(contact); contactMapper.insert(contact);
// 创建数据权限 // 2. 创建数据权限
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CONTACTS.getType()) crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
.setBizId(contact.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 .setBizType(CrmBizTypeEnum.CRM_CONTACTS.getType()).setBizId(contact.getId())
.setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
// 返回
return contact.getId(); return contact.getId();
} }
@Override @Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
public void updateContact(ContactUpdateReqVO updateReqVO) { public void updateContact(CrmContactUpdateReqVO updateReqVO) {
// 校验存在 // 1. 校验存在
validateContactExists(updateReqVO.getId()); validateContactExists(updateReqVO.getId());
validateDataExist(updateReqVO); validateRelationDataExists(updateReqVO);
// 更新 // 2. 更新
ContactDO updateObj = ContactConvert.INSTANCE.convert(updateReqVO); CrmContactDO updateObj = ContactConvert.INSTANCE.convert(updateReqVO);
contactMapper.updateById(updateObj); contactMapper.updateById(updateObj);
} }
/**
* 校验关联的数据都存在
*
* @param saveReqVO 新增/修改请求 VO
*/
private void validateRelationDataExists(CrmContactBaseVO saveReqVO){
// 1. 校验客户
if (saveReqVO.getCustomerId() != null && customerService.getCustomer(saveReqVO.getCustomerId()) == null) {
throw exception(CUSTOMER_NOT_EXISTS);
}
// 2. 校验负责人
if (saveReqVO.getOwnerUserId() != null && adminUserApi.getUser(saveReqVO.getOwnerUserId()) == null) {
throw exception(USER_NOT_EXISTS);
}
// 3. 直属上级
if (saveReqVO.getParentId() != null && contactMapper.selectById(saveReqVO.getParentId()) == null) {
throw exception(CONTACT_NOT_EXISTS);
}
}
@Override @Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, bizId = "#id", level = CrmPermissionLevelEnum.WRITE) @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, bizId = "#id", level = CrmPermissionLevelEnum.WRITE)
public void deleteContact(Long id) { public void deleteContact(Long id) {
// 校验存在 // 校验存在
@ -96,14 +112,15 @@ public class ContactServiceImpl implements ContactService {
} }
} }
// TODO 芋艿是否要做数据权限的校验
@Override @Override
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, bizId = "#id", level = CrmPermissionLevelEnum.READ) @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACTS, bizId = "#id", level = CrmPermissionLevelEnum.READ)
public ContactDO getContact(Long id) { public CrmContactDO getContact(Long id) {
return contactMapper.selectById(id); return contactMapper.selectById(id);
} }
@Override @Override
public List<ContactDO> getContactList(Collection<Long> ids) { public List<CrmContactDO> getContactList(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) { if (CollUtil.isEmpty(ids)) {
return ListUtil.empty(); return ListUtil.empty();
} }
@ -111,34 +128,20 @@ public class ContactServiceImpl implements ContactService {
} }
@Override @Override
public PageResult<ContactDO> getContactPage(ContactPageReqVO pageReqVO) { public PageResult<CrmContactDO> getContactPage(CrmContactPageReqVO pageReqVO) {
// TODO puhui999后面要改成基于数据权限的查询
return contactMapper.selectPage(pageReqVO); return contactMapper.selectPage(pageReqVO);
} }
@Override @Override
public List<ContactDO> getContactList(ContactPageReqVO exportReqVO) { @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageVO.customerId", level = CrmPermissionLevelEnum.READ)
return contactMapper.selectList(exportReqVO); public PageResult<CrmContactDO> getContactPageByCustomer(CrmContactPageReqVO pageVO) {
return contactMapper.selectPageByCustomer(pageVO);
} }
@Override @Override
public List<ContactDO> getContactList() { public List<CrmContactDO> getContactList() {
return contactMapper.selectList(); return contactMapper.selectList();
} }
// TODO 芋艿后面在看下这个方法
private void validateDataExist(ContactBaseVO contactBaseVO){
// 1.校验客户
if (contactBaseVO.getCustomerId() != null) {
Optional.ofNullable(customerService.getCustomer(contactBaseVO.getCustomerId())).orElseThrow(() -> exception(CUSTOMER_NOT_EXISTS));
}
// 2.校验负责人
if (contactBaseVO.getOwnerUserId() != null) {
Optional.ofNullable(adminUserApi.getUser(contactBaseVO.getOwnerUserId())).orElseThrow(() -> exception(USER_NOT_EXISTS));
}
// 3.直属上级
if (contactBaseVO.getParentId() != null) {
Optional.ofNullable(contactMapper.selectById(contactBaseVO.getParentId())).orElseThrow(() -> exception(CONTACT_NOT_EXISTS));
}
}
} }

View File

@ -1,4 +0,0 @@
/**
* 联系人
*/
package cn.iocoder.yudao.module.crm.service.contact;

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.crm.service.customer; package cn.iocoder.yudao.module.crm.service.customer;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO;
@ -19,10 +20,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
@ -96,6 +94,9 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
@Override @Override
public List<CrmCustomerDO> getCustomerList(Collection<Long> ids) { public List<CrmCustomerDO> getCustomerList(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) {
return Collections.emptyList();
}
return customerMapper.selectBatchIds(ids); return customerMapper.selectBatchIds(ids);
} }