!875 完善 review 提到的问题

Merge pull request !875 from puhui999/develop
This commit is contained in:
芋道源码 2024-02-21 14:57:22 +00:00 committed by Gitee
commit df2441def9
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
17 changed files with 80 additions and 70 deletions

View File

@ -26,6 +26,7 @@ public interface ErrorCodeConstants {
ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在");
ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode(1_020_003_001, "联系人商机关联不存在"); ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode(1_020_003_001, "联系人商机关联不存在");
ErrorCode CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS = new ErrorCode(1_020_003_002, "联系人已关联合同,不能删除"); ErrorCode CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS = new ErrorCode(1_020_003_002, "联系人已关联合同,不能删除");
ErrorCode CONTACT_UPDATE_OWNER_USER_FAIL = new ErrorCode(1_020_003_003, "更新联系人负责人失败");
// ========== 回款 1-020-004-000 ========== // ========== 回款 1-020-004-000 ==========
ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在"); ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在");

View File

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

View File

@ -130,14 +130,13 @@ public class CrmContractRespVO {
private Integer auditStatus; private Integer auditStatus;
@Schema(description = "产品列表") @Schema(description = "产品列表")
private List<CrmContractProductItemRespVO> productItems; private List<Item> items;
// TODO @puhui999可以直接叫 Item
@Schema(description = "产品列表") @Schema(description = "产品列表")
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public static class CrmContractProductItemRespVO { public static class Item {
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529") @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529")
private Long id; private Long id;

View File

@ -59,8 +59,8 @@ public interface CrmContractConvert {
default void setContractRespVOProductItems(CrmContractRespVO respVO, Map<Long, CrmContractProductDO> contractProductMap, default void setContractRespVOProductItems(CrmContractRespVO respVO, Map<Long, CrmContractProductDO> contractProductMap,
List<CrmProductDO> productList) { List<CrmProductDO> productList) {
respVO.setProductItems(CollectionUtils.convertList(productList, product -> { respVO.setItems(CollectionUtils.convertList(productList, product -> {
CrmContractRespVO.CrmContractProductItemRespVO productItemRespVO = BeanUtils.toBean(product, CrmContractRespVO.CrmContractProductItemRespVO.class); CrmContractRespVO.Item productItemRespVO = BeanUtils.toBean(product, CrmContractRespVO.Item.class);
findAndThen(contractProductMap, product.getId(), contractProduct -> findAndThen(contractProductMap, product.getId(), contractProduct ->
productItemRespVO.setCount(contractProduct.getCount()).setDiscountPercent(contractProduct.getDiscountPercent())); productItemRespVO.setCount(contractProduct.getCount()).setDiscountPercent(contractProduct.getDiscountPercent()));
return productItemRespVO; return productItemRespVO;

View File

@ -57,8 +57,9 @@ public class CrmContractProductDO extends BaseDO {
private Integer discountPercent; private Integer discountPercent;
/** /**
* 总计价格折扣后价格 * 总计价格折扣后价格
* * = {@link #price}
* TODO @puhui999可以写下计算公式哈 * * {@link #count}
* * ({@link #discountPercent / 100})
*/ */
private Integer totalPrice; private Integer totalPrice;

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.crm.dal.mysql.business;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
@ -16,18 +15,8 @@ import java.util.List;
@Mapper @Mapper
public interface CrmBusinessProductMapper extends BaseMapperX<CrmBusinessProductDO> { public interface CrmBusinessProductMapper extends BaseMapperX<CrmBusinessProductDO> {
// TODO @puhui999用不到的方法看看是不是删除哈
default void deleteByBusinessId(Long getBusinessId) { // TODO @lzxhqs第一个方法和类之间最好空一行
delete(CrmBusinessProductDO::getBusinessId, getBusinessId);
}
default CrmBusinessProductDO selectByBusinessId(Long getBusinessId) {
return selectOne(CrmBusinessProductDO::getBusinessId, getBusinessId);
}
default List<CrmBusinessProductDO> selectListByBusinessId(Long businessId) { default List<CrmBusinessProductDO> selectListByBusinessId(Long businessId) {
// TODO @puhui999可以简化selectList(CrmBusinessProductDO::getBusinessId, businessId) return selectList(CrmBusinessProductDO::getBusinessId, businessId);
return selectList(new LambdaQueryWrapperX<CrmBusinessProductDO>().eq(CrmBusinessProductDO::getBusinessId, businessId));
} }
} }

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink; package cn.iocoder.yudao.module.crm.dal.mysql.contact;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
@ -9,7 +9,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
/** /**
* CRM 联系人商机关联 Mapper * CRM 联系人商机关联 Mapper
* *
* @author 芋道源码 * @author 芋道源码
*/ */
@ -31,4 +31,4 @@ public interface CrmContactBusinessMapper extends BaseMapperX<CrmContactBusiness
return selectList(CrmContactBusinessDO::getContactId, contactId); return selectList(CrmContactBusinessDO::getContactId, contactId);
} }
} }

View File

@ -65,4 +65,8 @@ public interface CrmContactMapper extends BaseMapperX<CrmContactDO> {
return selectJoinList(CrmContactDO.class, query); return selectJoinList(CrmContactDO.class, query);
} }
default List<CrmContactDO> selectListByCustomerId(Long customerId) {
return selectList(CrmContactDO::getCustomerId, customerId);
}
} }

View File

@ -16,15 +16,6 @@ import java.util.List;
@Mapper @Mapper
public interface CrmContractProductMapper extends BaseMapperX<CrmContractProductDO> { public interface CrmContractProductMapper extends BaseMapperX<CrmContractProductDO> {
// TODO @puhui999用不到的方法看看是不是删除哈
default void deleteByContractId(Long contractId) { // TODO @lzxhqs第一个方法和类之间最好空一行
delete(CrmContractProductDO::getContractId, contractId);
}
default CrmContractProductDO selectByContractId(Long contractId) {
return selectOne(CrmContractProductDO::getContractId, contractId);
}
default List<CrmContractProductDO> selectListByContractId(Long contractId) { default List<CrmContractProductDO> selectListByContractId(Long contractId) {
return selectList(new LambdaQueryWrapperX<CrmContractProductDO>().eq(CrmContractProductDO::getContractId, contractId)); return selectList(new LambdaQueryWrapperX<CrmContractProductDO>().eq(CrmContractProductDO::getContractId, contractId));
} }

View File

@ -100,10 +100,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
businessProducts.forEach(item -> item.setBusinessId(business.getId())); businessProducts.forEach(item -> item.setBusinessId(business.getId()));
businessProductMapper.insertBatch(businessProducts); businessProductMapper.insertBatch(businessProducts);
} }
// 在联系人的详情页如果直接新建商机则需要关联下
// TODO @puhui999在联系人的详情页如果直接新建商机则需要关联下这里要搞个 CrmContactBusinessDO contactBusinessService.createContactBusiness(createReqVO.getContactId(), business.getId());
createContactBusiness(business.getId(), createReqVO.getContactId());
// 3. 创建数据权限 // 3. 创建数据权限
// 设置当前操作的人为负责人 // 设置当前操作的人为负责人
permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()) permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())
@ -114,17 +112,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
return business.getId(); return business.getId();
} }
// TODO @lzxhqsCrmContactBusinessService 调用这个这样逻辑才能收敛哈
private void createContactBusiness(Long businessId, Long contactId) {
if (contactId == null) {
return;
}
CrmContactBusinessDO contactBusiness = new CrmContactBusinessDO();
contactBusiness.setBusinessId(businessId);
contactBusiness.setContactId(contactId);
contactBusinessService.insert(contactBusiness);
}
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",

View File

@ -25,13 +25,13 @@ public class CrmBusinessUpdateProductReqBO {
// TODO @芋艿再想想 // TODO @芋艿再想想
@NotEmpty(message = "产品列表不能为空") @NotEmpty(message = "产品列表不能为空")
private List<CrmBusinessProductItem> productItems; private List<Item> items;
@Schema(description = "产品列表") @Schema(description = "产品列表")
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public static class CrmBusinessProductItem { public static class Item {
@Schema(description = "产品编号", example = "20529") @Schema(description = "产品编号", example = "20529")
@NotNull(message = "产品编号不能为空") @NotNull(message = "产品编号不能为空")

View File

@ -13,6 +13,15 @@ import java.util.List;
*/ */
public interface CrmContactBusinessService { public interface CrmContactBusinessService {
/**
* 创建联系人人商机关联
*
* @param contactId 联系人编号
* @param businessId 商机编号
*/
void createContactBusiness(Long contactId, Long businessId);
/** /**
* 创建联系人与商机的关联 * 创建联系人与商机的关联
* *
@ -42,11 +51,4 @@ public interface CrmContactBusinessService {
*/ */
List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId); List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId);
/**
* 新增联系人与商机的关联
*
* @param contactBusiness 新增联系人与商机的对象
*/
void insert(CrmContactBusinessDO contactBusiness);
} }

View File

@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusines
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; 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.CrmContactBusinessDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; 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.dal.mysql.contact.CrmContactBusinessMapper;
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; 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.framework.permission.core.annotations.CrmPermission;
@ -41,6 +41,22 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService
@Lazy // 延迟加载为了解决延迟加载 @Lazy // 延迟加载为了解决延迟加载
private CrmContactService contactService; private CrmContactService contactService;
@Override
public void createContactBusiness(Long contactId, Long businessId) {
// 校验存在
CrmContactDO contact = contactService.getContact(contactId);
if (contact == null) {
throw exception(CONTACT_NOT_EXISTS);
}
CrmBusinessDO business = businessService.getBusiness(businessId);
if (business == null) {
throw exception(BUSINESS_NOT_EXISTS);
}
// 插入
contactBusinessMapper.insert(new CrmContactBusinessDO(null, contactId, businessId));
}
@Override @Override
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#createReqVO.contactId", level = CrmPermissionLevelEnum.WRITE) @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#createReqVO.contactId", level = CrmPermissionLevelEnum.WRITE)
public void createContactBusinessList(CrmContactBusinessReqVO createReqVO) { public void createContactBusinessList(CrmContactBusinessReqVO createReqVO) {
@ -91,9 +107,4 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService
return contactBusinessMapper.selectListByContactId(contactId); return contactBusinessMapper.selectListByContactId(contactId);
} }
@Override
public void insert(CrmContactBusinessDO contactBusiness) {
contactBusinessMapper.insert(contactBusiness);
}
} }

