Merge remote-tracking branch 'yudao/develop' into develop
This commit is contained in:
commit
e6f4c1f0d5
|
@ -92,6 +92,8 @@
|
|||
|
||||
如果你想把【完整版】的功能,迁移到【精简版】,可以参考 [《迁移功能到精简版》](https://doc.iocoder.cn/migrate-module/) 文档。
|
||||
|
||||
如果你想把【完整版】的功能,迁移到【精简版】,可以参考 [《迁移功能到精简版》](https://doc.iocoder.cn/migrate-module/) 文档。
|
||||
|
||||
## 😎 开源协议
|
||||
|
||||
**为什么推荐使用本项目?**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
-- `ruoyi-vue-pro`.crm_contact_business_link definition
|
||||
|
||||
CREATE TABLE `crm_contact_business_link` (
|
||||
CREATE TABLE `crm_contact_business` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`contact_id` int(11) DEFAULT NULL COMMENT '联系人id',
|
||||
`business_id` int(11) DEFAULT NULL COMMENT '商机id',
|
||||
|
@ -10,6 +10,5 @@ CREATE TABLE `crm_contact_business_link` (
|
|||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||
`tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '租户编号',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `crm_contact_business_link_un` (`contact_id`,`business_id`,`deleted`,`tenant_id`)
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='联系人商机关联表';
|
|
@ -39,6 +39,10 @@ public interface ErrorCodeConstants {
|
|||
ErrorCode CUSTOMER_IN_POOL = new ErrorCode(1_020_006_004, "客户【{}】放入公海失败,原因:已经是公海客户");
|
||||
ErrorCode CUSTOMER_LOCKED_PUT_POOL_FAIL = new ErrorCode(1_020_006_005, "客户【{}】放入公海失败,原因:客户已锁定");
|
||||
ErrorCode CUSTOMER_UPDATE_OWNER_USER_FAIL = new ErrorCode(1_020_006_006, "更新客户【{}】负责人失败, 原因:系统异常");
|
||||
ErrorCode CUSTOMER_LOCK_FAIL_IS_LOCK = new ErrorCode(1_020_006_007, "锁定客户失败,它已经处于锁定状态");
|
||||
ErrorCode CUSTOMER_UNLOCK_FAIL_IS_UNLOCK = new ErrorCode(1_020_006_008, "锁定客户失败,它已经处于未锁定状态");
|
||||
ErrorCode CUSTOMER_LOCK_EXCEED_LIMIT = new ErrorCode(1_020_006_009, "锁定客户失败,超出锁定规则上限");
|
||||
ErrorCode CUSTOMER_OWNER_EXCEED_LIMIT = new ErrorCode(1_020_006_010, "操作失败,超出客户数拥有上限");
|
||||
|
||||
// ========== 权限管理 1_020_007_000 ==========
|
||||
ErrorCode CRM_PERMISSION_NOT_EXISTS = new ErrorCode(1_020_007_000, "数据权限不存在");
|
||||
|
|
|
@ -18,19 +18,19 @@ public enum CrmCustomerLimitConfigTypeEnum implements IntArrayValuable {
|
|||
/**
|
||||
* 拥有客户数限制
|
||||
*/
|
||||
CUSTOMER_QUANTITY_LIMIT(1, "拥有客户数限制"),
|
||||
CUSTOMER_OWNER_LIMIT(1, "拥有客户数限制"),
|
||||
/**
|
||||
* 锁定客户数限制
|
||||
*/
|
||||
CUSTOMER_LOCK_LIMIT(2, "锁定客户数限制"),
|
||||
;
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmCustomerLimitConfigTypeEnum::getCode).toArray();
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmCustomerLimitConfigTypeEnum::getType).toArray();
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private final Integer code;
|
||||
private final Integer type;
|
||||
/**
|
||||
* 状态名
|
||||
*/
|
||||
|
|
|
@ -7,8 +7,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|||
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.business.vo.business.*;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO;
|
||||
import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
|
||||
|
@ -30,12 +28,10 @@ import org.springframework.web.bind.annotation.*;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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.convertSet;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
|
@ -47,16 +43,14 @@ public class CrmBusinessController {
|
|||
|
||||
@Resource
|
||||
private CrmBusinessService businessService;
|
||||
|
||||
@Resource
|
||||
private CrmCustomerService customerService;
|
||||
|
||||
@Resource
|
||||
private CrmBusinessStatusTypeService businessStatusTypeService;
|
||||
|
||||
@Resource
|
||||
private CrmBusinessStatusService businessStatusService;
|
||||
|
||||
// TODO @商机待定:CrmBusinessCreateReqVO、CrmBusinessUpdateReqVO、CrmBusinessRespVO 按照新的 VO 规范
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建商机")
|
||||
@PreAuthorize("@ss.hasPermission('crm:business:create')")
|
||||
|
@ -95,27 +89,7 @@ public class CrmBusinessController {
|
|||
@PreAuthorize("@ss.hasPermission('crm:business:query')")
|
||||
public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPage(@Valid CrmBusinessPageReqVO pageVO) {
|
||||
PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPage(pageVO, getLoginUserId());
|
||||
if (CollUtil.isEmpty(pageResult.getList())) {
|
||||
return success(PageResult.empty(pageResult.getTotal()));
|
||||
}
|
||||
// 处理客户名称回显
|
||||
// TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈;
|
||||
Set<Long> customerIds = pageResult.getList().stream()
|
||||
.map(CrmBusinessDO::getCustomerId).filter(Objects::nonNull).collect(Collectors.toSet());
|
||||
List<CrmCustomerDO> customerList = customerService.getCustomerList(customerIds, getLoginUserId());
|
||||
// 处理商机状态类型名称回显
|
||||
Set<Long> statusTypeIds = pageResult.getList().stream()
|
||||
.map(CrmBusinessDO::getStatusTypeId).filter(Objects::nonNull).collect(Collectors.toSet());
|
||||
CrmBusinessStatusTypeQueryVO queryStatusTypeVO = new CrmBusinessStatusTypeQueryVO();
|
||||
queryStatusTypeVO.setIdList(statusTypeIds);
|
||||
List<CrmBusinessStatusTypeDO> statusTypeList = businessStatusTypeService.selectList(queryStatusTypeVO);
|
||||
// 处理商机状态名称回显
|
||||
Set<Long> statusIds = pageResult.getList().stream()
|
||||
.map(CrmBusinessDO::getStatusId).filter(Objects::nonNull).collect(Collectors.toSet());
|
||||
CrmBusinessStatusQueryVO queryVO = new CrmBusinessStatusQueryVO();
|
||||
queryVO.setIdList(statusIds);
|
||||
List<CrmBusinessStatusDO> statusList = businessStatusService.selectList(queryVO);
|
||||
return success(CrmBusinessConvert.INSTANCE.convertPage(pageResult, customerList, statusTypeList, statusList));
|
||||
return success(buildBusinessDetailPageResult(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/page-by-customer")
|
||||
|
@ -123,24 +97,15 @@ public class CrmBusinessController {
|
|||
public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPageByCustomer(@Valid CrmBusinessPageReqVO pageReqVO) {
|
||||
Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空");
|
||||
PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomerId(pageReqVO);
|
||||
// 处理客户名称回显
|
||||
// TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈;
|
||||
Set<Long> customerIds = pageResult.getList().stream()
|
||||
.map(CrmBusinessDO::getCustomerId).filter(Objects::nonNull).collect(Collectors.toSet());
|
||||
List<CrmCustomerDO> customerList = customerService.getCustomerList(customerIds, getLoginUserId());
|
||||
// 处理商机状态类型名称回显
|
||||
Set<Long> statusTypeIds = pageResult.getList().stream()
|
||||
.map(CrmBusinessDO::getStatusTypeId).filter(Objects::nonNull).collect(Collectors.toSet());
|
||||
CrmBusinessStatusTypeQueryVO queryStatusTypeVO = new CrmBusinessStatusTypeQueryVO();
|
||||
queryStatusTypeVO.setIdList(statusTypeIds);
|
||||
List<CrmBusinessStatusTypeDO> statusTypeList = businessStatusTypeService.selectList(queryStatusTypeVO);
|
||||
// 处理商机状态名称回显
|
||||
Set<Long> statusIds = pageResult.getList().stream()
|
||||
.map(CrmBusinessDO::getStatusId).filter(Objects::nonNull).collect(Collectors.toSet());
|
||||
CrmBusinessStatusQueryVO queryVO = new CrmBusinessStatusQueryVO();
|
||||
queryVO.setIdList(statusIds);
|
||||
List<CrmBusinessStatusDO> statusList = businessStatusService.selectList(queryVO);
|
||||
return success(CrmBusinessConvert.INSTANCE.convertPage(pageResult, customerList, statusTypeList, statusList));
|
||||
return success(buildBusinessDetailPageResult(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/page-by-contact")
|
||||
@Operation(summary = "获得联系人的商机分页")
|
||||
@PreAuthorize("@ss.hasPermission('crm:business:query')")
|
||||
public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessContactPage(@Valid CrmBusinessPageReqVO pageReqVO) {
|
||||
PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByContact(pageReqVO);
|
||||
return success(buildBusinessDetailPageResult(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
|
@ -152,8 +117,27 @@ public class CrmBusinessController {
|
|||
exportReqVO.setPageSize(PAGE_SIZE_NONE);
|
||||
PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPage(exportReqVO, getLoginUserId());
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "商机.xls", "数据", CrmBusinessExcelVO.class,
|
||||
CrmBusinessConvert.INSTANCE.convertList02(pageResult.getList()));
|
||||
ExcelUtils.write(response, "商机.xls", "数据", CrmBusinessRespVO.class,
|
||||
buildBusinessDetailPageResult(pageResult).getList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建详细的商机分页结果
|
||||
*
|
||||
* @param pageResult 简单的商机分页结果
|
||||
* @return 详细的商机分页结果
|
||||
*/
|
||||
private PageResult<CrmBusinessRespVO> buildBusinessDetailPageResult(PageResult<CrmBusinessDO> pageResult) {
|
||||
if (CollUtil.isEmpty(pageResult.getList())) {
|
||||
return PageResult.empty(pageResult.getTotal());
|
||||
}
|
||||
List<CrmBusinessStatusTypeDO> statusTypeList = businessStatusTypeService.getBusinessStatusTypeList(
|
||||
convertSet(pageResult.getList(), CrmBusinessDO::getStatusTypeId));
|
||||
List<CrmBusinessStatusDO> statusList = businessStatusService.getBusinessStatusList(
|
||||
convertSet(pageResult.getList(), CrmBusinessDO::getStatusId));
|
||||
List<CrmCustomerDO> customerList = customerService.getCustomerList(
|
||||
convertSet(pageResult.getList(), CrmBusinessDO::getCustomerId));
|
||||
return CrmBusinessConvert.INSTANCE.convertPage(pageResult, customerList, statusTypeList, statusList);
|
||||
}
|
||||
|
||||
@PutMapping("/transfer")
|
||||
|
|
|
@ -20,6 +20,9 @@ public class CrmBusinessPageReqVO extends PageParam {
|
|||
@Schema(description = "客户编号", example = "10795")
|
||||
private Long customerId;
|
||||
|
||||
@Schema(description = "联系人编号", example = "10795")
|
||||
private Long contactId;
|
||||
|
||||
@Schema(description = "场景类型", example = "1")
|
||||
@InEnum(CrmSceneTypeEnum.class)
|
||||
private Integer sceneType; // 场景类型,为 null 时则表示全部
|
||||
|
|
|
@ -6,6 +6,7 @@ import cn.hutool.core.util.NumberUtil;
|
|||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
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.contact.vo.*;
|
||||
|
@ -13,6 +14,7 @@ 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.dataobject.customer.CrmCustomerDO;
|
||||
import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants;
|
||||
import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService;
|
||||
import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
|
||||
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
|
@ -54,10 +56,13 @@ public class CrmContactController {
|
|||
private CrmContactService contactService;
|
||||
@Resource
|
||||
private CrmCustomerService customerService;
|
||||
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
|
||||
@Resource
|
||||
private CrmContactBusinessService contactBusinessLinkService;
|
||||
|
||||
// TODO @zyna:CrmContactCreateReqVO、CrmContactUpdateReqVO、CrmContactRespVO 按照新的 VO 规范搞哈;可以参考 dept 模块
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建联系人")
|
||||
@PreAuthorize("@ss.hasPermission('crm:contact:create')")
|
||||
|
@ -96,7 +101,7 @@ public class CrmContactController {
|
|||
NumberUtil.parseLong(contact.getCreator()), contact.getOwnerUserId())));
|
||||
// 2. 获取客户信息
|
||||
List<CrmCustomerDO> customerList = customerService.getCustomerList(
|
||||
Collections.singletonList(contact.getCustomerId()), getLoginUserId());
|
||||
Collections.singletonList(contact.getCustomerId()));
|
||||
// 3. 直属上级
|
||||
List<CrmContactDO> parentContactList = contactService.getContactList(
|
||||
Collections.singletonList(contact.getParentId()), getLoginUserId());
|
||||
|
@ -107,10 +112,11 @@ public class CrmContactController {
|
|||
@Operation(summary = "获得联系人列表")
|
||||
@PreAuthorize("@ss.hasPermission('crm:contact:query')")
|
||||
public CommonResult<List<CrmContactSimpleRespVO>> getSimpleContactList() {
|
||||
// TODO @zyna:建议 contactService 单独搞个 list 接口哈
|
||||
CrmContactPageReqVO pageReqVO = new CrmContactPageReqVO();
|
||||
pageReqVO.setPageSize(PAGE_SIZE_NONE);
|
||||
List<CrmContactDO> list = contactService.getContactPage(pageReqVO, getLoginUserId()).getList();
|
||||
return success(CrmContactConvert.INSTANCE.convertAllList(list));
|
||||
return success(BeanUtils.toBean(list, CrmContactSimpleRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
|
@ -118,7 +124,7 @@ public class CrmContactController {
|
|||
@PreAuthorize("@ss.hasPermission('crm:contact:query')")
|
||||
public CommonResult<PageResult<CrmContactRespVO>> getContactPage(@Valid CrmContactPageReqVO pageVO) {
|
||||
PageResult<CrmContactDO> pageResult = contactService.getContactPage(pageVO, getLoginUserId());
|
||||
return success(convertDetailContactPage(pageResult));
|
||||
return success(buildContactDetailPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/page-by-customer")
|
||||
|
@ -126,7 +132,7 @@ public class CrmContactController {
|
|||
public CommonResult<PageResult<CrmContactRespVO>> getContactPageByCustomer(@Valid CrmContactPageReqVO pageVO) {
|
||||
Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空");
|
||||
PageResult<CrmContactDO> pageResult = contactService.getContactPageByCustomerId(pageVO);
|
||||
return success(convertDetailContactPage(pageResult));
|
||||
return success(buildContactDetailPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
|
@ -138,23 +144,23 @@ public class CrmContactController {
|
|||
exportReqVO.setPageNo(PAGE_SIZE_NONE);
|
||||
PageResult<CrmContactDO> pageResult = contactService.getContactPage(exportReqVO, getLoginUserId());
|
||||
ExcelUtils.write(response, "联系人.xls", "数据", CrmContactRespVO.class,
|
||||
convertDetailContactPage(pageResult).getList());
|
||||
buildContactDetailPage(pageResult).getList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换成详细的联系人分页,即读取关联信息
|
||||
* 构建详细的联系人分页结果
|
||||
*
|
||||
* @param pageResult 联系人分页
|
||||
* @return 详细的联系人分页
|
||||
* @param pageResult 简单的联系人分页结果
|
||||
* @return 详细的联系人分页结果
|
||||
*/
|
||||
private PageResult<CrmContactRespVO> convertDetailContactPage(PageResult<CrmContactDO> pageResult) {
|
||||
private PageResult<CrmContactRespVO> buildContactDetailPage(PageResult<CrmContactDO> pageResult) {
|
||||
List<CrmContactDO> contactList = pageResult.getList();
|
||||
if (CollUtil.isEmpty(contactList)) {
|
||||
return PageResult.empty(pageResult.getTotal());
|
||||
}
|
||||
// 1. 获取客户列表
|
||||
List<CrmCustomerDO> crmCustomerDOList = customerService.getCustomerList(
|
||||
convertSet(contactList, CrmContactDO::getCustomerId), getLoginUserId());
|
||||
convertSet(contactList, CrmContactDO::getCustomerId));
|
||||
// 2. 获取创建人、负责人列表
|
||||
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(contactList,
|
||||
contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId())));
|
||||
|
@ -172,4 +178,22 @@ public class CrmContactController {
|
|||
return success(true);
|
||||
}
|
||||
|
||||
// ================== 关联/取关联系人 ===================
|
||||
|
||||
@PostMapping("/create-business-list")
|
||||
@Operation(summary = "创建联系人与联系人的关联")
|
||||
@PreAuthorize("@ss.hasPermission('crm:contact:create-business')")
|
||||
public CommonResult<Boolean> createContactBusinessList(@Valid @RequestBody CrmContactBusinessReqVO createReqVO) {
|
||||
contactBusinessLinkService.createContactBusinessList(createReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete-business-list")
|
||||
@Operation(summary = "删除联系人与联系人的关联")
|
||||
@PreAuthorize("@ss.hasPermission('crm:contact:delete-business')")
|
||||
public CommonResult<Boolean> deleteContactBusinessList(@Valid @RequestBody CrmContactBusinessReqVO deleteReqVO) {
|
||||
contactBusinessLinkService.deleteContactBusinessList(deleteReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,11 +8,11 @@ import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
|
|||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
|
||||
|
@ -75,29 +75,29 @@ public class CrmContactBaseVO {
|
|||
@ExcelProperty(value = "邮箱",order = 4)
|
||||
private String email;
|
||||
|
||||
@Schema(description = "地区编号", example = "20158")
|
||||
private Integer areaId;
|
||||
|
||||
@ExcelProperty(value = "地址",order = 5)
|
||||
@Schema(description = "地址")
|
||||
private String address;
|
||||
|
||||
@Schema(description = "下次联系时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
@ExcelProperty(value = "下次联系时间",order = 6)
|
||||
private LocalDateTime nextTime;
|
||||
private String detailAddress;
|
||||
|
||||
@Schema(description = "备注", example = "你说的对")
|
||||
@ExcelProperty(value = "备注",order = 6)
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "最后跟进时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ExcelProperty(value = "最后跟进时间",order = 6)
|
||||
private LocalDateTime lastTime;
|
||||
|
||||
@Schema(description = "负责人用户编号", example = "14334")
|
||||
@NotNull(message = "负责人不能为空")
|
||||
private Long ownerUserId;
|
||||
|
||||
@Schema(description = "地区编号", example = "20158")
|
||||
private Integer areaId;
|
||||
@Schema(description = "最后跟进时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ExcelProperty(value = "最后跟进时间",order = 6)
|
||||
private LocalDateTime contactLastTime;
|
||||
|
||||
@Schema(description = "下次联系时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
@ExcelProperty(value = "下次联系时间",order = 6)
|
||||
private LocalDateTime contactNextTime;
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - CRM 联系人商机 Request VO") // 用于关联,取消关联的操作
|
||||
@Data
|
||||
public class CrmContactBusinessReqVO {
|
||||
|
||||
@Schema(description = "联系人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20878")
|
||||
@NotNull(message="联系人不能为空")
|
||||
private Long contactId;
|
||||
|
||||
@Schema(description = "商机编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "7638")
|
||||
@NotEmpty(message="商机不能为空")
|
||||
private List<Long> businessIds;
|
||||
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
package cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
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.business.vo.business.CrmBusinessRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkSaveReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contactbusinesslink.CrmContactBusinessLinkDO;
|
||||
import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
|
||||
import cn.iocoder.yudao.module.crm.service.contactbusinesslink.CrmContactBusinessLinkService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
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.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS;
|
||||
|
||||
@Tag(name = "管理后台 - CRM 联系人商机关联")
|
||||
@RestController
|
||||
@RequestMapping("/crm/contact-business-link")
|
||||
@Validated
|
||||
public class CrmContactBusinessLinkController {
|
||||
|
||||
@Resource
|
||||
private CrmContactBusinessLinkService contactBusinessLinkService;
|
||||
@Resource
|
||||
private CrmBusinessService crmBusinessService;
|
||||
|
||||
// TODO @zyna:createContactBusinessLink 和 createContactBusinessLinkBatch 是不是合并成一个接口?contactId、List<businessId>
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建联系人商机关联")
|
||||
@PreAuthorize("@ss.hasPermission('crm:contact-business-link:create')")
|
||||
public CommonResult<Long> createContactBusinessLink(@Valid @RequestBody CrmContactBusinessLinkSaveReqVO createReqVO) {
|
||||
return success(contactBusinessLinkService.createContactBusinessLink(createReqVO));
|
||||
}
|
||||
|
||||
@PostMapping("/create-batch")
|
||||
@Operation(summary = "创建联系人商机关联")
|
||||
@PreAuthorize("@ss.hasPermission('crm:contact-business-link:create')")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public CommonResult<Boolean> createContactBusinessLinkBatch(
|
||||
@Valid @RequestBody List<CrmContactBusinessLinkSaveReqVO> createReqVO) {
|
||||
createReqVO.stream().forEach(item -> {
|
||||
CrmBusinessDO crmBusinessDO = crmBusinessService.getBusiness(item.getBusinessId());
|
||||
if(crmBusinessDO == null){
|
||||
throw exception(BUSINESS_NOT_EXISTS);
|
||||
}
|
||||
});
|
||||
contactBusinessLinkService.createContactBusinessLinkBatch(createReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
// TODO @zyna:这个接口是不是可以删除掉了哈?应该不存在更新。
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新联系人商机关联")
|
||||
@PreAuthorize("@ss.hasPermission('crm:contact-business-link:update')")
|
||||
public CommonResult<Boolean> updateContactBusinessLink(@Valid @RequestBody CrmContactBusinessLinkSaveReqVO updateReqVO) {
|
||||
contactBusinessLinkService.updateContactBusinessLink(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
// TODO @zyna:删除,是不是传递 ids?
|
||||
@DeleteMapping("/delete-batch")
|
||||
@Operation(summary = "批量删除联系人商机关联")
|
||||
@PreAuthorize("@ss.hasPermission('crm:contact-business-link:delete')")
|
||||
public CommonResult<Boolean> deleteContactBusinessLinkBatch(@Valid @RequestBody List<CrmContactBusinessLinkSaveReqVO> deleteList) {
|
||||
contactBusinessLinkService.deleteContactBusinessLink(deleteList);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
// TODO @zyna:这个接口是不是可以删除掉了哈?应该不存在单个读取;
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得联系人商机关联")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('crm:contact-business-link:query')")
|
||||
public CommonResult<CrmContactBusinessLinkRespVO> getContactBusinessLink(@RequestParam("id") Long id) {
|
||||
CrmContactBusinessLinkDO contactBusinessLink = contactBusinessLinkService.getContactBusinessLink(id);
|
||||
return success(BeanUtils.toBean(contactBusinessLink, CrmContactBusinessLinkRespVO.class));
|
||||
}
|
||||
|
||||
// TODO @zyna:这个可以转化下,使用客户编号去查询,就是使用 CrmBusinessController 的 getBusinessPageByCustomer 接口;目的是:复用
|
||||
@GetMapping("/page-by-contact")
|
||||
@Operation(summary = "获得联系人商机关联")
|
||||
@PreAuthorize("@ss.hasPermission('crm:contact-business-link:query')")
|
||||
public CommonResult<PageResult<CrmBusinessRespVO>> getContactBusinessLinkByContact(
|
||||
@Valid CrmContactBusinessLinkPageReqVO pageReqVO) {
|
||||
PageResult<CrmBusinessRespVO> contactBusinessLink = contactBusinessLinkService.getContactBusinessLinkPageByContact(pageReqVO);
|
||||
return success(contactBusinessLink);
|
||||
}
|
||||
|
||||
// TODO @zyna:这个优化下,搞到 CrmBusinessController 里去,加一个 CrmBusinessController 的 getBusinessPageByContact 接口;目的是:
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得联系人商机关联分页")
|
||||
@PreAuthorize("@ss.hasPermission('crm:contact-business-link:query')")
|
||||
public CommonResult<PageResult<CrmContactBusinessLinkRespVO>> getContactBusinessLinkPage(
|
||||
@Valid CrmContactBusinessLinkPageReqVO pageReqVO) {
|
||||
PageResult<CrmContactBusinessLinkDO> pageResult = contactBusinessLinkService.getContactBusinessLinkPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, CrmContactBusinessLinkRespVO.class));
|
||||
}
|
||||
|
||||
// TODO @zyna:最终梳理完后,应该就 2 个接口,要不直接合并到 CrmContactController 中,不作为独立模块,就关联、接触关联。其实和 user 设置它有哪些岗位、部门是类似的。
|
||||
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
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 = "管理后台 - CRM 联系人商机关联分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class CrmContactBusinessLinkPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "联系人编号", example = "20878")
|
||||
private Long contactId;
|
||||
|
||||
@Schema(description = "商机编号", example = "7638")
|
||||
private Long businessId;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - CRM 联系人商机关联 Response VO")
|
||||
@Data
|
||||
public class CrmContactBusinessLinkRespVO {
|
||||
|
||||
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "17220")
|
||||
@ExcelProperty("主键")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "联系人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20878")
|
||||
private Long contactId;
|
||||
|
||||
@Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7638")
|
||||
private Long businessId;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - CRM 联系人商机关联新增/修改 Request VO")
|
||||
@Data
|
||||
public class CrmContactBusinessLinkSaveReqVO {
|
||||
|
||||
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "17220")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "联系人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20878")
|
||||
@NotNull(message="联系人不能为空")
|
||||
private Long contactId;
|
||||
|
||||
@Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7638")
|
||||
@NotNull(message="商机不能为空")
|
||||
private Long businessId;
|
||||
|
||||
}
|
|
@ -88,7 +88,7 @@ public class CrmContractController {
|
|||
@PreAuthorize("@ss.hasPermission('crm:contract:query')")
|
||||
public CommonResult<PageResult<ContractRespVO>> getContractPage(@Valid CrmContractPageReqVO pageVO) {
|
||||
PageResult<CrmContractDO> pageResult = contractService.getContractPage(pageVO, getLoginUserId());
|
||||
return success(convertDetailContractPage(pageResult));
|
||||
return success(buildContractDetailPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/page-by-customer")
|
||||
|
@ -96,7 +96,7 @@ public class CrmContractController {
|
|||
public CommonResult<PageResult<ContractRespVO>> getContractPageByCustomer(@Valid CrmContractPageReqVO pageVO) {
|
||||
Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空");
|
||||
PageResult<CrmContractDO> pageResult = contractService.getContractPageByCustomerId(pageVO);
|
||||
return success(convertDetailContractPage(pageResult));
|
||||
return success(buildContractDetailPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
|
@ -112,19 +112,19 @@ public class CrmContractController {
|
|||
}
|
||||
|
||||
/**
|
||||
* 转换成详细的合同分页,即读取关联信息
|
||||
* 构建详细的合同分页结果
|
||||
*
|
||||
* @param pageResult 合同分页
|
||||
* @return 详细的合同分页
|
||||
* @param pageResult 简单的合同分页结果
|
||||
* @return 详细的合同分页结果
|
||||
*/
|
||||
private PageResult<ContractRespVO> convertDetailContractPage(PageResult<CrmContractDO> pageResult) {
|
||||
private PageResult<ContractRespVO> buildContractDetailPage(PageResult<CrmContractDO> pageResult) {
|
||||
List<CrmContractDO> contactList = pageResult.getList();
|
||||
if (CollUtil.isEmpty(contactList)) {
|
||||
return PageResult.empty(pageResult.getTotal());
|
||||
}
|
||||
// 1. 获取客户列表
|
||||
List<CrmCustomerDO> customerList = customerService.getCustomerList(
|
||||
convertSet(contactList, CrmContractDO::getCustomerId), getLoginUserId());
|
||||
convertSet(contactList, CrmContractDO::getCustomerId));
|
||||
// 2. 获取创建人、负责人列表
|
||||
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(contactList,
|
||||
contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId())));
|
||||
|
|
|
@ -58,6 +58,7 @@ public class CrmCustomerController {
|
|||
@Resource
|
||||
private OperateLogApi operateLogApi;
|
||||
|
||||
// TODO @puhui999:把 CrmCustomerCreateReqVO、CrmCustomerUpdateReqVO、CrmCustomerRespVO 按照新的规范,搞一下哈;
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建客户")
|
||||
@OperateLog(enable = false) // TODO 关闭原有日志记录;@puhui999:注解都先删除。先记录,没关系。我们下个迭代,就都删除掉操作日志了;
|
||||
|
@ -114,6 +115,7 @@ public class CrmCustomerController {
|
|||
}
|
||||
|
||||
// 2. 拼接数据
|
||||
// TODO @puhui999:距离进入公海的时间
|
||||
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
|
||||
convertSetByFlatMap(pageResult.getList(), user -> Stream.of(Long.parseLong(user.getCreator()), user.getOwnerUserId())));
|
||||
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
|
||||
|
@ -134,7 +136,7 @@ public class CrmCustomerController {
|
|||
}
|
||||
|
||||
@PutMapping("/transfer")
|
||||
@Operation(summary = "客户转移")
|
||||
@Operation(summary = "转移客户")
|
||||
@OperateLog(enable = false) // TODO 关闭原有日志记录
|
||||
@PreAuthorize("@ss.hasPermission('crm:customer:update')")
|
||||
public CommonResult<Boolean> transfer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) {
|
||||
|
@ -152,13 +154,12 @@ public class CrmCustomerController {
|
|||
return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class)));
|
||||
}
|
||||
|
||||
// TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了;
|
||||
@PutMapping("/lock")
|
||||
@Operation(summary = "锁定/解锁客户")
|
||||
@OperateLog(enable = false) // TODO 关闭原有日志记录
|
||||
@PreAuthorize("@ss.hasPermission('crm:customer:update')")
|
||||
public CommonResult<Boolean> lockCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) {
|
||||
customerService.lockCustomer(updateReqVO);
|
||||
public CommonResult<Boolean> lockCustomer(@Valid @RequestBody CrmCustomerLockReqVO lockReqVO) {
|
||||
customerService.lockCustomer(lockReqVO, getLoginUserId());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
|
@ -183,6 +184,7 @@ public class CrmCustomerController {
|
|||
return success(true);
|
||||
}
|
||||
|
||||
// TODO @puhui999:需要搞个 VO 类
|
||||
@PutMapping("/distribute")
|
||||
@Operation(summary = "分配公海给对应负责人")
|
||||
@Parameters({
|
||||
|
@ -192,7 +194,6 @@ public class CrmCustomerController {
|
|||
@PreAuthorize("@ss.hasPermission('crm:customer:distribute')")
|
||||
public CommonResult<Boolean> distributeCustomer(@RequestParam(value = "ids") List<Long> ids,
|
||||
@RequestParam(value = "ownerUserId") Long ownerUserId) {
|
||||
// 领取公海数据
|
||||
customerService.receiveCustomer(ids, ownerUserId);
|
||||
return success(true);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ public class CrmCustomerLimitConfigController {
|
|||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
|
||||
// TODO @puhui999:可以把 vo 改下哈
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建客户限制配置")
|
||||
@PreAuthorize("@ss.hasPermission('crm:customer-limit-config:create')")
|
||||
|
|
|
@ -26,6 +26,7 @@ public class CrmCustomerPoolConfigController {
|
|||
@Resource
|
||||
private CrmCustomerPoolConfigService customerPoolConfigService;
|
||||
|
||||
// TODO @puhui999:可以把 vo 改下哈
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获取客户公海规则设置")
|
||||
@PreAuthorize("@ss.hasPermission('crm:customer-pool-config:query')")
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - CRM 客户锁定/解锁 Request VO")
|
||||
@Data
|
||||
public class CrmCustomerLockReqVO {
|
||||
|
||||
@Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "客户锁定状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||
private Boolean lockStatus;
|
||||
|
||||
}
|
|
@ -28,4 +28,6 @@ public class CrmCustomerTransferReqVO {
|
|||
@Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
private Integer oldOwnerPermissionLevel;
|
||||
|
||||
// TODO @puhui999:联系人、商机、合同的转移
|
||||
|
||||
}
|
||||
|
|
|
@ -16,9 +16,9 @@ import java.util.Objects;
|
|||
@ToString(callSuper = true)
|
||||
public class CrmCustomerPoolConfigSaveReqVO extends CrmCustomerPoolConfigBaseVO {
|
||||
|
||||
// TODO @wanwan:AssertTrue 必须 is 开头哈;注意需要 json 忽略下,避免被序列化;
|
||||
// TODO @puhui999:AssertTrue 必须 is 开头哈;注意需要 json 忽略下,避免被序列化;
|
||||
@AssertTrue(message = "客户公海规则设置不正确")
|
||||
// TODO @wanwan:这个方法,是不是拆成 2 个,一个校验 contactExpireDays、一个校验 dealExpireDays;
|
||||
// TODO @puhui999:这个方法,是不是拆成 2 个,一个校验 contactExpireDays、一个校验 dealExpireDays;
|
||||
public boolean poolEnableValid() {
|
||||
if (!BooleanUtil.isTrue(getEnabled())) {
|
||||
return true;
|
||||
|
@ -27,7 +27,7 @@ public class CrmCustomerPoolConfigSaveReqVO extends CrmCustomerPoolConfigBaseVO
|
|||
}
|
||||
|
||||
@AssertTrue(message = "客户公海规则设置不正确")
|
||||
// TODO @wanwan:这个方法,是不是改成 isNotifyDaysValid() 更好点?本质校验的是 notifyDays 是否为空
|
||||
// TODO @puhui999:这个方法,是不是改成 isNotifyDaysValid() 更好点?本质校验的是 notifyDays 是否为空
|
||||
public boolean notifyEnableValid() {
|
||||
if (!BooleanUtil.isTrue(getNotifyEnabled())) {
|
||||
return true;
|
||||
|
|
|
@ -103,6 +103,7 @@ public class CrmPermissionController {
|
|||
// 拼接数据
|
||||
List<AdminUserRespDTO> userList = adminUserApi.getUserList(convertSet(permission, CrmPermissionDO::getUserId));
|
||||
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId));
|
||||
// TODO @puhui999:可能 postIds 为空的时候,会导致报错,看看怎么 fix 下
|
||||
Set<Long> postIds = CollectionUtils.convertSetByFlatMap(userList, AdminUserRespDTO::getPostIds, Collection::stream);
|
||||
Map<Long, PostRespDTO> postMap = postApi.getPostMap(postIds);
|
||||
return success(CrmPermissionConvert.INSTANCE.convert(permission, userList, deptMap, postMap));
|
||||
|
|
|
@ -93,7 +93,7 @@ public class CrmReceivableController {
|
|||
@PreAuthorize("@ss.hasPermission('crm:receivable:query')")
|
||||
public CommonResult<PageResult<CrmReceivableRespVO>> getReceivablePage(@Valid CrmReceivablePageReqVO pageReqVO) {
|
||||
PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(pageReqVO, getLoginUserId());
|
||||
return success(convertDetailReceivablePage(pageResult));
|
||||
return success(buildReceivableDetailPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/page-by-customer")
|
||||
|
@ -101,7 +101,7 @@ public class CrmReceivableController {
|
|||
public CommonResult<PageResult<CrmReceivableRespVO>> getReceivablePageByCustomer(@Valid CrmReceivablePageReqVO pageReqVO) {
|
||||
Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空");
|
||||
PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePageByCustomerId(pageReqVO);
|
||||
return success(convertDetailReceivablePage(pageResult));
|
||||
return success(buildReceivableDetailPage(pageResult));
|
||||
}
|
||||
|
||||
// TODO 芋艿:后面在优化导出
|
||||
|
@ -115,23 +115,23 @@ public class CrmReceivableController {
|
|||
PageResult<CrmReceivableDO> pageResult = receivableService.getReceivablePage(exportReqVO, getLoginUserId());
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "回款.xls", "数据", CrmReceivableRespVO.class,
|
||||
convertDetailReceivablePage(pageResult).getList());
|
||||
buildReceivableDetailPage(pageResult).getList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换成详细的回款分页,即读取关联信息
|
||||
* 构建详细的回款分页结果
|
||||
*
|
||||
* @param pageResult 回款分页
|
||||
* @return 详细的回款分页
|
||||
* @param pageResult 简单的回款分页结果
|
||||
* @return 详细的回款分页结果
|
||||
*/
|
||||
private PageResult<CrmReceivableRespVO> convertDetailReceivablePage(PageResult<CrmReceivableDO> pageResult) {
|
||||
private PageResult<CrmReceivableRespVO> buildReceivableDetailPage(PageResult<CrmReceivableDO> pageResult) {
|
||||
List<CrmReceivableDO> receivableList = pageResult.getList();
|
||||
if (CollUtil.isEmpty(receivableList)) {
|
||||
return PageResult.empty(pageResult.getTotal());
|
||||
}
|
||||
// 1. 获取客户列表
|
||||
List<CrmCustomerDO> customerList = customerService.getCustomerList(
|
||||
convertSet(receivableList, CrmReceivableDO::getCustomerId), getLoginUserId());
|
||||
convertSet(receivableList, CrmReceivableDO::getCustomerId));
|
||||
// 2. 获取创建人、负责人列表
|
||||
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(receivableList,
|
||||
contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId())));
|
||||
|
|
|
@ -123,10 +123,10 @@ public class CrmReceivablePlanController {
|
|||
}
|
||||
|
||||
/**
|
||||
* 转换成详细的回款计划分页,即读取关联信息
|
||||
* 构建详细的回款计划分页结果
|
||||
*
|
||||
* @param pageResult 回款计划分页
|
||||
* @return 详细的回款计划分页
|
||||
* @param pageResult 简单的回款计划分页结果
|
||||
* @return 详细的回款计划分页结果
|
||||
*/
|
||||
private PageResult<CrmReceivablePlanRespVO> convertDetailReceivablePlanPage(PageResult<CrmReceivablePlanDO> pageResult) {
|
||||
List<CrmReceivablePlanDO> receivablePlanList = pageResult.getList();
|
||||
|
@ -135,7 +135,7 @@ public class CrmReceivablePlanController {
|
|||
}
|
||||
// 1. 获取客户列表
|
||||
List<CrmCustomerDO> customerList = customerService.getCustomerList(
|
||||
convertSet(receivablePlanList, CrmReceivablePlanDO::getCustomerId), getLoginUserId());
|
||||
convertSet(receivablePlanList, CrmReceivablePlanDO::getCustomerId));
|
||||
// 2. 获取创建人、负责人列表
|
||||
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(receivablePlanList,
|
||||
contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId())));
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cn.iocoder.yudao.module.crm.convert.business;
|
||||
|
||||
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.business.vo.business.*;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
|
||||
|
@ -9,7 +10,6 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
|||
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -34,25 +34,23 @@ public interface CrmBusinessConvert {
|
|||
CrmBusinessRespVO convert(CrmBusinessDO bean);
|
||||
List<CrmBusinessRespVO> convert(List<CrmBusinessDO> bean);
|
||||
|
||||
PageResult<CrmBusinessRespVO> convertPage(PageResult<CrmBusinessDO> page);
|
||||
|
||||
List<CrmBusinessExcelVO> convertList02(List<CrmBusinessDO> list);
|
||||
|
||||
@Mapping(target = "bizId", source = "reqVO.id")
|
||||
CrmPermissionTransferReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId);
|
||||
|
||||
default PageResult<CrmBusinessRespVO> convertPage(PageResult<CrmBusinessDO> page, List<CrmCustomerDO> customerList,
|
||||
default PageResult<CrmBusinessRespVO> convertPage(PageResult<CrmBusinessDO> pageResult, List<CrmCustomerDO> customerList,
|
||||
List<CrmBusinessStatusTypeDO> statusTypeList, List<CrmBusinessStatusDO> statusList) {
|
||||
PageResult<CrmBusinessRespVO> result = convertPage(page);
|
||||
PageResult<CrmBusinessRespVO> voPageResult = BeanUtils.toBean(pageResult, CrmBusinessRespVO.class);
|
||||
// 拼接关联字段
|
||||
Map<Long, String> customerMap = convertMap(customerList, CrmCustomerDO::getId, CrmCustomerDO::getName);
|
||||
Map<Long, String> statusTypeMap = convertMap(statusTypeList, CrmBusinessStatusTypeDO::getId, CrmBusinessStatusTypeDO::getName);
|
||||
Map<Long, String> statusMap = convertMap(statusList, CrmBusinessStatusDO::getId, CrmBusinessStatusDO::getName);
|
||||
result.getList().forEach(type -> type
|
||||
voPageResult.getList().forEach(type -> type
|
||||
.setCustomerName(customerMap.get(type.getCustomerId()))
|
||||
.setStatusTypeName(statusTypeMap.get(type.getStatusTypeId()))
|
||||
.setStatusName(statusMap.get(type.getStatusId())));
|
||||
return result;
|
||||
return voPageResult;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package cn.iocoder.yudao.module.crm.convert.contact;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
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.dal.dataobject.contact.CrmContactDO;
|
||||
|
@ -13,12 +15,10 @@ import org.mapstruct.factory.Mappers;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
|
||||
|
||||
// TODO 芋艿:convert 后面在梳理下,略微有点乱
|
||||
/**
|
||||
* CRM 联系人 Convert
|
||||
*
|
||||
|
@ -39,64 +39,37 @@ public interface CrmContactConvert {
|
|||
|
||||
PageResult<CrmContactRespVO> convertPage(PageResult<CrmContactDO> page);
|
||||
|
||||
default PageResult<CrmContactRespVO> convertPage(PageResult<CrmContactDO> pageResult, Map<Long, AdminUserRespDTO> userMap,
|
||||
List<CrmCustomerDO> customerList, List<CrmContactDO> parentContactList) {
|
||||
List<CrmContactRespVO> list = converList(pageResult.getList(), userMap, customerList, parentContactList);
|
||||
return convertPage(pageResult).setList(list);
|
||||
}
|
||||
|
||||
List<CrmContactSimpleRespVO> convertAllList(List<CrmContactDO> list);
|
||||
|
||||
@Mapping(target = "bizId", source = "reqVO.id")
|
||||
CrmPermissionTransferReqBO convert(CrmContactTransferReqVO reqVO, Long userId);
|
||||
|
||||
/**
|
||||
* 转换详情信息
|
||||
*
|
||||
* @param contactDO 联系人
|
||||
* @param userMap 用户列表
|
||||
* @param crmCustomerDOList 客户
|
||||
* @return ContactRespVO
|
||||
*/
|
||||
default CrmContactRespVO convert(CrmContactDO contactDO, Map<Long, AdminUserRespDTO> userMap, List<CrmCustomerDO> crmCustomerDOList,
|
||||
List<CrmContactDO> contactList) {
|
||||
default PageResult<CrmContactRespVO> convertPage(PageResult<CrmContactDO> pageResult, Map<Long, AdminUserRespDTO> userMap,
|
||||
List<CrmCustomerDO> customerList, List<CrmContactDO> parentContactList) {
|
||||
PageResult<CrmContactRespVO> voPageResult = BeanUtils.toBean(pageResult, CrmContactRespVO.class);
|
||||
// 拼接关联字段
|
||||
Map<Long, CrmContactDO> parentContactMap = convertMap(parentContactList, CrmContactDO::getId);
|
||||
Map<Long, CrmCustomerDO> customerMap = convertMap(customerList, CrmCustomerDO::getId);
|
||||
voPageResult.getList().forEach(item -> {
|
||||
setUserInfo(item, userMap);
|
||||
findAndThen(customerMap, item.getCustomerId(), customer -> item.setCustomerName(customer.getName()));
|
||||
findAndThen(parentContactMap, item.getParentId(), contactDO -> item.setParentName(contactDO.getName()));
|
||||
});
|
||||
return voPageResult;
|
||||
}
|
||||
|
||||
default CrmContactRespVO convert(CrmContactDO contactDO, Map<Long, AdminUserRespDTO> userMap,
|
||||
List<CrmCustomerDO> customerList, List<CrmContactDO> parentContactList) {
|
||||
CrmContactRespVO contactVO = convert(contactDO);
|
||||
setUserInfo(contactVO, userMap);
|
||||
Map<Long, CrmCustomerDO> ustomerMap = crmCustomerDOList.stream().collect(Collectors.toMap(CrmCustomerDO::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()));
|
||||
Map<Long, CrmCustomerDO> customerMap = CollectionUtils.convertMap(customerList, CrmCustomerDO::getId);
|
||||
Map<Long, CrmContactDO> contactMap = CollectionUtils.convertMap(parentContactList, CrmContactDO::getId);
|
||||
findAndThen(customerMap, contactDO.getCustomerId(), customer -> contactVO.setCustomerName(customer.getName()));
|
||||
findAndThen(contactMap, contactDO.getParentId(), contact -> contactVO.setParentName(contact.getName()));
|
||||
return contactVO;
|
||||
}
|
||||
|
||||
default List<CrmContactRespVO> converList(List<CrmContactDO> contactList, Map<Long, AdminUserRespDTO> userMap,
|
||||
List<CrmCustomerDO> customerList, List<CrmContactDO> parentContactList) {
|
||||
List<CrmContactRespVO> result = convertList(contactList);
|
||||
Map<Long, CrmContactDO> parentContactMap = convertMap(parentContactList, CrmContactDO::getId);
|
||||
Map<Long, CrmCustomerDO> customerMap = convertMap(customerList, CrmCustomerDO::getId);
|
||||
result.forEach(item -> {
|
||||
setUserInfo(item, userMap);
|
||||
findAndThen(customerMap, item.getCustomerId(), customer -> { // TODO @zyna:这里的 { 可以去掉
|
||||
item.setCustomerName(customer.getName());
|
||||
});
|
||||
findAndThen(parentContactMap, item.getParentId(), contactDO -> { // TODO @zyna:这里的 { 可以去掉
|
||||
item.setParentName(contactDO.getName());
|
||||
});
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户信息
|
||||
*
|
||||
* @param contactRespVO 联系人Response VO
|
||||
* @param userMap 用户信息 map
|
||||
*/
|
||||
static void setUserInfo(CrmContactRespVO contactRespVO, Map<Long, AdminUserRespDTO> userMap) {
|
||||
contactRespVO.setAreaName(AreaUtils.format(contactRespVO.getAreaId()));
|
||||
findAndThen(userMap, contactRespVO.getOwnerUserId(), user -> {
|
||||
contactRespVO.setOwnerUserName(user == null ? "" : user.getNickname());
|
||||
});
|
||||
findAndThen(userMap, contactRespVO.getOwnerUserId(), user -> contactRespVO.setOwnerUserName(user.getNickname()));
|
||||
findAndThen(userMap, Long.parseLong(contactRespVO.getCreator()), user -> contactRespVO.setCreatorName(user.getNickname()));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
package cn.iocoder.yudao.module.crm.convert.contactbusinessslink;
|
||||
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkSaveReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contactbusinesslink.CrmContactBusinessLinkDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
// TODO @zyna:使用 BeanUtils 慢慢替代现有的 mapstruct 哈
|
||||
@Mapper
|
||||
public interface CrmContactBusinessLinkConvert {
|
||||
CrmContactBusinessLinkConvert INSTANCE = Mappers.getMapper(CrmContactBusinessLinkConvert.class);
|
||||
CrmContactBusinessLinkDO convert(CrmContactBusinessLinkSaveReqVO bean);
|
||||
List<CrmContactBusinessLinkDO> convert(List<CrmContactBusinessLinkSaveReqVO> bean);
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package cn.iocoder.yudao.module.crm.convert.contract;
|
||||
|
||||
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.contract.vo.*;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
|
@ -43,23 +44,15 @@ public interface CrmContractConvert {
|
|||
|
||||
default PageResult<ContractRespVO> convertPage(PageResult<CrmContractDO> pageResult, Map<Long, AdminUserRespDTO> userMap,
|
||||
List<CrmCustomerDO> customerList) {
|
||||
return new PageResult<>(converList(pageResult.getList(), userMap, customerList), pageResult.getTotal());
|
||||
}
|
||||
|
||||
default List<ContractRespVO> converList(List<CrmContractDO> contractList, Map<Long, AdminUserRespDTO> userMap,
|
||||
List<CrmCustomerDO> customerList) {
|
||||
List<ContractRespVO> result = convertList(contractList);
|
||||
PageResult<ContractRespVO> voPageResult = BeanUtils.toBean(pageResult, ContractRespVO.class);
|
||||
// 拼接关联字段
|
||||
Map<Long, CrmCustomerDO> customerMap = convertMap(customerList, CrmCustomerDO::getId);
|
||||
result.forEach(item -> {
|
||||
setUserInfo(item, userMap);
|
||||
findAndThen(customerMap, item.getCustomerId(), customer -> item.setCustomerName(customer.getName()));
|
||||
voPageResult.getList().forEach(contract -> {
|
||||
findAndThen(userMap, contract.getOwnerUserId(), user -> contract.setOwnerUserName(user.getNickname()));
|
||||
findAndThen(userMap, Long.parseLong(contract.getCreator()), user -> contract.setCreatorName(user.getNickname()));
|
||||
findAndThen(customerMap, contract.getCustomerId(), customer -> contract.setCustomerName(customer.getName()));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
static void setUserInfo(ContractRespVO contract, Map<Long, AdminUserRespDTO> userMap) {
|
||||
findAndThen(userMap, contract.getOwnerUserId(), user -> contract.setOwnerUserName(user.getNickname()));
|
||||
findAndThen(userMap, Long.parseLong(contract.getCreator()), user -> contract.setCreatorName(user.getNickname()));
|
||||
return voPageResult;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
|||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cn.iocoder.yudao.module.crm.convert.receivable;
|
||||
|
||||
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.receivable.vo.receivable.CrmReceivableCreateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableTransferReqVO;
|
||||
|
@ -36,29 +37,19 @@ public interface CrmReceivableConvert {
|
|||
|
||||
CrmReceivableRespVO convert(CrmReceivableDO bean);
|
||||
|
||||
List<CrmReceivableRespVO> convertList(List<CrmReceivableDO> list);
|
||||
|
||||
default PageResult<CrmReceivableRespVO> convertPage(PageResult<CrmReceivableDO> pageResult, Map<Long, AdminUserRespDTO> userMap,
|
||||
List<CrmCustomerDO> customerList, List<CrmContractDO> contractList) {
|
||||
return new PageResult<>(converList(pageResult.getList(), userMap, customerList, contractList), pageResult.getTotal());
|
||||
}
|
||||
|
||||
default List<CrmReceivableRespVO> converList(List<CrmReceivableDO> receivableList, Map<Long, AdminUserRespDTO> userMap,
|
||||
List<CrmCustomerDO> customerList, List<CrmContractDO> contractList) {
|
||||
List<CrmReceivableRespVO> result = convertList(receivableList);
|
||||
PageResult<CrmReceivableRespVO> voPageResult = BeanUtils.toBean(pageResult, CrmReceivableRespVO.class);
|
||||
// 拼接关联字段
|
||||
Map<Long, CrmCustomerDO> customerMap = convertMap(customerList, CrmCustomerDO::getId);
|
||||
Map<Long, CrmContractDO> contractMap = convertMap(contractList, CrmContractDO::getId);
|
||||
result.forEach(item -> {
|
||||
setUserInfo(item, userMap);
|
||||
findAndThen(customerMap, item.getCustomerId(), customer -> item.setCustomerName(customer.getName()));
|
||||
findAndThen(contractMap, item.getContractId(), contract -> item.setContractNo(contract.getNo()));
|
||||
voPageResult.getList().forEach(receivable -> {
|
||||
findAndThen(userMap, receivable.getOwnerUserId(), user -> receivable.setOwnerUserName(user.getNickname()));
|
||||
findAndThen(userMap, Long.parseLong(receivable.getCreator()), user -> receivable.setCreatorName(user.getNickname()));
|
||||
findAndThen(customerMap, receivable.getCustomerId(), customer -> receivable.setCustomerName(customer.getName()));
|
||||
findAndThen(contractMap, receivable.getContractId(), contract -> receivable.setContractNo(contract.getNo()));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
static void setUserInfo(CrmReceivableRespVO receivable, Map<Long, AdminUserRespDTO> userMap) {
|
||||
findAndThen(userMap, receivable.getOwnerUserId(), user -> receivable.setOwnerUserName(user.getNickname()));
|
||||
findAndThen(userMap, Long.parseLong(receivable.getCreator()), user -> receivable.setCreatorName(user.getNickname()));
|
||||
return voPageResult;
|
||||
}
|
||||
|
||||
@Mapping(target = "bizId", source = "reqVO.id")
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cn.iocoder.yudao.module.crm.convert.receivable;
|
||||
|
||||
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.receivable.vo.plan.CrmReceivablePlanCreateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanTransferReqVO;
|
||||
|
@ -37,33 +38,22 @@ public interface CrmReceivablePlanConvert {
|
|||
|
||||
CrmReceivablePlanRespVO convert(CrmReceivablePlanDO bean);
|
||||
|
||||
List<CrmReceivablePlanRespVO> convertList(List<CrmReceivablePlanDO> list);
|
||||
|
||||
default PageResult<CrmReceivablePlanRespVO> convertPage(PageResult<CrmReceivablePlanDO> pageResult, Map<Long, AdminUserRespDTO> userMap,
|
||||
List<CrmCustomerDO> customerList, List<CrmContractDO> contractList,
|
||||
List<CrmReceivableDO> receivableList) {
|
||||
return new PageResult<>(converList(pageResult.getList(), userMap, customerList, contractList, receivableList), pageResult.getTotal());
|
||||
}
|
||||
|
||||
default List<CrmReceivablePlanRespVO> converList(List<CrmReceivablePlanDO> receivablePlanList, Map<Long, AdminUserRespDTO> userMap,
|
||||
List<CrmCustomerDO> customerList, List<CrmContractDO> contractList,
|
||||
List<CrmReceivableDO> receivableList) {
|
||||
List<CrmReceivablePlanRespVO> result = convertList(receivablePlanList);
|
||||
PageResult<CrmReceivablePlanRespVO> voPageResult = BeanUtils.toBean(pageResult, CrmReceivablePlanRespVO.class);
|
||||
// 拼接关联字段
|
||||
Map<Long, CrmCustomerDO> customerMap = convertMap(customerList, CrmCustomerDO::getId);
|
||||
Map<Long, CrmContractDO> contractMap = convertMap(contractList, CrmContractDO::getId);
|
||||
Map<Long, CrmReceivableDO> receivableMap = convertMap(receivableList, CrmReceivableDO::getId);
|
||||
result.forEach(item -> {
|
||||
setUserInfo(item, userMap);
|
||||
findAndThen(customerMap, item.getCustomerId(), customer -> item.setCustomerName(customer.getName()));
|
||||
findAndThen(contractMap, item.getContractId(), contract -> item.setContractNo(contract.getNo()));
|
||||
findAndThen(receivableMap, item.getReceivableId(), receivable -> item.setReturnType(receivable.getReturnType()));
|
||||
voPageResult.getList().forEach(receivablePlan -> {
|
||||
findAndThen(userMap, receivablePlan.getOwnerUserId(), user -> receivablePlan.setOwnerUserName(user.getNickname()));
|
||||
findAndThen(userMap, Long.parseLong(receivablePlan.getCreator()), user -> receivablePlan.setCreatorName(user.getNickname()));
|
||||
findAndThen(customerMap, receivablePlan.getCustomerId(), customer -> receivablePlan.setCustomerName(customer.getName()));
|
||||
findAndThen(contractMap, receivablePlan.getContractId(), contract -> receivablePlan.setContractNo(contract.getNo()));
|
||||
findAndThen(receivableMap, receivablePlan.getReceivableId(), receivable -> receivablePlan.setReturnType(receivable.getReturnType()));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
static void setUserInfo(CrmReceivablePlanRespVO receivablePlan, Map<Long, AdminUserRespDTO> userMap) {
|
||||
findAndThen(userMap, receivablePlan.getOwnerUserId(), user -> receivablePlan.setOwnerUserName(user.getNickname()));
|
||||
findAndThen(userMap, Long.parseLong(receivablePlan.getCreator()), user -> receivablePlan.setCreatorName(user.getNickname()));
|
||||
return voPageResult;
|
||||
}
|
||||
|
||||
@Mapping(target = "bizId", source = "reqVO.id")
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
/**
|
||||
* 商机(销售机会)
|
||||
*/
|
||||
package cn.iocoder.yudao.module.crm.dal.dataobject.business;
|
|
@ -1,28 +1,26 @@
|
|||
package cn.iocoder.yudao.module.crm.dal.dataobject.contactbusinesslink;
|
||||
package cn.iocoder.yudao.module.crm.dal.dataobject.contact;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
// TODO @zyna:可以放到 contact 包下
|
||||
/**
|
||||
* CRM 联系人商机关联 DO
|
||||
* CRM 联系人与商机的关联 DO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("crm_contact_business_link")
|
||||
@KeySequence("crm_contact_business_link_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@TableName("crm_contact_business")
|
||||
@KeySequence("crm_contact_business_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CrmContactBusinessLinkDO extends BaseDO {
|
||||
public class CrmContactBusinessDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 主键
|
|
@ -1,6 +1,7 @@
|
|||
package cn.iocoder.yudao.module.crm.dal.dataobject.contact;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
|
@ -29,9 +30,11 @@ public class CrmContactDO extends BaseDO {
|
|||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 下次联系时间
|
||||
* 客户编号
|
||||
*
|
||||
* 关联 {@link CrmCustomerDO#getId()}
|
||||
*/
|
||||
private LocalDateTime nextTime;
|
||||
private Long customerId;
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
|
@ -45,21 +48,20 @@ public class CrmContactDO extends BaseDO {
|
|||
*/
|
||||
private String email;
|
||||
/**
|
||||
* 客户编号
|
||||
* 所在地
|
||||
*
|
||||
* 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段
|
||||
*/
|
||||
private Long customerId;
|
||||
private Integer areaId;
|
||||
/**
|
||||
* 地址
|
||||
* 详细地址
|
||||
*/
|
||||
private String address;
|
||||
private String detailAddress;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
/**
|
||||
* 最后跟进时间
|
||||
*/
|
||||
private LocalDateTime lastTime;
|
||||
|
||||
/**
|
||||
* 直属上级
|
||||
*
|
||||
|
@ -100,10 +102,13 @@ public class CrmContactDO extends BaseDO {
|
|||
private Long ownerUserId;
|
||||
|
||||
/**
|
||||
* 所在地
|
||||
*
|
||||
* 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段
|
||||
* 最后跟进时间
|
||||
*/
|
||||
private Integer areaId;
|
||||
private LocalDateTime contactLastTime;
|
||||
// TODO @puhui999:增加一个字段 contactLastContent;最后跟进内容
|
||||
/**
|
||||
* 下次联系时间
|
||||
*/
|
||||
private LocalDateTime contactNextTime;
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import java.time.LocalDateTime;
|
|||
// TODO 芋艿:调整下字段
|
||||
|
||||
/**
|
||||
* 客户 DO
|
||||
* CRM 客户 DO
|
||||
*
|
||||
* @author Wanwan
|
||||
*/
|
||||
|
@ -104,17 +104,21 @@ public class CrmCustomerDO extends BaseDO {
|
|||
*/
|
||||
private Long ownerUserId;
|
||||
/**
|
||||
* 地区编号
|
||||
* 所在地
|
||||
*
|
||||
* 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段
|
||||
*/
|
||||
private Integer areaId;
|
||||
/**
|
||||
* 详细地址
|
||||
*/
|
||||
private String detailAddress;
|
||||
|
||||
/**
|
||||
* 最后跟进时间
|
||||
*/
|
||||
private LocalDateTime contactLastTime;
|
||||
// TODO @puhui999:增加一个字段 contactLastContent;最后跟进内容
|
||||
/**
|
||||
* 下次联系时间
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
package cn.iocoder.yudao.module.crm.dal.dataobject.followup;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
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.enums.common.CrmBizTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
// TODO @puhui999:界面:做成一个 list 列表,字段是 id、跟进人、跟进方式、跟进时间、跟进内容、下次联系时间、关联联系人、关联商机
|
||||
// TODO @puhui999:界面:记录时,弹窗,表单字段是跟进方式、跟进内容、下次联系时间、关联联系人、关联商机;其中关联联系人、关联商机,要做成对应的组件列。
|
||||
/**
|
||||
* 跟进记录 DO
|
||||
*
|
||||
* 用于记录客户、联系人的每一次跟进
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName(value = "crm_follow_up_record")
|
||||
@KeySequence("crm_follow_up_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CrmFollowUpRecordDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 数据类型
|
||||
*
|
||||
* 枚举 {@link CrmBizTypeEnum}
|
||||
*/
|
||||
private Integer bizType;
|
||||
/**
|
||||
* 数据编号
|
||||
*
|
||||
* 关联 {@link CrmBizTypeEnum} 对应模块 DO 的 id 字段
|
||||
*/
|
||||
private Long bizId;
|
||||
|
||||
/**
|
||||
* 跟进类型
|
||||
*
|
||||
* TODO @puhui999:可以搞个数据字典,打电话、发短信、上门拜访、微信、邮箱、QQ
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 跟进内容
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 下次联系时间
|
||||
*/
|
||||
private LocalDateTime nextTime;
|
||||
|
||||
/**
|
||||
* 关联的商机编号数组
|
||||
*
|
||||
* 关联 {@link CrmBusinessDO#getId()}
|
||||
*/
|
||||
private List<Long> businessIds;
|
||||
/**
|
||||
* 关联的联系人编号数组
|
||||
*
|
||||
* 关联 {@link CrmContactDO#getId()}
|
||||
*/
|
||||
private List<Long> contactIds;
|
||||
|
||||
}
|
|
@ -30,7 +30,14 @@ public interface CrmBusinessMapper extends BaseMapperX<CrmBusinessDO> {
|
|||
|
||||
default PageResult<CrmBusinessDO> selectPageByCustomerId(CrmBusinessPageReqVO pageReqVO) {
|
||||
return selectPage(pageReqVO, new LambdaQueryWrapperX<CrmBusinessDO>()
|
||||
.eq(CrmBusinessDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号
|
||||
.eq(CrmBusinessDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号
|
||||
.likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName())
|
||||
.orderByDesc(CrmBusinessDO::getId));
|
||||
}
|
||||
|
||||
default PageResult<CrmBusinessDO> selectPageByContactId(CrmBusinessPageReqVO pageReqVO, Collection<Long> businessIds) {
|
||||
return selectPage(pageReqVO, new LambdaQueryWrapperX<CrmBusinessDO>()
|
||||
.in(CrmBusinessDO::getId, businessIds) // 指定商机编号
|
||||
.likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName())
|
||||
.orderByDesc(CrmBusinessDO::getId));
|
||||
}
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
package cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink;
|
||||
|
||||
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.contactbusinesslink.vo.CrmContactBusinessLinkPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contactbusinesslink.CrmContactBusinessLinkDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* CRM 联系人商机关联 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface CrmContactBusinessLinkMapper extends BaseMapperX<CrmContactBusinessLinkDO> {
|
||||
|
||||
default PageResult<CrmContactBusinessLinkDO> selectPage(CrmContactBusinessLinkPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<CrmContactBusinessLinkDO>()
|
||||
.eqIfPresent(CrmContactBusinessLinkDO::getContactId, reqVO.getContactId())
|
||||
.eqIfPresent(CrmContactBusinessLinkDO::getBusinessId, reqVO.getBusinessId())
|
||||
.betweenIfPresent(CrmContactBusinessLinkDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(CrmContactBusinessLinkDO::getId));
|
||||
} // TODO @zyna:方法和方法之间要有空行
|
||||
default PageResult<CrmContactBusinessLinkDO> selectPageByContact(CrmContactBusinessLinkPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<CrmContactBusinessLinkDO>()
|
||||
.eqIfPresent(CrmContactBusinessLinkDO::getContactId, reqVO.getContactId())
|
||||
.orderByDesc(CrmContactBusinessLinkDO::getId));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* CRM 联系人与商机的关联 Mapper
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface CrmContactBusinessMapper extends BaseMapperX<CrmContactBusinessDO> {
|
||||
|
||||
default CrmContactBusinessDO selectByContactIdAndBusinessId(Long contactId, Long businessId) {
|
||||
return selectOne(CrmContactBusinessDO::getContactId, contactId,
|
||||
CrmContactBusinessDO::getBusinessId, businessId);
|
||||
}
|
||||
|
||||
default void deleteByContactIdAndBusinessId(Long contactId, Collection<Long> businessIds) {
|
||||
delete(new LambdaQueryWrapper<CrmContactBusinessDO>()
|
||||
.eq(CrmContactBusinessDO::getContactId, contactId)
|
||||
.in(CrmContactBusinessDO::getBusinessId, businessIds));
|
||||
}
|
||||
|
||||
default List<CrmContactBusinessDO> selectListByContactId(Long contactId) {
|
||||
return selectList(CrmContactBusinessDO::getContactId, contactId);
|
||||
}
|
||||
|
||||
}
|
|
@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmC
|
|||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客户限制配置 Mapper
|
||||
*
|
||||
|
@ -21,4 +23,15 @@ public interface CrmCustomerLimitConfigMapper extends BaseMapperX<CrmCustomerLim
|
|||
.orderByDesc(CrmCustomerLimitConfigDO::getId));
|
||||
}
|
||||
|
||||
default List<CrmCustomerLimitConfigDO> selectListByTypeAndUserIdAndDeptId(
|
||||
Integer type, Long userId, Long deptId) {
|
||||
LambdaQueryWrapperX<CrmCustomerLimitConfigDO> query = new LambdaQueryWrapperX<CrmCustomerLimitConfigDO>()
|
||||
.eq(CrmCustomerLimitConfigDO::getType, type);
|
||||
query.apply("FIND_IN_SET({0}, user_ids) > 0", userId);
|
||||
if (deptId != null) {
|
||||
query.apply("FIND_IN_SET({0}, dept_ids) > 0", deptId);
|
||||
}
|
||||
return selectList(query);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.customer;
|
|||
|
||||
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.framework.mybatis.core.query.MPJLambdaWrapperX;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
|
@ -9,6 +10,7 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
|
|||
import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
@ -21,6 +23,18 @@ import java.util.List;
|
|||
@Mapper
|
||||
public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> {
|
||||
|
||||
default Long selectCountByLockStatusAndOwnerUserId(Boolean lockStatus, Long ownerUserId) {
|
||||
return selectCount(new LambdaUpdateWrapper<CrmCustomerDO>()
|
||||
.eq(CrmCustomerDO::getLockStatus, lockStatus)
|
||||
.eq(CrmCustomerDO::getOwnerUserId, ownerUserId));
|
||||
}
|
||||
|
||||
default Long selectCountByDealStatusAndOwnerUserId(@Nullable Boolean dealStatus, Long ownerUserId) {
|
||||
return selectCount(new LambdaQueryWrapperX<CrmCustomerDO>()
|
||||
.eqIfPresent(CrmCustomerDO::getDealStatus, dealStatus)
|
||||
.eq(CrmCustomerDO::getOwnerUserId, ownerUserId));
|
||||
}
|
||||
|
||||
default int updateOwnerUserIdById(Long id, Long ownerUserId) {
|
||||
return update(new LambdaUpdateWrapper<CrmCustomerDO>()
|
||||
.eq(CrmCustomerDO::getId, id)
|
||||
|
|
|
@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusi
|
|||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessUpdateReqVO;
|
||||
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.customer.CrmCustomerDO;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
|
@ -75,10 +76,20 @@ public interface CrmBusinessService {
|
|||
* 数据权限:基于 {@link CrmCustomerDO} 读取
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 联系人分页
|
||||
* @return 商机分页
|
||||
*/
|
||||
PageResult<CrmBusinessDO> getBusinessPageByCustomerId(CrmBusinessPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 获得商机分页,基于指定联系人
|
||||
*
|
||||
* 数据权限:基于 {@link CrmContactDO} 读取
|
||||
*
|
||||
* @param pageReqVO 分页参数
|
||||
* @return 商机分页
|
||||
*/
|
||||
PageResult<CrmBusinessDO> getBusinessPageByContact(CrmBusinessPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 商机转移
|
||||
*
|
||||
|
|
|
@ -9,11 +9,12 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusi
|
|||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper;
|
||||
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
|
||||
import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission;
|
||||
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
|
||||
import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService;
|
||||
import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
|
||||
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
|
||||
import jakarta.annotation.Resource;
|
||||
|
@ -25,6 +26,7 @@ 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.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
|
@ -38,24 +40,26 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
|||
|
||||
@Resource
|
||||
private CrmBusinessMapper businessMapper;
|
||||
@Resource
|
||||
private CrmCustomerService customerService;
|
||||
|
||||
@Resource
|
||||
private CrmPermissionService crmPermissionService;
|
||||
private CrmPermissionService permissionService;
|
||||
@Resource
|
||||
private CrmContactBusinessService contactBusinessService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
// TODO @商机待定:操作日志;
|
||||
public Long createBusiness(CrmBusinessCreateReqVO createReqVO, Long userId) {
|
||||
// 插入
|
||||
// 1. 插入商机
|
||||
CrmBusinessDO business = CrmBusinessConvert.INSTANCE.convert(createReqVO);
|
||||
businessMapper.insert(business);
|
||||
// TODO 商机待定:插入商机与产品的关联表;校验商品存在
|
||||
|
||||
// 创建数据权限
|
||||
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())
|
||||
// TODO 商机待定:在联系人的详情页,如果直接【新建商机】,则需要关联下。这里要搞个 CrmContactBusinessDO 表
|
||||
|
||||
// 2. 创建数据权限
|
||||
permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())
|
||||
.setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
|
||||
|
||||
// 返回
|
||||
return business.getId();
|
||||
}
|
||||
|
||||
|
@ -63,12 +67,17 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
|||
@Transactional(rollbackFor = Exception.class)
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#updateReqVO.id",
|
||||
level = CrmPermissionLevelEnum.WRITE)
|
||||
// TODO @商机待定:操作日志;
|
||||
public void updateBusiness(CrmBusinessUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
// 1. 校验存在
|
||||
validateBusinessExists(updateReqVO.getId());
|
||||
// 更新
|
||||
|
||||
// 2. 更新商机
|
||||
CrmBusinessDO updateObj = CrmBusinessConvert.INSTANCE.convert(updateReqVO);
|
||||
businessMapper.updateById(updateObj);
|
||||
// TODO 商机待定:插入商机与产品的关联表;校验商品存在
|
||||
|
||||
// TODO @商机待定:如果状态发生变化,插入商机状态变更记录表
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -77,10 +86,12 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
|||
public void deleteBusiness(Long id) {
|
||||
// 校验存在
|
||||
validateBusinessExists(id);
|
||||
// TODO @商机待定:需要校验有没关联合同。CrmContractDO 的 businessId 字段
|
||||
|
||||
// 删除
|
||||
businessMapper.deleteById(id);
|
||||
// 删除数据权限
|
||||
crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_BUSINESS.getType(), id);
|
||||
permissionService.deletePermission(CrmBizTypeEnum.CRM_BUSINESS.getType(), id);
|
||||
}
|
||||
|
||||
private CrmBusinessDO validateBusinessExists(Long id) {
|
||||
|
@ -116,19 +127,32 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
|||
return businessMapper.selectPageByCustomerId(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#pageReqVO.contactId", level = CrmPermissionLevelEnum.READ)
|
||||
public PageResult<CrmBusinessDO> getBusinessPageByContact(CrmBusinessPageReqVO pageReqVO) {
|
||||
// 1. 查询关联的商机编号
|
||||
List<CrmContactBusinessDO> contactBusinessList = contactBusinessService.getContactBusinessListByContactId(
|
||||
pageReqVO.getContactId());
|
||||
if (CollUtil.isEmpty(contactBusinessList)) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
// 2. 查询商机分页
|
||||
return businessMapper.selectPageByContactId(pageReqVO,
|
||||
convertSet(contactBusinessList, CrmContactBusinessDO::getBusinessId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
// TODO @puhui999:操作日志
|
||||
public void transferBusiness(CrmBusinessTransferReqVO reqVO, Long userId) {
|
||||
// 1 校验商机是否存在
|
||||
validateBusinessExists(reqVO.getId());
|
||||
|
||||
// 2.1 数据权限转移
|
||||
crmPermissionService.transferPermission(
|
||||
permissionService.transferPermission(
|
||||
CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()));
|
||||
// 2.2 设置新的负责人
|
||||
businessMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
|
||||
|
||||
// 3. TODO 记录转移日志
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusine
|
|||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -64,4 +66,12 @@ public interface CrmBusinessStatusService {
|
|||
*/
|
||||
List<CrmBusinessStatusDO> selectList(CrmBusinessStatusQueryVO queryVO);
|
||||
|
||||
/**
|
||||
* 获得商机状态列表
|
||||
*
|
||||
* @param ids 编号数组
|
||||
* @return 商机状态列表
|
||||
*/
|
||||
List<CrmBusinessStatusDO> getBusinessStatusList(Collection<Long> ids);
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.springframework.validation.annotation.Validated;
|
|||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
|
@ -77,4 +78,9 @@ public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService {
|
|||
return businessStatusMapper.selectList(queryVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmBusinessStatusDO> getBusinessStatusList(Collection<Long> ids) {
|
||||
return businessStatusMapper.selectBatchIds(ids);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,8 +5,9 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusiness
|
|||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeSaveReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -63,4 +64,12 @@ public interface CrmBusinessStatusTypeService {
|
|||
*/
|
||||
List<CrmBusinessStatusTypeDO> selectList(CrmBusinessStatusTypeQueryVO queryVO);
|
||||
|
||||
/**
|
||||
* 获得商机状态类型列表
|
||||
*
|
||||
* @param ids 编号数组
|
||||
* @return 商机状态类型列表
|
||||
*/
|
||||
List<CrmBusinessStatusTypeDO> getBusinessStatusTypeList(Collection<Long> ids);
|
||||
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
|
@ -118,4 +120,9 @@ public class CrmBusinessStatusTypeServiceImpl implements CrmBusinessStatusTypeSe
|
|||
return businessStatusTypeMapper.selectList(queryVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmBusinessStatusTypeDO> getBusinessStatusTypeList(Collection<Long> ids) {
|
||||
return businessStatusTypeMapper.selectBatchIds(ids);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
/**
|
||||
* 商机(销售机会)
|
||||
*/
|
||||
package cn.iocoder.yudao.module.crm.service.business;
|
|
@ -1,4 +0,0 @@
|
|||
/**
|
||||
* 线索
|
||||
*/
|
||||
package cn.iocoder.yudao.module.crm.service.clue;
|
|
@ -0,0 +1,38 @@
|
|||
package cn.iocoder.yudao.module.crm.service.contact;
|
||||
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* CRM 联系人与商机的关联 Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface CrmContactBusinessService {
|
||||
|
||||
/**
|
||||
* 创建联系人与商机的关联
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
*/
|
||||
void createContactBusinessList(@Valid CrmContactBusinessReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 删除联系人与商机的关联
|
||||
*
|
||||
* @param deleteReqVO 删除信息
|
||||
*/
|
||||
void deleteContactBusinessList(@Valid CrmContactBusinessReqVO deleteReqVO);
|
||||
|
||||
/**
|
||||
* 获得联系人与商机的关联列表,基于联系人编号
|
||||
*
|
||||
* @param contactId 联系人编号
|
||||
* @return 联系人商机关联
|
||||
*/
|
||||
List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId);
|
||||
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package cn.iocoder.yudao.module.crm.service.contact;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessMapper;
|
||||
import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTACT_NOT_EXISTS;
|
||||
|
||||
// TODO @puhui999:数据权限的校验;每个操作;
|
||||
/**
|
||||
* 联系人与商机的关联 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class CrmContactBusinessServiceImpl implements CrmContactBusinessService {
|
||||
|
||||
@Resource
|
||||
private CrmContactBusinessMapper contactBusinessMapper;
|
||||
|
||||
@Resource
|
||||
@Lazy // 延迟加载,为了解决延迟加载
|
||||
private CrmBusinessService businessService;
|
||||
@Resource
|
||||
@Lazy // 延迟加载,为了解决延迟加载
|
||||
private CrmContactService contactService;
|
||||
|
||||
@Override
|
||||
public void createContactBusinessList(CrmContactBusinessReqVO createReqVO) {
|
||||
CrmContactDO contact = contactService.getContact(createReqVO.getContactId());
|
||||
if (contact == null) {
|
||||
throw exception(CONTACT_NOT_EXISTS);
|
||||
}
|
||||
// 遍历处理,考虑到一般数量不会太多,代码处理简单
|
||||
List<CrmContactBusinessDO> saveDOList = new ArrayList<>();
|
||||
createReqVO.getBusinessIds().forEach(businessId -> {
|
||||
CrmBusinessDO business = businessService.getBusiness(businessId);
|
||||
if (business == null) {
|
||||
throw exception(BUSINESS_NOT_EXISTS);
|
||||
}
|
||||
// 关联判重
|
||||
if (contactBusinessMapper.selectByContactIdAndBusinessId(createReqVO.getContactId(), businessId) != null) {
|
||||
return;
|
||||
}
|
||||
saveDOList.add(new CrmContactBusinessDO(null, createReqVO.getContactId(), businessId));
|
||||
});
|
||||
// 批量插入
|
||||
if (CollUtil.isNotEmpty(saveDOList)) {
|
||||
contactBusinessMapper.insertBatch(saveDOList);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteContactBusinessList(CrmContactBusinessReqVO deleteReqVO) {
|
||||
CrmContactDO contact = contactService.getContact(deleteReqVO.getContactId());
|
||||
if (contact == null) {
|
||||
throw exception(CONTACT_NOT_EXISTS);
|
||||
}
|
||||
// 直接删除
|
||||
contactBusinessMapper.deleteByContactIdAndBusinessId(
|
||||
deleteReqVO.getContactId(), deleteReqVO.getBusinessIds());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId) {
|
||||
return contactBusinessMapper.selectListByContactId(contactId);
|
||||
}
|
||||
|
||||
}
|
|
@ -43,33 +43,38 @@ public class CrmContactServiceImpl implements CrmContactService {
|
|||
private CrmCustomerService customerService;
|
||||
@Resource
|
||||
private CrmPermissionService crmPermissionService;
|
||||
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
// TODO @zyna:增加操作日志,可以参考 CustomerService;内容是 新建了联系人【名字】
|
||||
public Long createContact(CrmContactCreateReqVO createReqVO, Long userId) {
|
||||
// 1.1 校验
|
||||
// 1. 校验
|
||||
validateRelationDataExists(createReqVO);
|
||||
// 1.2 插入
|
||||
|
||||
// 2. 插入联系人
|
||||
CrmContactDO contact = CrmContactConvert.INSTANCE.convert(createReqVO);
|
||||
contactMapper.insert(contact);
|
||||
|
||||
// 2. 创建数据权限
|
||||
// 3. 创建数据权限
|
||||
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
|
||||
.setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()).setBizId(contact.getId())
|
||||
.setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
|
||||
|
||||
// TODO @zyna:特殊逻辑:如果在【商机】详情那,点击【新增联系人】时,可以自动绑定商机
|
||||
return contact.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
|
||||
// TODO @zyna:增加操作日志,可以参考 CustomerService;需要 diff 出字段
|
||||
public void updateContact(CrmContactUpdateReqVO updateReqVO) {
|
||||
// 1. 校验存在
|
||||
validateContactExists(updateReqVO.getId());
|
||||
validateRelationDataExists(updateReqVO);
|
||||
// 2. 更新
|
||||
|
||||
// 2. 更新联系人
|
||||
CrmContactDO updateObj = CrmContactConvert.INSTANCE.convert(updateReqVO);
|
||||
contactMapper.updateById(updateObj);
|
||||
}
|
||||
|
@ -99,10 +104,15 @@ public class CrmContactServiceImpl implements CrmContactService {
|
|||
public void deleteContact(Long id) {
|
||||
// 校验存在
|
||||
validateContactExists(id);
|
||||
// TODO @zyna:如果有关联的合同,不允许删除;Contract.contactId
|
||||
|
||||
// 删除
|
||||
contactMapper.deleteById(id);
|
||||
// 删除数据权限
|
||||
crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CONTACT.getType(), id);
|
||||
// TODO @zyna:删除商机联系人关联
|
||||
|
||||
// TODO @puhui999:删除跟进记录
|
||||
}
|
||||
|
||||
private void validateContactExists(Long id) {
|
||||
|
@ -137,6 +147,8 @@ public class CrmContactServiceImpl implements CrmContactService {
|
|||
}
|
||||
|
||||
@Override
|
||||
// TODO @puhui999:权限校验
|
||||
// TODO @puhui999:记录操作日志;将联系人【名字】转移给【新负责人】
|
||||
public void transferContact(CrmContactTransferReqVO reqVO, Long userId) {
|
||||
// 1 校验联系人是否存在
|
||||
validateContactExists(reqVO.getId());
|
||||
|
@ -150,4 +162,4 @@ public class CrmContactServiceImpl implements CrmContactService {
|
|||
// 3. TODO 记录转移日志
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
package cn.iocoder.yudao.module.crm.service.contactbusinesslink;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkSaveReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contactbusinesslink.CrmContactBusinessLinkDO;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* CRM 联系人商机关联 Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface CrmContactBusinessLinkService {
|
||||
|
||||
/**
|
||||
* 创建联系人商机关联
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createContactBusinessLink(@Valid CrmContactBusinessLinkSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 创建联系人商机关联
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
*/
|
||||
void createContactBusinessLinkBatch(@Valid List<CrmContactBusinessLinkSaveReqVO> createReqVO);
|
||||
|
||||
/**
|
||||
* 更新联系人商机关联
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateContactBusinessLink(@Valid CrmContactBusinessLinkSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除联系人商机关联
|
||||
*
|
||||
* @param createReqVO 删除列表
|
||||
*/
|
||||
void deleteContactBusinessLink(@Valid List<CrmContactBusinessLinkSaveReqVO> createReqVO);
|
||||
|
||||
/**
|
||||
* 获得联系人商机关联
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 联系人商机关联
|
||||
*/
|
||||
CrmContactBusinessLinkDO getContactBusinessLink(Long id);
|
||||
|
||||
/**
|
||||
* 获得联系人商机关联分页
|
||||
*
|
||||
* @param pageReqVO 编号
|
||||
* @return 联系人商机关联
|
||||
*/
|
||||
PageResult<CrmBusinessRespVO> getContactBusinessLinkPageByContact(CrmContactBusinessLinkPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 获得联系人商机关联分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 联系人商机关联分页
|
||||
*/
|
||||
PageResult<CrmContactBusinessLinkDO> getContactBusinessLinkPage(CrmContactBusinessLinkPageReqVO pageReqVO);
|
||||
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
package cn.iocoder.yudao.module.crm.service.contactbusinesslink;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkSaveReqVO;
|
||||
import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert;
|
||||
import cn.iocoder.yudao.module.crm.convert.contactbusinessslink.CrmContactBusinessLinkConvert;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contactbusinesslink.CrmContactBusinessLinkDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessLinkMapper;
|
||||
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
|
||||
import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission;
|
||||
import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTACT_BUSINESS_LINK_NOT_EXISTS;
|
||||
|
||||
// TODO @puhui999:数据权限的校验;每个操作;
|
||||
/**
|
||||
* 联系人商机关联 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class CrmContactBusinessLinkServiceImpl implements CrmContactBusinessLinkService {
|
||||
|
||||
@Resource
|
||||
private CrmContactBusinessLinkMapper contactBusinessLinkMapper;
|
||||
@Resource
|
||||
private CrmBusinessService crmBusinessService;
|
||||
|
||||
@Override
|
||||
public Long createContactBusinessLink(CrmContactBusinessLinkSaveReqVO createReqVO) {
|
||||
CrmContactBusinessLinkDO contactBusinessLink = BeanUtils.toBean(createReqVO, CrmContactBusinessLinkDO.class);
|
||||
contactBusinessLinkMapper.insert(contactBusinessLink);
|
||||
return contactBusinessLink.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createContactBusinessLinkBatch(List<CrmContactBusinessLinkSaveReqVO> createReqVOList) {
|
||||
// 插入
|
||||
// TODO @zyna:如果已经关联过,不用重复插入;
|
||||
// TODO @zyna:contact 和 business 存在校验,挪到这里,Controller 不用 @Transactional 注解,添加到这里哈。尽量业务都在 Service;
|
||||
List<CrmContactBusinessLinkDO> saveDoList = CrmContactBusinessLinkConvert.INSTANCE.convert(createReqVOList);
|
||||
contactBusinessLinkMapper.insertBatch(saveDoList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
|
||||
public void updateContactBusinessLink(CrmContactBusinessLinkSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateContactBusinessLinkExists(updateReqVO.getId());
|
||||
// 更新
|
||||
CrmContactBusinessLinkDO updateObj = BeanUtils.toBean(updateReqVO, CrmContactBusinessLinkDO.class);
|
||||
contactBusinessLinkMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteContactBusinessLink(List<CrmContactBusinessLinkSaveReqVO> createReqVO) {
|
||||
// 删除
|
||||
createReqVO.forEach(item -> {
|
||||
contactBusinessLinkMapper.delete(new LambdaQueryWrapperX<CrmContactBusinessLinkDO>()
|
||||
.eq(CrmContactBusinessLinkDO::getBusinessId,item.getBusinessId())
|
||||
.eq(CrmContactBusinessLinkDO::getContactId,item.getContactId())
|
||||
.eq(CrmContactBusinessLinkDO::getDeleted,0));
|
||||
});
|
||||
}
|
||||
|
||||
private void validateContactBusinessLinkExists(Long id) {
|
||||
if (contactBusinessLinkMapper.selectById(id) == null) {
|
||||
throw exception(CONTACT_BUSINESS_LINK_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.READ)
|
||||
public CrmContactBusinessLinkDO getContactBusinessLink(Long id) {
|
||||
return contactBusinessLinkMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<CrmBusinessRespVO> getContactBusinessLinkPageByContact(CrmContactBusinessLinkPageReqVO pageReqVO) {
|
||||
CrmContactBusinessLinkPageReqVO crmContactBusinessLinkPageReqVO = new CrmContactBusinessLinkPageReqVO();
|
||||
crmContactBusinessLinkPageReqVO.setContactId(pageReqVO.getContactId());
|
||||
PageResult<CrmContactBusinessLinkDO> businessLinkDOS = contactBusinessLinkMapper.selectPageByContact(crmContactBusinessLinkPageReqVO);
|
||||
List<CrmBusinessDO> businessDOS = crmBusinessService.getBusinessList(CollectionUtils.convertList(businessLinkDOS.getList(),
|
||||
CrmContactBusinessLinkDO::getBusinessId), getLoginUserId());
|
||||
PageResult<CrmBusinessRespVO> pageResult = new PageResult<CrmBusinessRespVO>();
|
||||
pageResult.setList(CrmBusinessConvert.INSTANCE.convert(businessDOS));
|
||||
pageResult.setTotal(businessLinkDOS.getTotal());
|
||||
return pageResult;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<CrmContactBusinessLinkDO> getContactBusinessLinkPage(CrmContactBusinessLinkPageReqVO pageReqVO) {
|
||||
return contactBusinessLinkMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
}
|
|
@ -42,8 +42,10 @@ public class CrmContractServiceImpl implements CrmContractService {
|
|||
private CrmPermissionService crmPermissionService;
|
||||
|
||||
@Override
|
||||
// TODO @puhui999:添加操作日志
|
||||
public Long createContract(CrmContractCreateReqVO createReqVO, Long userId) {
|
||||
// 插入
|
||||
// TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO
|
||||
// 插入合同
|
||||
CrmContractDO contract = CrmContractConvert.INSTANCE.convert(createReqVO);
|
||||
contractMapper.insert(contract);
|
||||
|
||||
|
@ -57,18 +59,26 @@ public class CrmContractServiceImpl implements CrmContractService {
|
|||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
|
||||
// TODO @puhui999:添加操作日志
|
||||
public void updateContract(CrmContractUpdateReqVO updateReqVO) {
|
||||
// TODO @合同待定:只有草稿、审批中,可以编辑;
|
||||
// 校验存在
|
||||
validateContractExists(updateReqVO.getId());
|
||||
// 更新
|
||||
// 更新合同
|
||||
CrmContractDO updateObj = CrmContractConvert.INSTANCE.convert(updateReqVO);
|
||||
contractMapper.updateById(updateObj);
|
||||
// TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO
|
||||
}
|
||||
|
||||
// TODO @合同待定:缺一个取消合同的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum
|
||||
|
||||
// TODO @合同待定:缺一个发起审批的接口;只有草稿可以发起审批;CrmAuditStatusEnum
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
|
||||
public void deleteContract(Long id) {
|
||||
// TODO @合同待定:如果被 CrmReceivableDO 所使用,则不允许删除
|
||||
// 校验存在
|
||||
validateContractExists(id);
|
||||
// 删除
|
||||
|
@ -112,6 +122,8 @@ public class CrmContractServiceImpl implements CrmContractService {
|
|||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
// 3. TODO @puhui999:记录转移日志
|
||||
// TODO @puhui999:权限校验,这里要搞哇?
|
||||
public void transferContract(CrmContractTransferReqVO reqVO, Long userId) {
|
||||
// 1. 校验合同是否存在
|
||||
validateContractExists(reqVO.getId());
|
||||
|
@ -121,9 +133,7 @@ public class CrmContractServiceImpl implements CrmContractService {
|
|||
CrmContractConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()));
|
||||
// 2.2 设置负责人
|
||||
contractMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
|
||||
|
||||
// 3. TODO 记录转移日志
|
||||
|
||||
}
|
||||
|
||||
// TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒;
|
||||
}
|
||||
|
|
|
@ -5,9 +5,10 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmC
|
|||
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客户限制配置 Service 接口
|
||||
*
|
||||
|
@ -53,4 +54,12 @@ public interface CrmCustomerLimitConfigService {
|
|||
*/
|
||||
PageResult<CrmCustomerLimitConfigDO> getCustomerLimitConfigPage(CrmCustomerLimitConfigPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 查询用户对应的配置列表
|
||||
*
|
||||
* @param type 类型
|
||||
* @param userId 用户类型
|
||||
*/
|
||||
List<CrmCustomerLimitConfigDO> getCustomerLimitConfigListByUserId(Integer type, Long userId);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cn.iocoder.yudao.module.crm.service.customer;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO;
|
||||
|
@ -9,12 +10,14 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfi
|
|||
import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerLimitConfigMapper;
|
||||
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_LIMIT_CONFIG_NOT_EXISTS;
|
||||
|
@ -30,12 +33,14 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig
|
|||
|
||||
@Resource
|
||||
private CrmCustomerLimitConfigMapper customerLimitConfigMapper;
|
||||
|
||||
@Resource
|
||||
private DeptApi deptApi;
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
|
||||
@Override
|
||||
// TODO @puhui999:操作日志
|
||||
public Long createCustomerLimitConfig(CrmCustomerLimitConfigCreateReqVO createReqVO) {
|
||||
validateUserAndDept(createReqVO.getUserIds(), createReqVO.getDeptIds());
|
||||
// 插入
|
||||
|
@ -46,6 +51,7 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig
|
|||
}
|
||||
|
||||
@Override
|
||||
// TODO @puhui999:操作日志
|
||||
public void updateCustomerLimitConfig(CrmCustomerLimitConfigUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateCustomerLimitConfigExists(updateReqVO.getId());
|
||||
|
@ -56,6 +62,7 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig
|
|||
}
|
||||
|
||||
@Override
|
||||
// TODO @puhui999:操作日志
|
||||
public void deleteCustomerLimitConfig(Long id) {
|
||||
// 校验存在
|
||||
validateCustomerLimitConfigExists(id);
|
||||
|
@ -90,4 +97,11 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig
|
|||
adminUserApi.validateUserList(userIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmCustomerLimitConfigDO> getCustomerLimitConfigListByUserId(Integer type, Long userId) {
|
||||
AdminUserRespDTO user = adminUserApi.getUser(userId);
|
||||
Assert.notNull(user, "用户({})不存在", userId);
|
||||
return customerLimitConfigMapper.selectListByTypeAndUserIdAndDeptId(type, userId, user.getDeptId());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ public class CrmCustomerPoolConfigServiceImpl implements CrmCustomerPoolConfigSe
|
|||
* @param saveReqVO 更新信息
|
||||
*/
|
||||
@Override
|
||||
// TODO @puhui999:操作日志
|
||||
public void saveCustomerPoolConfig(CrmCustomerPoolConfigSaveReqVO saveReqVO) {
|
||||
// 存在,则进行更新
|
||||
CrmCustomerPoolConfigDO dbConfig = getCustomerPoolConfig();
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
package cn.iocoder.yudao.module.crm.service.customer;
|
||||
|
||||
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.CrmCustomerPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
|
@ -56,7 +53,7 @@ public interface CrmCustomerService {
|
|||
* @return 客户列表
|
||||
* @author ljlleo
|
||||
*/
|
||||
List<CrmCustomerDO> getCustomerList(Collection<Long> ids, Long userId);
|
||||
List<CrmCustomerDO> getCustomerList(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得客户分页
|
||||
|
@ -85,9 +82,10 @@ public interface CrmCustomerService {
|
|||
/**
|
||||
* 锁定/解锁客户
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
* @param lockReqVO 更新信息
|
||||
* @param userId 用户编号
|
||||
*/
|
||||
void lockCustomer(@Valid CrmCustomerUpdateReqVO updateReqVO);
|
||||
void lockCustomer(@Valid CrmCustomerLockReqVO lockReqVO, Long userId);
|
||||
|
||||
// ==================== 公海相关操作 ====================
|
||||
|
||||
|
|
|
@ -2,13 +2,12 @@ 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.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
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.CrmCustomerTransferReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
|
||||
import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper;
|
||||
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
|
||||
|
@ -24,12 +23,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.*;
|
||||
|
||||
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.LogRecordConstants.CRM_CUSTOMER;
|
||||
import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.TRANSFER_CUSTOMER_LOG_SUCCESS;
|
||||
import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_LOCK_LIMIT;
|
||||
import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_OWNER_LIMIT;
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
/**
|
||||
|
@ -45,24 +47,32 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
|||
private CrmCustomerMapper customerMapper;
|
||||
|
||||
@Resource
|
||||
private CrmPermissionService crmPermissionService;
|
||||
private CrmPermissionService permissionService;
|
||||
@Resource
|
||||
private CrmCustomerLimitConfigService customerLimitConfigService;
|
||||
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@LogRecord(type = CRM_CUSTOMER, subType = "创建客户", bizNo = "{{#customerId}}", success = "创建了客户")
|
||||
@LogRecord(type = CRM_CUSTOMER, subType = "创建客户", bizNo = "{{#customerId}}", success = "创建了客户") // TODO @puhui999:创建了客户【客户名】,要记录进去;不然在展示操作日志的全列表,看不清楚是哪个客户哈;
|
||||
public Long createCustomer(CrmCustomerCreateReqVO createReqVO, Long userId) {
|
||||
// 插入
|
||||
CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO);
|
||||
// 1. 校验拥有客户是否到达上限
|
||||
validateCustomerExceedOwnerLimit(createReqVO.getOwnerUserId(), 1);
|
||||
|
||||
// 2. 插入客户
|
||||
CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO)
|
||||
.setLockStatus(false).setDealStatus(false)
|
||||
.setContactLastTime(LocalDateTime.now());
|
||||
// TODO @puhui999:可能要加个 receiveTime 字段,记录最后接收时间
|
||||
customerMapper.insert(customer);
|
||||
|
||||
// 创建数据权限
|
||||
crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())
|
||||
// 3. 创建数据权限
|
||||
permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())
|
||||
.setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
|
||||
|
||||
// 记录操作日志
|
||||
// 4. 记录操作日志
|
||||
LogRecordContext.putVariable("customerId", customer.getId());
|
||||
return customer.getId();
|
||||
}
|
||||
|
@ -72,14 +82,15 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
|||
@LogRecord(type = CRM_CUSTOMER, subType = "更新客户", bizNo = "{{#updateReqVO.id}}", success = "更新了客户{_DIFF{#updateReqVO}}", extra = "{{#extra}}")
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
|
||||
public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
// TODO @puhui999:更新的时候,要把 updateReqVO 负责人设置为空,避免修改。
|
||||
// 1. 校验存在
|
||||
CrmCustomerDO oldCustomer = validateCustomerExists(updateReqVO.getId());
|
||||
|
||||
// 更新
|
||||
// 2. 更新客户
|
||||
CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO);
|
||||
customerMapper.updateById(updateObj);
|
||||
|
||||
// 记录操作日志
|
||||
// 3. 记录操作日志
|
||||
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomer, CrmCustomerUpdateReqVO.class));
|
||||
// TODO 扩展信息测试 @puhui999:看着没啥问题,可以删除啦;
|
||||
HashMap<String, Object> extra = new HashMap<>();
|
||||
|
@ -94,11 +105,13 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
|||
public void deleteCustomer(Long id) {
|
||||
// 校验存在
|
||||
validateCustomerExists(id);
|
||||
// TODO @puhui999:如果有联系人、商机,则不允许删除;
|
||||
|
||||
// 删除
|
||||
customerMapper.deleteById(id);
|
||||
// 删除数据权限
|
||||
crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id);
|
||||
permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id);
|
||||
// TODO @puhui999:删除跟进记录
|
||||
}
|
||||
|
||||
private CrmCustomerDO validateCustomerExists(Long id) {
|
||||
|
@ -116,11 +129,11 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<CrmCustomerDO> getCustomerList(Collection<Long> ids, Long userId) {
|
||||
public List<CrmCustomerDO> getCustomerList(Collection<Long> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return customerMapper.selectBatchIds(ids, userId);
|
||||
return customerMapper.selectBatchIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -140,38 +153,91 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
|||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@LogRecord(type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS)
|
||||
@LogRecord(type = CRM_CUSTOMER, subType = "转移客户", bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS)
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER)
|
||||
public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) {
|
||||
// 1. 校验客户是否存在
|
||||
CrmCustomerDO customerDO = validateCustomerExists(reqVO.getId());
|
||||
// 1.1 校验客户是否存在
|
||||
CrmCustomerDO customer = validateCustomerExists(reqVO.getId());
|
||||
// 1.2 校验拥有客户是否到达上限
|
||||
validateCustomerExceedOwnerLimit(reqVO.getNewOwnerUserId(), 1);
|
||||
|
||||
// 2.1 数据权限转移
|
||||
crmPermissionService.transferPermission(
|
||||
permissionService.transferPermission(
|
||||
CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()));
|
||||
// 2.2 转移后重新设置负责人
|
||||
customerMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
|
||||
|
||||
// 3. TODO 记录转移日志
|
||||
LogRecordContext.putVariable("crmCustomer", customerDO);
|
||||
LogRecordContext.putVariable("crmCustomer", customer);
|
||||
}
|
||||
|
||||
@Override
|
||||
// TODO @puhui999:看看这个能不能根据条件,写操作日志;
|
||||
// TODO 如果是 锁定,则 subType 为 锁定客户;success 为 将客户【】锁定
|
||||
// TODO 如果是 解锁,则 subType 为 解锁客户;success 为 将客户【】解锁
|
||||
@LogRecord(type = CRM_CUSTOMER, subType = "锁定/解锁客户", bizNo = "{{#updateReqVO.id}}", success = "锁定了客户")
|
||||
public void lockCustomer(CrmCustomerUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateCustomerExists(updateReqVO.getId());
|
||||
// TODO @Joey:可以校验下,如果已经对应的锁定状态,报个业务异常;原因是:后续这个业务会记录操作日志,会记录多了;
|
||||
// TODO @芋艿:业务完善,增加锁定上限;
|
||||
// TODO @puhui999:数据权限
|
||||
public void lockCustomer(CrmCustomerLockReqVO lockReqVO, Long userId) {
|
||||
// 1.1 校验当前客户是否存在
|
||||
validateCustomerExists(lockReqVO.getId());
|
||||
// 1.2 校验当前是否重复操作锁定/解锁状态
|
||||
CrmCustomerDO customer = customerMapper.selectById(lockReqVO.getId());
|
||||
if (customer.getLockStatus().equals(lockReqVO.getLockStatus())) {
|
||||
throw exception(customer.getLockStatus() ? CUSTOMER_LOCK_FAIL_IS_LOCK : CUSTOMER_UNLOCK_FAIL_IS_UNLOCK);
|
||||
}
|
||||
// 1.3 校验锁定上限。
|
||||
if (lockReqVO.getLockStatus()) {
|
||||
validateCustomerExceedLockLimit(userId);
|
||||
}
|
||||
|
||||
// 更新
|
||||
CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO);
|
||||
customerMapper.updateById(updateObj);
|
||||
// 2. 更新锁定状态
|
||||
customerMapper.updateById(BeanUtils.toBean(lockReqVO, CrmCustomerDO.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验用户拥有的客户数量,是否到达上限
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param newCount 附加数量
|
||||
*/
|
||||
private void validateCustomerExceedOwnerLimit(Long userId, int newCount) {
|
||||
List<CrmCustomerLimitConfigDO> limitConfigs = customerLimitConfigService.getCustomerLimitConfigListByUserId(
|
||||
CUSTOMER_OWNER_LIMIT.getType(), userId);
|
||||
if (CollUtil.isEmpty(limitConfigs)) {
|
||||
return;
|
||||
}
|
||||
Long ownerCount = customerMapper.selectCountByDealStatusAndOwnerUserId(null, userId);
|
||||
Long dealOwnerCount = customerMapper.selectCountByDealStatusAndOwnerUserId(true, userId);
|
||||
limitConfigs.forEach(limitConfig -> {
|
||||
long nowCount = limitConfig.getDealCountEnabled() ? ownerCount : ownerCount - dealOwnerCount;
|
||||
if (nowCount + newCount > limitConfig.getMaxCount()) {
|
||||
throw exception(CUSTOMER_OWNER_EXCEED_LIMIT);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验用户锁定的客户数量,是否到达上限
|
||||
*
|
||||
* @param userId 用户编号
|
||||
*/
|
||||
private void validateCustomerExceedLockLimit(Long userId) {
|
||||
List<CrmCustomerLimitConfigDO> limitConfigs = customerLimitConfigService.getCustomerLimitConfigListByUserId(
|
||||
CUSTOMER_LOCK_LIMIT.getType(), userId);
|
||||
if (CollUtil.isEmpty(limitConfigs)) {
|
||||
return;
|
||||
}
|
||||
Long lockCount = customerMapper.selectCountByLockStatusAndOwnerUserId(true, userId);
|
||||
Integer maxCount = CollectionUtils.getMaxValue(limitConfigs, CrmCustomerLimitConfigDO::getMaxCount);
|
||||
assert maxCount != null;
|
||||
if (lockCount >= maxCount) {
|
||||
throw exception(CUSTOMER_LOCK_EXCEED_LIMIT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@LogRecord(type = CRM_CUSTOMER, subType = "客户放入公海", bizNo = "{{#id}}", success = "将客户放入了公海")
|
||||
@LogRecord(type = CRM_CUSTOMER, subType = "客户放入公海", bizNo = "{{#id}}", success = "将客户放入了公海") // TODO @puhui999:将客户【】放入了公海
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
|
||||
public void putCustomerPool(Long id) {
|
||||
// 1. 校验存在
|
||||
|
@ -190,12 +256,18 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
|||
throw exception(CUSTOMER_UPDATE_OWNER_USER_FAIL);
|
||||
}
|
||||
// 3. 删除负责人数据权限
|
||||
crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), customer.getId(),
|
||||
permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), customer.getId(),
|
||||
CrmPermissionLevelEnum.OWNER.getLevel());
|
||||
// TODO @puhui999:联系人的负责人,也要设置为 null;这块和领取是对应的;因为领取后,负责人也要关联过来;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
// TODO @puhui999:权限校验
|
||||
|
||||
// TODO @puhui999:如果是分配,操作日志是 “将客户【】分配给【】”
|
||||
// TODO @puhui999:如果是领取,操作日志是“领取客户【】”;
|
||||
// TODO @puhui999:如果是多条,则需要记录多条操作日志;不然 bizId 不好关联
|
||||
public void receiveCustomer(List<Long> ids, Long ownerUserId) {
|
||||
// 1.1 校验存在
|
||||
List<CrmCustomerDO> customers = customerMapper.selectBatchIds(ids);
|
||||
|
@ -213,8 +285,10 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
|||
// 校验成交状态
|
||||
validateCustomerDeal(customer);
|
||||
});
|
||||
// 1.4 校验负责人是否到达上限
|
||||
validateCustomerExceedOwnerLimit(ownerUserId, customers.size());
|
||||
|
||||
// 2. 领取公海数据
|
||||
// 2.1 领取公海数据
|
||||
List<CrmCustomerDO> updateCustomers = new ArrayList<>();
|
||||
List<CrmPermissionCreateReqBO> createPermissions = new ArrayList<>();
|
||||
customers.forEach(customer -> {
|
||||
|
@ -224,11 +298,11 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
|
|||
createPermissions.add(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())
|
||||
.setBizId(customer.getId()).setUserId(ownerUserId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
|
||||
});
|
||||
|
||||
// 3.1 更新客户负责人
|
||||
// 2.2 更新客户负责人
|
||||
customerMapper.updateBatch(updateCustomers);
|
||||
// 3.2 创建负责人数据权限
|
||||
crmPermissionService.createPermissionBatch(createPermissions);
|
||||
// 2.3 创建负责人数据权限
|
||||
permissionService.createPermissionBatch(createPermissions);
|
||||
// TODO @芋艿:要不要处理关联的联系人???
|
||||
}
|
||||
|
||||
private void validateCustomerOwnerExists(CrmCustomerDO customer, Boolean pool) {
|
||||
|
|
|
@ -35,18 +35,20 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService
|
|||
private CrmProductService crmProductService;
|
||||
|
||||
@Override
|
||||
// TODO @puhui999:操作日志
|
||||
public Long createProductCategory(CrmProductCategoryCreateReqVO createReqVO) {
|
||||
// 1.1 校验父分类存在
|
||||
validateParentProductCategory(createReqVO.getParentId());
|
||||
// 1.2 分类名称是否存在
|
||||
validateProductNameExists(null, createReqVO.getParentId(), createReqVO.getName());
|
||||
// 2. 插入
|
||||
// 2. 插入分类
|
||||
CrmProductCategoryDO category = BeanUtils.toBean(createReqVO, CrmProductCategoryDO.class);
|
||||
productCategoryMapper.insert(category);
|
||||
return category.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
// TODO @puhui999:操作日志
|
||||
public void updateProductCategory(CrmProductCategoryCreateReqVO updateReqVO) {
|
||||
// 1.1 校验存在
|
||||
validateProductCategoryExists(updateReqVO.getId());
|
||||
|
@ -54,7 +56,7 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService
|
|||
validateParentProductCategory(updateReqVO.getParentId());
|
||||
// 1.3 分类名称是否存在
|
||||
validateProductNameExists(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());
|
||||
// 2. 更新
|
||||
// 2. 更新分类
|
||||
CrmProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, CrmProductCategoryDO.class);
|
||||
productCategoryMapper.updateById(updateObj);
|
||||
}
|
||||
|
@ -91,19 +93,19 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService
|
|||
}
|
||||
|
||||
@Override
|
||||
// TODO @puhui999:操作日志
|
||||
public void deleteProductCategory(Long id) {
|
||||
// TODO zange:参考 mall: ProductCategoryServiceImpl 补充下必要的参数校验;
|
||||
// 校验存在
|
||||
// 1.1 校验存在
|
||||
validateProductCategoryExists(id);
|
||||
// 校验是否还有子分类
|
||||
// 1.2 校验是否还有子分类
|
||||
if (productCategoryMapper.selectCountByParentId(id) > 0) {
|
||||
throw exception(product_CATEGORY_EXISTS_CHILDREN);
|
||||
}
|
||||
// 校验是否被产品使用
|
||||
// 1.3 校验是否被产品使用
|
||||
if (crmProductService.getProductByCategoryId(id) !=null) {
|
||||
throw exception(PRODUCT_CATEGORY_USED);
|
||||
}
|
||||
// 删除
|
||||
// 2. 删除
|
||||
productCategoryMapper.deleteById(id);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ public class CrmProductServiceImpl implements CrmProductService {
|
|||
private AdminUserApi adminUserApi;
|
||||
|
||||
@Override
|
||||
// TODO @puhui999:操作日志
|
||||
public Long createProduct(CrmProductSaveReqVO createReqVO) {
|
||||
// 校验产品
|
||||
adminUserApi.validateUserList(Collections.singleton(createReqVO.getOwnerUserId()));
|
||||
|
@ -66,6 +67,7 @@ public class CrmProductServiceImpl implements CrmProductService {
|
|||
}
|
||||
|
||||
@Override
|
||||
// TODO @puhui999:操作日志
|
||||
public void updateProduct(CrmProductSaveReqVO updateReqVO) {
|
||||
// 校验产品
|
||||
updateReqVO.setOwnerUserId(null); // 不修改负责人
|
||||
|
@ -102,6 +104,7 @@ public class CrmProductServiceImpl implements CrmProductService {
|
|||
}
|
||||
|
||||
@Override
|
||||
// TODO @puhui999:操作日志
|
||||
public void deleteProduct(Long id) {
|
||||
// 校验存在
|
||||
validateProductExists(id);
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
/**
|
||||
* 产品表
|
||||
*/
|
||||
package cn.iocoder.yudao.module.crm.service.product;
|
|
@ -52,7 +52,10 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
|
|||
private CrmPermissionService crmPermissionService;
|
||||
|
||||
@Override
|
||||
// TODO @puhui999:操作日志
|
||||
public Long createReceivablePlan(CrmReceivablePlanCreateReqVO createReqVO, Long userId) {
|
||||
// TODO @liuhongfeng:第几期的计算;基于是 contractId + contractDO 的第几个还款
|
||||
// TODO @liuhongfeng contractId:校验合同是否存在
|
||||
// 插入
|
||||
CrmReceivablePlanDO receivablePlan = CrmReceivablePlanConvert.INSTANCE.convert(createReqVO);
|
||||
receivablePlan.setFinishStatus(false);
|
||||
|
@ -87,7 +90,9 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
|
|||
|
||||
@Override
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
|
||||
// TODO @puhui999:操作日志
|
||||
public void updateReceivablePlan(CrmReceivablePlanUpdateReqVO updateReqVO) {
|
||||
// TODO @liuhongfeng:如果已经有对应的还款,则不允许编辑;
|
||||
// 校验存在
|
||||
validateReceivablePlanExists(updateReqVO.getId());
|
||||
|
||||
|
@ -136,6 +141,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
|
|||
return receivablePlanMapper.selectPageByCustomerId(pageReqVO);
|
||||
}
|
||||
|
||||
// TODO @puhui999:这个没有 transfer 接口;可能是的哈
|
||||
@Override
|
||||
public void transferReceivablePlan(CrmReceivablePlanTransferReqVO reqVO, Long userId) {
|
||||
// 1 校验回款计划是否存在
|
||||
|
|
|
@ -53,10 +53,10 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
|
|||
@Resource
|
||||
private CrmPermissionService crmPermissionService;
|
||||
|
||||
// TODO @liuhongfeng:创建还款后,是不是什么时候,要更新 plan?
|
||||
@Override
|
||||
// TODO @puhui999:操作日志
|
||||
public Long createReceivable(CrmReceivableCreateReqVO createReqVO) {
|
||||
// 插入
|
||||
// 插入还款
|
||||
CrmReceivableDO receivable = CrmReceivableConvert.INSTANCE.convert(createReqVO);
|
||||
if (ObjectUtil.isNull(receivable.getAuditStatus())) {
|
||||
receivable.setAuditStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
|
@ -64,15 +64,17 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
|
|||
receivable.setAuditStatus(CrmAuditStatusEnum.DRAFT.getStatus());
|
||||
|
||||
// TODO @liuhongfeng:一般来说,逻辑的写法,是要先检查,后操作 db;所以,你这个 check 应该放到 CrmReceivableDO receivable 之前;
|
||||
// 校验
|
||||
checkReceivable(receivable);
|
||||
|
||||
receivableMapper.insert(receivable);
|
||||
|
||||
// TODO @liuhongfeng:需要更新关联的 plan
|
||||
return receivable.getId();
|
||||
}
|
||||
|
||||
// TODO @liuhongfeng:这里的括号要注意排版;
|
||||
private void checkReceivable(CrmReceivableDO receivable) {
|
||||
// TODO @liuhongfeng:校验 no 的唯一性
|
||||
// TODO @liuhongfeng:这个放在参数校验合适
|
||||
if (ObjectUtil.isNull(receivable.getContractId())) {
|
||||
throw exception(CONTRACT_NOT_EXISTS);
|
||||
|
@ -96,17 +98,29 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
|
|||
}
|
||||
|
||||
@Override
|
||||
// TODO @puhui999:操作日志
|
||||
// TODO @puhui999:权限校验
|
||||
public void updateReceivable(CrmReceivableUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateReceivableExists(updateReqVO.getId());
|
||||
// TODO @liuhongfeng:只有在草稿、审核中,可以提交修改
|
||||
|
||||
// 更新
|
||||
// 更新还款
|
||||
CrmReceivableDO updateObj = CrmReceivableConvert.INSTANCE.convert(updateReqVO);
|
||||
receivableMapper.updateById(updateObj);
|
||||
|
||||
// TODO @liuhongfeng:需要更新关联的 plan
|
||||
}
|
||||
|
||||
// TODO @liuhongfeng:缺一个取消合同的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum
|
||||
|
||||
// TODO @liuhongfeng:缺一个发起审批的接口;只有草稿可以发起审批;CrmAuditStatusEnum
|
||||
|
||||
@Override
|
||||
// TODO @puhui999:操作日志
|
||||
// TODO @puhui999:权限校验
|
||||
public void deleteReceivable(Long id) {
|
||||
// TODO @liuhongfeng:如果被 CrmReceivablePlanDO 所使用,则不允许删除
|
||||
// 校验存在
|
||||
validateReceivableExists(id);
|
||||
// 删除
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
/**
|
||||
* 回款
|
||||
*/
|
||||
package cn.iocoder.yudao.module.crm.service.receivable;
|
Loading…
Reference in New Issue