商机模块代码优化

This commit is contained in:
lzxhqs 2024-01-22 16:48:59 +08:00
parent 206899bfc0
commit fb54c5fc89
12 changed files with 167 additions and 52 deletions

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.product; package cn.iocoder.yudao.module.crm.controller.admin.business.vo.product;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
@ -16,12 +17,12 @@ public class CrmBusinessProductSaveReqVO {
// TODO @lzxhqs这个字段应该是 Long 类型 // TODO @lzxhqs这个字段应该是 Long 类型
@Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
@NotNull(message = "商机编号不能为空") @NotNull(message = "商机编号不能为空")
private Integer businessId; private Long businessId;
// TODO @lzxhqs这个字段应该是 Long 类型 // TODO @lzxhqs这个字段应该是 Long 类型
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
@NotNull(message = "产品编号不能为空") @NotNull(message = "产品编号不能为空")
private Integer productId; private Long productId;
@Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
@NotNull(message = "产品单价不能为空") @NotNull(message = "产品单价不能为空")
@ -45,7 +46,7 @@ public class CrmBusinessProductSaveReqVO {
// TODO @lzxhqs字符串 @NotEmpty因为要考虑 "" 前端搞了这个玩意 // TODO @lzxhqs字符串 @NotEmpty因为要考虑 "" 前端搞了这个玩意
@Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
@NotNull(message = "单位不能为空") @NotEmpty(message = "单位不能为空")
private String unit; private String unit;
} }

View File