View File

@ -55,6 +55,7 @@ public interface CrmContactService {
/** /**
* 更新指定客户的联系人的负责人 * 更新指定客户的联系人的负责人
* 数据权限基于 客户
* *
* @param customerId 客户编号 * @param customerId 客户编号
* @param ownerUserId 用户编号 * @param ownerUserId 用户编号
@ -64,8 +65,8 @@ public interface CrmContactService {
/** /**
* 更新联系人相关跟进信息 * 更新联系人相关跟进信息
* *
* @param id 编号 * @param id 编号
* @param contactNextTime 下次联系时间 * @param contactNextTime 下次联系时间
* @param contactLastContent 最后联系内容 * @param contactLastContent 最后联系内容
*/ */
void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent); void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent);
@ -73,8 +74,8 @@ public interface CrmContactService {
/** /**
* 更新联系人相关跟进信息 * 更新联系人相关跟进信息
* *
* @param ids 编号数组 * @param ids 编号数组
* @param contactNextTime 下次联系时间 * @param contactNextTime 下次联系时间
* @param contactLastContent 最后联系内容 * @param contactLastContent 最后联系内容
*/ */
void updateContactFollowUpBatch(Collection<Long> ids, LocalDateTime contactNextTime, String contactLastContent); void updateContactFollowUpBatch(Collection<Long> ids, LocalDateTime contactNextTime, String contactLastContent);

View File

@ -184,7 +184,7 @@ public class CrmContactServiceImpl implements CrmContactService {
// 2.1 数据权限转移 // 2.1 数据权限转移
permissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_CONTACT.getType(), permissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_CONTACT.getType(),
reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel())); reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel()));
// 2.2 设置新的负责人 // 2.2 设置新的负责人
contactMapper.updateById(new CrmContactDO().setId(reqVO.getId()).setOwnerUserId(reqVO.getNewOwnerUserId())); contactMapper.updateById(new CrmContactDO().setId(reqVO.getId()).setOwnerUserId(reqVO.getNewOwnerUserId()));
@ -193,9 +193,31 @@ public class CrmContactServiceImpl implements CrmContactService {
} }
@Override @Override
@Transactional(rollbackFor = Exception.class)
@CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#customerId", level = CrmPermissionLevelEnum.OWNER)
public void updateOwnerUserIdByCustomerId(Long customerId, Long ownerUserId) { public void updateOwnerUserIdByCustomerId(Long customerId, Long ownerUserId) {
contactMapper.updateOwnerUserIdByCustomerId(customerId, ownerUserId); // 1. 校验存在
// TODO @puhui999操作日志数据权限 List<CrmContactDO> contacts = contactMapper.selectListByCustomerId(customerId);
if (CollUtil.isEmpty(contacts)) {
return;
}
int count = contactMapper.updateOwnerUserIdByCustomerId(customerId, ownerUserId);
if (count == 0) {
throw exception(CONTACT_UPDATE_OWNER_USER_FAIL);
}
// 2. 记录操作日志
for (CrmContactDO contact : contacts) {
receiveContactLog(contact, ownerUserId);
}
}
@LogRecord(type = CRM_CONTACT_TYPE, subType = CRM_CONTACT_UPDATE_OWNER_USER_SUB_TYPE, bizNo = "{{#contact.id}",
success = CRM_CONTACT_UPDATE_OWNER_USER_SUCCESS)
public void receiveContactLog(CrmContactDO contact, Long ownerUserId) {
// 记录操作日志上下文
LogRecordContext.putVariable("contact", contact);
LogRecordContext.putVariable("ownerUserId", ownerUserId);
} }
@Override @Override

View File

@ -104,7 +104,7 @@ public class CrmContractServiceImpl implements CrmContractService {
// 如果存在合同关联了商机则更新商机商品关联 // 如果存在合同关联了商机则更新商机商品关联
if (contract.getBusinessId() != null) { if (contract.getBusinessId() != null) {
businessService.updateBusinessProduct(new CrmBusinessUpdateProductReqBO().setId(contract.getBusinessId()) businessService.updateBusinessProduct(new CrmBusinessUpdateProductReqBO().setId(contract.getBusinessId())
.setProductItems(BeanUtils.toBean(createReqVO.getProductItems(), CrmBusinessUpdateProductReqBO.CrmBusinessProductItem.class))); .setItems(BeanUtils.toBean(createReqVO.getProductItems(), CrmBusinessUpdateProductReqBO.Item.class)));
} }
} }

View File

@ -412,7 +412,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
return count; return count;
} }
@Transactional // 需要 protected 修饰因为需要在事务中调用 @Transactional(rollbackFor = Exception.class) // 需要 protected 修饰因为需要在事务中调用
protected void putCustomerPool(CrmCustomerDO customer) { protected void putCustomerPool(CrmCustomerDO customer) {
// 1. 设置负责人为 NULL // 1. 设置负责人为 NULL
int updateOwnerUserIncr = customerMapper.updateOwnerUserIdById(customer.getId(), null); int updateOwnerUserIncr = customerMapper.updateOwnerUserIdById(customer.getId(), null);