@ -98,7 +98,7 @@ public class CrmBusinessDO extends BaseDO {
* *
* TODO @lzxhqs目前就是 Boolean是否跟进 * TODO @lzxhqs目前就是 Boolean是否跟进
*/ */
private Integer followUpStatus; private Boolean followUpStatus;
/** /**
* 负责人的用户编号 * 负责人的用户编号

View File

@ -48,7 +48,7 @@ public class CrmBusinessProductDO extends BaseDO {
/** /**
* 产品单价 * 产品单价
*/ */
private BigDecimal price; private Integer price;
/** /**
* 销售价格 * 销售价格
@ -59,19 +59,19 @@ public class CrmBusinessProductDO extends BaseDO {
/** /**
* 数量 * 数量
*/ */
private BigDecimal num; private BigDecimal count;
// TODO @lzxhqs改成 discountPercent // TODO @lzxhqs改成 discountPercent
/** /**
* 折扣 * 折扣
*/ */
private BigDecimal discount; private BigDecimal discountPercent;
// TODO @lzxhqs改成 totalPrice总计价格和现有项目风格一致 // TODO @lzxhqs改成 totalPrice总计价格和现有项目风格一致
/** /**
* 小计折扣后价格 * 小计折扣后价格
*/ */
private BigDecimal subtotal; private BigDecimal totalPrice;
/** /**
* 单位 * 单位

View File

@ -7,10 +7,12 @@ import org.apache.ibatis.annotations.Mapper;
/** /**
* 商机产品 Mapper // TODO @lzxhqs类注释和作者之间要有一个空行 * 商机产品 Mapper // TODO @lzxhqs类注释和作者之间要有一个空行
*
* @author lzxhqs * @author lzxhqs
*/ */
@Mapper @Mapper
public interface CrmBusinessProductMapper extends BaseMapperX<CrmBusinessProductDO> { public interface CrmBusinessProductMapper extends BaseMapperX<CrmBusinessProductDO> {
default void deleteByBusinessId(Long id) { // TODO @lzxhqs第一个方法和类之间最好空一行 default void deleteByBusinessId(Long id) { // TODO @lzxhqs第一个方法和类之间最好空一行
delete(CrmBusinessProductDO::getBusinessId, id); delete(CrmBusinessProductDO::getBusinessId, id);
} }

View File

@ -65,8 +65,9 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> {
default Long selectCountByContactId(Long contactId) { default Long selectCountByContactId(Long contactId) {
return selectCount(CrmContractDO::getContactId, contactId); return selectCount(CrmContractDO::getContactId, contactId);
} }
default CrmContractDO selectByBizId(Long businessId) { // TODO @lzxhqs1方法和方法之间要有空行2selectCountByBusinessId一个是应该求数量一个是不要缩写 BizId 可读性
return selectOne(CrmContractDO::getBusinessId, businessId); default Long selectCountByBusinessId(Long businessId) { // TODO @lzxhqs1方法和方法之间要有空行2selectCountByBusinessId一个是应该求数量一个是不要缩写 BizId 可读性
return selectCount(CrmContractDO::getBusinessId, businessId);
} }
} }

View File

@ -0,0 +1,43 @@
package cn.iocoder.yudao.module.crm.service.business;
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
import java.util.List;
/**
* 商机产品关联表 Service 接口
*
* @author lzxhqs
*/
public interface CrmBusinessProductService {
/**
* 批量新增商机产品关联数据
* @param list 商机产品集合
*/
void insertBatch(List<CrmBusinessProductDO> list);
/**
* 根据商机id获取商机产品关联数据集合
* @param businessId 商机id
*/
List<CrmBusinessProductDO> selectListByBusinessId(Long businessId);
/**
* 批量更新商机产品表
* @param list 商机产品数据集合
*/
void updateBatch(List<CrmBusinessProductDO> list);
/**
* 批量删除
* @param list 需要删除的商机产品集合
*/
void deleteBatch(List<CrmBusinessProductDO> list);
/**
*根据商机id删除商机产品关联数据
* @param businessId 商机id
*/
void deleteByBusinessId(Long businessId);
}

View File

@ -0,0 +1,48 @@
package cn.iocoder.yudao.module.crm.service.business;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.List;
/**
* 商机产品关联表 Service 实现类
*
* @author lzxhqs
*/
@Service
@Validated
public class CrmBusinessProductServiceImpl implements CrmBusinessProductService {
@Resource
private CrmBusinessProductMapper businessProductMapper;
@Override
public void insertBatch(List<CrmBusinessProductDO> list) {
businessProductMapper.insertBatch(list);
}
@Override
public List<CrmBusinessProductDO> selectListByBusinessId(Long businessId) {
return businessProductMapper.selectList(CrmBusinessProductDO::getBusinessId,businessId);
}
@Override
public void updateBatch(List<CrmBusinessProductDO> list) {
businessProductMapper.updateBatch(list);
}
@Override
public void deleteBatch(List<CrmBusinessProductDO> list) {
businessProductMapper.deleteBatchIds(CollectionUtils.convertList(list,CrmBusinessProductDO::getId));
}
@Override
public void deleteByBusinessId(Long businessId) {
businessProductMapper.deleteByBusinessId(businessId);
}
}

View File

@ -2,7 +2,9 @@ package cn.iocoder.yudao.module.crm.service.business;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil; import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; 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.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
@ -13,15 +15,12 @@ import cn.iocoder.yudao.module.crm.convert.businessproduct.CrmBusinessProductCon
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.business.CrmBusinessProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
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.contract.CrmContractDO;
import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper;
import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper;
import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessMapper;
import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper;
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;
import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService;
import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
@ -33,7 +32,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -56,14 +54,13 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
private CrmBusinessMapper businessMapper; private CrmBusinessMapper businessMapper;
@Resource @Resource
private CrmBusinessProductMapper businessProductMapper; private CrmBusinessProductService businessProductService;
// TODO @lzxhqs不直接调用这个 mapper要调用对方的 service每个业务独立收敛 // TODO @lzxhqs不直接调用这个 mapper要调用对方的 service每个业务独立收敛
@Resource @Resource
private CrmContractMapper contractMapper; private CrmContractService contractService;
// TODO @lzxhqs不直接调用这个 mapper要调用对方的 service每个业务独立收敛 // TODO @lzxhqs不直接调用这个 mapper要调用对方的 service每个业务独立收敛
@Resource
private CrmContactBusinessMapper contactBusinessMapper;
@Resource @Resource
private CrmPermissionService permissionService; private CrmPermissionService permissionService;
@Resource @Resource
@ -81,10 +78,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
businessMapper.insert(business); businessMapper.insert(business);
// TODO 商机待定插入商机与产品的关联表校验商品存在 // TODO 商机待定插入商机与产品的关联表校验商品存在
// TODO lzxhqs新增时是不是不用调用这个方法哈 // TODO lzxhqs新增时是不是不用调用这个方法哈
verifyCrmBusinessProduct(business.getId());
// TODO @lzxhqs CollUtils.isNotEmpty // TODO @lzxhqs CollUtils.isNotEmpty
if (!createReqVO.getProducts().isEmpty()) { if (CollUtil.isNotEmpty(createReqVO.getProducts())) {
createBusinessProducts(createReqVO.getProducts(), business.getId()); createBusinessProducts(createReqVO.getProducts(), business.getId(), false);
} }
// TODO 商机待定在联系人的详情页如果直接新建商机则需要关联下这里要搞个 CrmContactBusinessDO // TODO 商机待定在联系人的详情页如果直接新建商机则需要关联下这里要搞个 CrmContactBusinessDO
createContactBusiness(business.getId(), createReqVO.getContactId()); createContactBusiness(business.getId(), createReqVO.getContactId());
@ -111,37 +107,39 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
CrmContactBusinessDO contactBusiness = new CrmContactBusinessDO(); CrmContactBusinessDO contactBusiness = new CrmContactBusinessDO();
contactBusiness.setBusinessId(businessId); contactBusiness.setBusinessId(businessId);
contactBusiness.setContactId(contactId); contactBusiness.setContactId(contactId);
contactBusinessMapper.insert(contactBusiness); contactBusinessService.insert(contactBusiness);
} }
// TODO @lzxhqs这个方法注释格式不对删除@description然后把 插入商机产品关联表 作为方法注释 // TODO @lzxhqs这个方法注释格式不对删除@description然后把 插入商机产品关联表 作为方法注释
/** /**
* 插入商机产品关联表
*
* @param products 产品集合 * @param products 产品集合
* @description 插入商机产品关联表 * @param businessId 商机id
* @param updateFlag 更新标识 true 代表更新
* @author lzxhqs * @author lzxhqs
*/ */
private void createBusinessProducts(List<CrmBusinessProductSaveReqVO> products, Long businessId) { private void createBusinessProducts(List<CrmBusinessProductSaveReqVO> products, Long businessId, Boolean updateFlag) {
// TODO @lzxhqs可以用 CollectionUtils.convertList // TODO @lzxhqs可以用 CollectionUtils.convertList
List<CrmBusinessProductDO> list = new ArrayList<>(); List<CrmBusinessProductDO> list = CollectionUtils.convertList(products, product ->
for (CrmBusinessProductSaveReqVO product : products) { CrmBusinessProductConvert.INSTANCE.convert(product).setBusinessId(businessId));
CrmBusinessProductDO businessProductDO = CrmBusinessProductConvert.INSTANCE.convert(product); if (Boolean.TRUE.equals(updateFlag)) {
businessProductDO.setBusinessId(businessId); // 根据商机 id从商机产品关联表中获取已存在的数据集合
list.add(businessProductDO); List<CrmBusinessProductDO> oldProducts = businessProductService.selectListByBusinessId(businessId);
List<List<CrmBusinessProductDO>> diffList = CollectionUtils.diffList(oldProducts, list, (oldValue, newValue) ->
ObjectUtil.equal(oldValue.getProductId(), newValue.getProductId()));
if (CollUtil.isNotEmpty(diffList.getFirst())) {
businessProductService.insertBatch(diffList.getFirst());
} }
businessProductMapper.insertBatch(list); if (CollUtil.isNotEmpty(diffList.get(1))) {
businessProductService.updateBatch(diffList.get(1));
} }
if (CollUtil.isNotEmpty(diffList.get(2))) {
/** businessProductService.deleteBatch(diffList.get(2));
* @param id businessId }
* @description 校验管理的产品存在则删除 } else {
* @author lzxhqs businessProductService.insertBatch(list);
*/
private void verifyCrmBusinessProduct(Long id) {
CrmBusinessProductDO businessProductDO = businessProductMapper.selectByBusinessId(id);
if (businessProductDO != null) {
//通过商机Id删除
businessProductMapper.deleteByBusinessId(id);
} }
} }
@ -160,9 +158,10 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
businessMapper.updateById(updateObj); businessMapper.updateById(updateObj);
// TODO 商机待定插入商机与产品的关联表校验商品存在 // TODO 商机待定插入商机与产品的关联表校验商品存在
// TODO @lzxhqs更新时可以调用 CollectionUtils diffList尽量避免这种先删除再插入而是新增的插入变更的更新没的删除不然这个表每次更新会多好多数据 // TODO @lzxhqs更新时可以调用 CollectionUtils diffList尽量避免这种先删除再插入而是新增的插入变更的更新没的删除不然这个表每次更新会多好多数据
verifyCrmBusinessProduct(updateReqVO.getId()); if (CollUtil.isNotEmpty(updateReqVO.getProducts())) {
if (!updateReqVO.getProducts().isEmpty()) { createBusinessProducts(updateReqVO.getProducts(), updateReqVO.getId(), true);
createBusinessProducts(updateReqVO.getProducts(), updateReqVO.getId()); } else {
businessProductService.deleteByBusinessId(updateReqVO.getId());
} }
// TODO @商机待定如果状态发生变化插入商机状态变更记录表 // TODO @商机待定如果状态发生变化插入商机状态变更记录表
@ -197,14 +196,14 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
} }
/** /**
* 删除校验合同是关联合同
*
* @param businessId 商机id * @param businessId 商机id
* @throws
* @description 删除校验合同是关联合同
* @author lzxhqs * @author lzxhqs
*/ */
private void validateContractExists(Long businessId) { private void validateContractExists(Long businessId) {
CrmContractDO contract = contractMapper.selectByBizId(businessId); Long count = contractService.selectCountByBusinessId(businessId);
if (contract != null) { if (count > 0) {
throw exception(BUSINESS_CONTRACT_EXISTS); throw exception(BUSINESS_CONTRACT_EXISTS);
} }
} }

View File

@ -42,4 +42,9 @@ public interface CrmContactBusinessService {
*/ */
List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId); List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId);
/**
* 新增联系人与商机的
* @param contactBusiness 新增联系人与商机的对象
*/
void insert(CrmContactBusinessDO contactBusiness);
} }

View File

@ -85,4 +85,9 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService
return contactBusinessMapper.selectListByContactId(contactId); return contactBusinessMapper.selectListByContactId(contactId);
} }
@Override
public void insert(CrmContactBusinessDO contactBusiness) {
contactBusinessMapper.insert(contactBusiness);
}
} }

View File

@ -110,4 +110,10 @@ public interface CrmContractService {
*/ */
Long getContractCountByCustomerId(Long customerId); Long getContractCountByCustomerId(Long customerId);
/**
* 根据商机ID获取关联客户的合同数量
* @param businessId 商机ID
* @return 数量
*/
Long selectCountByBusinessId(Long businessId);
} }

View File

@ -178,5 +178,10 @@ public class CrmContractServiceImpl implements CrmContractService {
return contractMapper.selectCount(CrmContractDO::getCustomerId, customerId); return contractMapper.selectCount(CrmContractDO::getCustomerId, customerId);
} }
@Override
public Long selectCountByBusinessId(Long businessId) {
return contractMapper.selectCountByBusinessId(businessId);
}
// TODO @合同待定需要新增一个 ContractConfigDO 合同配置重点是到期提醒 // TODO @合同待定需要新增一个 ContractConfigDO 合同配置重点是到期提醒
} }