mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2025-01-31 09:30:05 +08:00
Merge remote-tracking branch 'yudao/develop' into develop
# Conflicts: # yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java # yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
This commit is contained in:
commit
1ad5602a19
@ -22,8 +22,6 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在");
|
||||
ErrorCode BUSINESS_CONTRACT_EXISTS = new ErrorCode(1_020_002_001, "商机已关联合同,不能删除");
|
||||
|
||||
// TODO @lilleo:商机状态、商机类型,都单独错误码段
|
||||
|
||||
// ========== 联系人管理 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, "联系人商机关联不存在");
|
||||
@ -68,6 +66,7 @@ public interface ErrorCodeConstants {
|
||||
// ========== 产品 1_020_008_000 ==========
|
||||
ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_020_008_000, "产品不存在");
|
||||
ErrorCode PRODUCT_NO_EXISTS = new ErrorCode(1_020_008_001, "产品编号已存在");
|
||||
ErrorCode PRODUCT_NOT_ENABLE = new ErrorCode(1_020_008_002, "产品【{}】已禁用");
|
||||
|
||||
// ========== 产品分类 1_020_009_000 ==========
|
||||
ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_020_009_000, "产品分类不存在");
|
||||
@ -77,12 +76,11 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode PRODUCT_CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1_020_009_004, "父分类不能是二级分类");
|
||||
ErrorCode product_CATEGORY_EXISTS_CHILDREN = new ErrorCode(1_020_009_005, "存在子分类,无法删除");
|
||||
|
||||
// ========== 商机状态类型 1_020_010_000 ==========
|
||||
ErrorCode BUSINESS_STATUS_TYPE_NOT_EXISTS = new ErrorCode(1_020_010_000, "商机状态类型不存在");
|
||||
ErrorCode BUSINESS_STATUS_TYPE_NAME_EXISTS = new ErrorCode(1_020_010_001, "商机状态类型名称已存在");
|
||||
|
||||
// ========== 商机状态 1_020_011_000 ==========
|
||||
ErrorCode BUSINESS_STATUS_NOT_EXISTS = new ErrorCode(1_020_011_000, "商机状态不存在");
|
||||
// ========== 商机状态 1_020_010_000 ==========
|
||||
ErrorCode BUSINESS_STATUS_TYPE_NOT_EXISTS = new ErrorCode(1_020_010_000, "商机状态组不存在");
|
||||
ErrorCode BUSINESS_STATUS_TYPE_NAME_EXISTS = new ErrorCode(1_020_010_001, "商机状态组的名称已存在");
|
||||
ErrorCode BUSINESS_STATUS_UPDATE_FAIL_USED = new ErrorCode(1_020_010_002, "已经被使用的商机状态组,无法进行更新");
|
||||
ErrorCode BUSINESS_STATUS_DELETE_FAIL_USED = new ErrorCode(1_020_010_002, "已经被使用的商机状态组,无法进行删除");
|
||||
|
||||
// ========== 客户公海规则设置 1_020_012_000 ==========
|
||||
ErrorCode CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED = new ErrorCode(1_020_012_000, "客户公海配置不存在或未启用");
|
||||
@ -92,6 +90,4 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode FOLLOW_UP_RECORD_NOT_EXISTS = new ErrorCode(1_020_013_000, "跟进记录不存在");
|
||||
ErrorCode FOLLOW_UP_RECORD_DELETE_DENIED = new ErrorCode(1_020_013_001, "删除跟进记录失败,原因:没有权限");
|
||||
|
||||
// ========== 待办消息 1_020_014_000 ==========
|
||||
|
||||
}
|
||||
|
@ -1,32 +0,0 @@
|
||||
### 请求 /transfer
|
||||
PUT {{baseUrl}}/crm/business/transfer
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"ownerUserId": 2,
|
||||
"transferType": 2,
|
||||
"permissionType": 2
|
||||
}
|
||||
|
||||
### 请求 /update
|
||||
PUT {{baseUrl}}/crm/business/update
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": "2",
|
||||
"statusTypeId": 2,
|
||||
"statusId": 2,
|
||||
"customerId": 1
|
||||
}
|
||||
|
||||
### 请求 /get
|
||||
GET {{baseUrl}}/crm/business/get?id=1024
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.business;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
||||
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;
|
||||
@ -10,15 +12,20 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusi
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
|
||||
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.CrmBusinessProductDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
|
||||
import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
|
||||
import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService;
|
||||
import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusTypeService;
|
||||
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
|
||||
import cn.iocoder.yudao.module.crm.service.product.CrmProductService;
|
||||
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@ -30,13 +37,15 @@ import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS;
|
||||
@ -52,9 +61,16 @@ public class CrmBusinessController {
|
||||
@Resource
|
||||
private CrmCustomerService customerService;
|
||||
@Resource
|
||||
private CrmBusinessStatusTypeService businessStatusTypeService;
|
||||
private CrmBusinessStatusService businessStatusTypeService;
|
||||
@Resource
|
||||
private CrmBusinessStatusService businessStatusService;
|
||||
@Resource
|
||||
private CrmProductService productService;
|
||||
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
@Resource
|
||||
private DeptApi deptApi;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建商机")
|
||||
@ -86,9 +102,25 @@ public class CrmBusinessController {
|
||||
@PreAuthorize("@ss.hasPermission('crm:business:query')")
|
||||
public CommonResult<CrmBusinessRespVO> getBusiness(@RequestParam("id") Long id) {
|
||||
CrmBusinessDO business = businessService.getBusiness(id);
|
||||
return success(BeanUtils.toBean(business, CrmBusinessRespVO.class));
|
||||
return success(buildBusinessDetail(business));
|
||||
}
|
||||
|
||||
private CrmBusinessRespVO buildBusinessDetail(CrmBusinessDO business) {
|
||||
if (business == null) {
|
||||
return null;
|
||||
}
|
||||
CrmBusinessRespVO businessVO = buildBusinessDetailList(Collections.singletonList(business)).get(0);
|
||||
// 拼接产品项
|
||||
List<CrmBusinessProductDO> businessProducts = businessService.getBusinessProductListByBusinessId(businessVO.getId());
|
||||
Map<Long, CrmProductDO> productMap = productService.getProductMap(
|
||||
convertSet(businessProducts, CrmBusinessProductDO::getProductId));
|
||||
businessVO.setProducts(BeanUtils.toBean(businessProducts, CrmBusinessRespVO.Product.class, businessProductVO ->
|
||||
MapUtils.findAndThen(productMap, businessProductVO.getProductId(),
|
||||
product -> businessProductVO.setProductNo(product.getNo()).setProductUnit(product.getUnit()))));
|
||||
return businessVO;
|
||||
}
|
||||
|
||||
// TODO 芋艿:处理下
|
||||
@GetMapping("/list-by-ids")
|
||||
@Operation(summary = "获得商机列表")
|
||||
@Parameter(name = "ids", description = "编号", required = true, example = "[1024]")
|
||||
@ -97,6 +129,7 @@ public class CrmBusinessController {
|
||||
return success(BeanUtils.toBean(businessService.getBusinessList(ids, getLoginUserId()), CrmBusinessRespVO.class));
|
||||
}
|
||||
|
||||
// TODO 芋艿:处理下
|
||||
@GetMapping("/simple-all-list")
|
||||
@Operation(summary = "获得联系人的精简列表")
|
||||
@PreAuthorize("@ss.hasPermission('crm:contact:query')")
|
||||
@ -113,7 +146,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());
|
||||
return success(buildBusinessDetailPageResult(pageResult));
|
||||
return success(new PageResult<>(buildBusinessDetailList(pageResult.getList()), pageResult.getTotal()));
|
||||
}
|
||||
|
||||
@GetMapping("/page-by-customer")
|
||||
@ -123,7 +156,7 @@ public class CrmBusinessController {
|
||||
throw exception(CUSTOMER_NOT_EXISTS);
|
||||
}
|
||||
PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomerId(pageReqVO);
|
||||
return success(buildBusinessDetailPageResult(pageResult));
|
||||
return success(new PageResult<>(buildBusinessDetailList(pageResult.getList()), pageResult.getTotal()));
|
||||
}
|
||||
|
||||
@GetMapping("/page-by-contact")
|
||||
@ -131,7 +164,7 @@ public class CrmBusinessController {
|
||||
@PreAuthorize("@ss.hasPermission('crm:business:query')")
|
||||
public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessContactPage(@Valid CrmBusinessPageReqVO pageReqVO) {
|
||||
PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByContact(pageReqVO);
|
||||
return success(buildBusinessDetailPageResult(pageResult));
|
||||
return success(new PageResult<>(buildBusinessDetailList(pageResult.getList()), pageResult.getTotal()));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@ -141,29 +174,43 @@ public class CrmBusinessController {
|
||||
public void exportBusinessExcel(@Valid CrmBusinessPageReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
exportReqVO.setPageSize(PAGE_SIZE_NONE);
|
||||
PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPage(exportReqVO, getLoginUserId());
|
||||
List<CrmBusinessDO> list = businessService.getBusinessPage(exportReqVO, getLoginUserId()).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "商机.xls", "数据", CrmBusinessRespVO.class,
|
||||
buildBusinessDetailPageResult(pageResult).getList());
|
||||
buildBusinessDetailList(list));
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建详细的商机分页结果
|
||||
*
|
||||
* @param pageResult 简单的商机分页结果
|
||||
* @return 详细的商机分页结果
|
||||
*/
|
||||
private PageResult<CrmBusinessRespVO> buildBusinessDetailPageResult(PageResult<CrmBusinessDO> pageResult) {
|
||||
if (CollUtil.isEmpty(pageResult.getList())) {
|
||||
return PageResult.empty(pageResult.getTotal());
|
||||
private List<CrmBusinessRespVO> buildBusinessDetailList(List<CrmBusinessDO> list) {
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
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);
|
||||
// 1.1 获取客户列表
|
||||
Map<Long, CrmCustomerDO> customerMap = customerService.getCustomerMap(
|
||||
convertSet(list, CrmBusinessDO::getCustomerId));
|
||||
// 1.2 获取创建人、负责人列表
|
||||
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(list,
|
||||
contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId())));
|
||||
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
|
||||
// 1.3 获得商机状态组
|
||||
Map<Long, CrmBusinessStatusTypeDO> statusTypeMap = businessStatusTypeService.getBusinessStatusTypeMap(
|
||||
convertSet(list, CrmBusinessDO::getStatusTypeId));
|
||||
Map<Long, CrmBusinessStatusDO> statusMap = businessStatusService.getBusinessStatusMap(
|
||||
convertSet(list, CrmBusinessDO::getStatusId));
|
||||
// 2. 拼接数据
|
||||
return BeanUtils.toBean(list, CrmBusinessRespVO.class, businessVO -> {
|
||||
// 2.1 设置客户名称
|
||||
MapUtils.findAndThen(customerMap, businessVO.getCustomerId(), customer -> businessVO.setCustomerName(customer.getName()));
|
||||
// 2.2 设置创建人、负责人名称
|
||||
MapUtils.findAndThen(userMap, NumberUtils.parseLong(businessVO.getCreator()),
|
||||
user -> businessVO.setCreatorName(user.getNickname()));
|
||||
MapUtils.findAndThen(userMap, businessVO.getOwnerUserId(), user -> {
|
||||
businessVO.setOwnerUserName(user.getNickname());
|
||||
MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> businessVO.setOwnerUserDeptName(dept.getName()));
|
||||
});
|
||||
// 2.3 设置商机状态
|
||||
MapUtils.findAndThen(statusTypeMap, businessVO.getStatusTypeId(), statusType -> businessVO.setStatusTypeName(statusType.getName()));
|
||||
MapUtils.findAndThen(statusMap, businessVO.getStatusId(), status -> businessVO.setStatusName(status.getName()));
|
||||
});
|
||||
}
|
||||
|
||||
@PutMapping("/transfer")
|
||||
|
@ -0,0 +1,126 @@
|
||||
package cn.iocoder.yudao.module.crm.controller.admin.business;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
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.module.crm.controller.admin.business.vo.status.CrmBusinessStatusRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
|
||||
import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService;
|
||||
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Tag(name = "管理后台 - CRM 商机状态")
|
||||
@RestController
|
||||
@RequestMapping("/crm/business-status")
|
||||
@Validated
|
||||
public class CrmBusinessStatusController {
|
||||
|
||||
@Resource
|
||||
private CrmBusinessStatusService businessStatusTypeService;
|
||||
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
@Resource
|
||||
private DeptApi deptApi;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建商机状态")
|
||||
@PreAuthorize("@ss.hasPermission('crm:business-status:create')")
|
||||
public CommonResult<Long> createBusinessStatus(@Valid @RequestBody CrmBusinessStatusSaveReqVO createReqVO) {
|
||||
return success(businessStatusTypeService.createBusinessStatus(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新商机状态")
|
||||
@PreAuthorize("@ss.hasPermission('crm:business-status:update')")
|
||||
public CommonResult<Boolean> updateBusinessStatus(@Valid @RequestBody CrmBusinessStatusSaveReqVO updateReqVO) {
|
||||
businessStatusTypeService.updateBusinessStatus(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除商机状态")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('crm:business-status:delete')")
|
||||
public CommonResult<Boolean> deleteBusinessStatusType(@RequestParam("id") Long id) {
|
||||
businessStatusTypeService.deleteBusinessStatusType(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得商机状态")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('crm:business-status:query')")
|
||||
public CommonResult<CrmBusinessStatusRespVO> getBusinessStatusType(@RequestParam("id") Long id) {
|
||||
CrmBusinessStatusTypeDO statusType = businessStatusTypeService.getBusinessStatusType(id);
|
||||
if (statusType == null) {
|
||||
return success(null);
|
||||
}
|
||||
List<CrmBusinessStatusDO> statuses = businessStatusTypeService.getBusinessStatusListByTypeId(id);
|
||||
return success(BeanUtils.toBean(statusType, CrmBusinessStatusRespVO.class,
|
||||
statusTypeVO -> statusTypeVO.setStatuses(BeanUtils.toBean(statuses, CrmBusinessStatusRespVO.Status.class))));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得商机状态分页")
|
||||
@PreAuthorize("@ss.hasPermission('crm:business-status:query')")
|
||||
public CommonResult<PageResult<CrmBusinessStatusRespVO>> getBusinessStatusPage(@Valid PageParam pageReqVO) {
|
||||
// 1. 查询数据
|
||||
PageResult<CrmBusinessStatusTypeDO> pageResult = businessStatusTypeService.getBusinessStatusTypePage(pageReqVO);
|
||||
if (CollUtil.isEmpty(pageResult.getList())) {
|
||||
return success(PageResult.empty(pageResult.getTotal()));
|
||||
}
|
||||
// 2. 拼接数据
|
||||
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
|
||||
convertSet(pageResult.getList(), statusType -> Long.parseLong(statusType.getCreator())));
|
||||
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(
|
||||
convertSetByFlatMap(pageResult.getList(), CrmBusinessStatusTypeDO::getDeptIds, Collection::stream));
|
||||
return success(BeanUtils.toBean(pageResult, CrmBusinessStatusRespVO.class, statusTypeVO -> {
|
||||
statusTypeVO.setCreator(userMap.get(NumberUtils.parseLong(statusTypeVO.getCreator())).getNickname());
|
||||
statusTypeVO.setDeptNames(convertList(statusTypeVO.getDeptIds(),
|
||||
deptId -> deptMap.containsKey(deptId) ? deptMap.get(deptId).getName() : null));
|
||||
}));
|
||||
}
|
||||
|
||||
@GetMapping("/type-simple-list")
|
||||
@Operation(summary = "获得商机状态组列表")
|
||||
public CommonResult<List<CrmBusinessStatusRespVO>> getBusinessStatusTypeSimpleList() {
|
||||
List<CrmBusinessStatusTypeDO> list = businessStatusTypeService.getBusinessStatusTypeList();
|
||||
// 过滤掉部门不匹配的
|
||||
Long deptId = adminUserApi.getUser(getLoginUserId()).getDeptId();
|
||||
list.removeIf(statusType -> CollUtil.isNotEmpty(statusType.getDeptIds()) && !statusType.getDeptIds().contains(deptId));
|
||||
return success(BeanUtils.toBean(list, CrmBusinessStatusRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/status-simple-list")
|
||||
@Operation(summary = "获得商机状态列表")
|
||||
@Parameter(name = "typeId", description = "商机状态组", required = true, example = "1024")
|
||||
public CommonResult<List<CrmBusinessStatusRespVO.Status>> getBusinessStatusSimpleList(@RequestParam("typeId") Long typeId) {
|
||||
List<CrmBusinessStatusDO> list = businessStatusTypeService.getBusinessStatusListByTypeId(typeId);
|
||||
return success(BeanUtils.toBean(list, CrmBusinessStatusRespVO.Status.class));
|
||||
}
|
||||
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
package cn.iocoder.yudao.module.crm.controller.admin.business;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
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.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypePageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeSaveReqVO;
|
||||
import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessStatusConvert;
|
||||
import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessStatusTypeConvert;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
|
||||
import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService;
|
||||
import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusTypeService;
|
||||
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
|
||||
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
|
||||
@Tag(name = "管理后台 - CRM 商机状态类型")
|
||||
@RestController
|
||||
@RequestMapping("/crm/business-status-type")
|
||||
@Validated
|
||||
public class CrmBusinessStatusTypeController {
|
||||
|
||||
@Resource
|
||||
private CrmBusinessStatusTypeService businessStatusTypeService;
|
||||
|
||||
@Resource
|
||||
private CrmBusinessStatusService businessStatusService;
|
||||
|
||||
@Resource
|
||||
private DeptApi deptApi;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建商机状态类型")
|
||||
@PreAuthorize("@ss.hasPermission('crm:business-status-type:create')")
|
||||
public CommonResult<Long> createBusinessStatusType(@Valid @RequestBody CrmBusinessStatusTypeSaveReqVO createReqVO) {
|
||||
return success(businessStatusTypeService.createBusinessStatusType(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新商机状态类型")
|
||||
@PreAuthorize("@ss.hasPermission('crm:business-status-type:update')")
|
||||
public CommonResult<Boolean> updateBusinessStatusType(@Valid @RequestBody CrmBusinessStatusTypeSaveReqVO updateReqVO) {
|
||||
businessStatusTypeService.updateBusinessStatusType(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除商机状态类型")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('crm:business-status-type:delete')")
|
||||
public CommonResult<Boolean> deleteBusinessStatusType(@RequestParam("id") Long id) {
|
||||
businessStatusTypeService.deleteBusinessStatusType(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得商机状态类型")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('crm:business-status-type:query')")
|
||||
public CommonResult<CrmBusinessStatusTypeRespVO> getBusinessStatusType(@RequestParam("id") Long id) {
|
||||
CrmBusinessStatusTypeDO statusType = businessStatusTypeService.getBusinessStatusType(id);
|
||||
// 处理状态回显
|
||||
// TODO @lzxhqs:可以在 businessStatusService 加个 getBusinessStatusListByTypeId 方法,直接返回 List<CrmBusinessStatusDO> 哈,常用的,尽量封装个简单易懂的方法,不用追求绝对通用哈;
|
||||
CrmBusinessStatusQueryVO queryVO = new CrmBusinessStatusQueryVO();
|
||||
queryVO.setTypeId(id);
|
||||
List<CrmBusinessStatusDO> statusList = businessStatusService.selectList(queryVO);
|
||||
return success(CrmBusinessStatusTypeConvert.INSTANCE.convert(statusType, statusList));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得商机状态类型分页")
|
||||
@PreAuthorize("@ss.hasPermission('crm:business-status-type:query')")
|
||||
public CommonResult<PageResult<CrmBusinessStatusTypeRespVO>> getBusinessStatusTypePage(@Valid CrmBusinessStatusTypePageReqVO pageReqVO) {
|
||||
PageResult<CrmBusinessStatusTypeDO> pageResult = businessStatusTypeService.getBusinessStatusTypePage(pageReqVO);
|
||||
// 处理部门回显
|
||||
Set<Long> deptIds = CollectionUtils.convertSetByFlatMap(pageResult.getList(), CrmBusinessStatusTypeDO::getDeptIds,Collection::stream);
|
||||
List<DeptRespDTO> deptList = deptApi.getDeptList(deptIds);
|
||||
return success(CrmBusinessStatusTypeConvert.INSTANCE.convertPage(pageResult, deptList));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出商机状态类型 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('crm:business-status-type:export')")
|
||||
@OperateLog(type = EXPORT)
|
||||
public void exportBusinessStatusTypeExcel(@Valid CrmBusinessStatusTypePageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<CrmBusinessStatusTypeDO> list = businessStatusTypeService.getBusinessStatusTypePage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "商机状态类型.xls", "数据", CrmBusinessStatusTypeRespVO.class,
|
||||
BeanUtils.toBean(list, CrmBusinessStatusTypeRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/get-simple-list")
|
||||
@Operation(summary = "获得商机状态类型列表")
|
||||
@PreAuthorize("@ss.hasPermission('crm:business-status-type:query')")
|
||||
public CommonResult<List<CrmBusinessStatusTypeRespVO>> getBusinessStatusTypeList() {
|
||||
CrmBusinessStatusTypeQueryVO queryVO = new CrmBusinessStatusTypeQueryVO();
|
||||
queryVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
List<CrmBusinessStatusTypeDO> list = businessStatusTypeService.selectList(queryVO);
|
||||
return success(BeanUtils.toBean(list, CrmBusinessStatusTypeRespVO.class));
|
||||
}
|
||||
|
||||
// TODO @ljlleo 这个接口,是不是可以和 getBusinessStatusTypeList 合并成一个?
|
||||
@GetMapping("/get-status-list")
|
||||
@Operation(summary = "获得商机状态列表")
|
||||
@PreAuthorize("@ss.hasPermission('crm:business-status:query')")
|
||||
public CommonResult<List<CrmBusinessStatusRespVO>> getBusinessStatusListByTypeId(@RequestParam("typeId") Long typeId) {
|
||||
CrmBusinessStatusQueryVO queryVO = new CrmBusinessStatusQueryVO();
|
||||
queryVO.setTypeId(typeId);
|
||||
List<CrmBusinessStatusDO> list = businessStatusService.selectList(queryVO);
|
||||
return success(CrmBusinessStatusConvert.INSTANCE.convertList(list));
|
||||
}
|
||||
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 商机 Excel VO
|
||||
*
|
||||
* @author ljlleo
|
||||
*/
|
||||
@Data
|
||||
public class CrmBusinessExcelVO {
|
||||
|
||||
@ExcelProperty("主键")
|
||||
private Long id;
|
||||
|
||||
@ExcelProperty("商机名称")
|
||||
private String name;
|
||||
|
||||
@ExcelProperty("商机状态类型编号")
|
||||
private Long statusTypeId;
|
||||
|
||||
@ExcelProperty("商机状态编号")
|
||||
private Long statusId;
|
||||
|
||||
@ExcelProperty("下次联系时间")
|
||||
private LocalDateTime contactNextTime;
|
||||
|
||||
@ExcelProperty("客户编号")
|
||||
private Long customerId;
|
||||
|
||||
@ExcelProperty("预计成交日期")
|
||||
private LocalDateTime dealTime;
|
||||
|
||||
@ExcelProperty("商机金额")
|
||||
private BigDecimal price;
|
||||
|
||||
@ExcelProperty("整单折扣")
|
||||
private BigDecimal discountPercent;
|
||||
|
||||
@ExcelProperty("产品总金额")
|
||||
private BigDecimal productPrice;
|
||||
|
||||
@ExcelProperty("备注")
|
||||
private String remark;
|
||||
|
||||
@ExcelProperty("负责人的用户编号")
|
||||
private Long ownerUserId;
|
||||
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@ExcelProperty("只读权限的用户编号数组")
|
||||
private Set<Long> roUserIds;
|
||||
|
||||
@ExcelProperty("读写权限的用户编号数组")
|
||||
private Set<Long> rwUserIds;
|
||||
|
||||
@ExcelProperty("1赢单2输单3无效")
|
||||
private Integer endStatus;
|
||||
|
||||
@ExcelProperty("结束时的备注")
|
||||
private String endRemark;
|
||||
|
||||
@ExcelProperty("最后跟进时间")
|
||||
private LocalDateTime contactLastTime;
|
||||
|
||||
@ExcelProperty("跟进状态")
|
||||
private Integer followUpStatus;
|
||||
|
||||
}
|
@ -1,69 +1,144 @@
|
||||
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 商机 Response VO")
|
||||
@Schema(description = "管理后台 - CRM 商机 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class CrmBusinessRespVO {
|
||||
|
||||
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129")
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129")
|
||||
@ExcelProperty("编号")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "商机名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
|
||||
@NotNull(message = "商机名称不能为空")
|
||||
@ExcelProperty("商机名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "商机状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714")
|
||||
@NotNull(message = "商机状态类型不能为空")
|
||||
private Long statusTypeId;
|
||||
|
||||
@Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
|
||||
@NotNull(message = "商机状态不能为空")
|
||||
private Long statusId;
|
||||
|
||||
@Schema(description = "下次联系时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime contactNextTime;
|
||||
|
||||
@Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10299")
|
||||
@NotNull(message = "客户不能为空")
|
||||
private Long customerId;
|
||||
|
||||
@Schema(description = "预计成交日期")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime dealTime;
|
||||
|
||||
@Schema(description = "商机金额", example = "12371")
|
||||
private Integer price;
|
||||
|
||||
// TODO @ljileo:折扣使用 Integer 类型,存储时,默认 * 100;展示的时候,前端需要 / 100;避免精度丢失问题
|
||||
@Schema(description = "整单折扣")
|
||||
private Integer discountPercent;
|
||||
|
||||
@Schema(description = "产品总金额", example = "12025")
|
||||
private BigDecimal productPrice;
|
||||
|
||||
@Schema(description = "备注", example = "随便")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
|
||||
@ExcelProperty("客户名称")
|
||||
private String customerName;
|
||||
|
||||
@Schema(description = "状态类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "进行中")
|
||||
@Schema(description = "跟进状态", requiredMode = Schema.RequiredMode.REQUIRED, example ="true")
|
||||
@ExcelProperty("跟进状态")
|
||||
private Boolean followUpStatus;
|
||||
|
||||
@Schema(description = "最后跟进时间")
|
||||
@ExcelProperty("最后跟进时间")
|
||||
private LocalDateTime contactLastTime;
|
||||
|
||||
@Schema(description = "下次联系时间")
|
||||
@ExcelProperty("下次联系时间")
|
||||
private LocalDateTime contactNextTime;
|
||||
|
||||
@Schema(description = "负责人的用户编号", example = "25682")
|
||||
@ExcelProperty("负责人的用户编号")
|
||||
private Long ownerUserId;
|
||||
@Schema(description = "负责人名字", example = "25682")
|
||||
@ExcelProperty("负责人名字")
|
||||
private String ownerUserName;
|
||||
@Schema(description = "负责人部门")
|
||||
@ExcelProperty("负责人部门")
|
||||
private String ownerUserDeptName;
|
||||
|
||||
@Schema(description = "商机状态组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714")
|
||||
private Long statusTypeId;
|
||||
@Schema(description = "商机状组名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "进行中")
|
||||
@ExcelProperty("商机状态组")
|
||||
private String statusTypeName;
|
||||
|
||||
@Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
|
||||
private Long statusId;
|
||||
@Schema(description = "状态名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "跟进中")
|
||||
@ExcelProperty("商机状态")
|
||||
private String statusName;
|
||||
|
||||
@Schema
|
||||
@ExcelProperty("1赢单2输单3无效")
|
||||
private Integer endStatus;
|
||||
|
||||
@ExcelProperty("结束时的备注")
|
||||
private String endRemark;
|
||||
|
||||
@Schema(description = "预计成交日期")
|
||||
@ExcelProperty("预计成交日期")
|
||||
private LocalDateTime dealTime;
|
||||
|
||||
@Schema(description = "产品总金额", example = "12025")
|
||||
@ExcelProperty("产品总金额")
|
||||
private BigDecimal totalProductPrice;
|
||||
|
||||
@Schema(description = "整单折扣")
|
||||
@ExcelProperty("整单折扣")
|
||||
private BigDecimal discountPercent;
|
||||
|
||||
@Schema(description = "商机总金额", example = "12371")
|
||||
@ExcelProperty("商机总金额")
|
||||
private BigDecimal totalPrice;
|
||||
|
||||
@Schema(description = "备注", example = "随便")
|
||||
@ExcelProperty("备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "创建人", example = "1024")
|
||||
@ExcelProperty("创建人")
|
||||
private String creator;
|
||||
@Schema(description = "创建人名字", example = "芋道源码")
|
||||
@ExcelProperty("创建人名字")
|
||||
private String creatorName;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("更新时间")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
@Schema(description = "产品列表")
|
||||
private List<Product> products;
|
||||
|
||||
@Schema(description = "产品列表")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Product {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "888")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529")
|
||||
private Long productId;
|
||||
@Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
|
||||
private String productName;
|
||||
@Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529")
|
||||
private String productNo;
|
||||
@Schema(description = "产品单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
|
||||
private Integer productUnit;
|
||||
|
||||
@Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00")
|
||||
private BigDecimal productPrice;
|
||||
|
||||
@Schema(description = "合同价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00")
|
||||
private BigDecimal businessPrice;
|
||||
|
||||
@Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911")
|
||||
private Integer count;
|
||||
|
||||
@Schema(description = "总计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00")
|
||||
private BigDecimal totalPrice;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.crm.enums.business.CrmBizEndStatus;
|
||||
import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerParseFunction;
|
||||
import cn.iocoder.yudao.module.crm.framework.operatelog.core.SysAdminUserParseFunction;
|
||||
import com.mzt.logapi.starter.annotation.DiffLogField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
@ -29,74 +28,68 @@ public class CrmBusinessSaveReqVO {
|
||||
@NotNull(message = "商机名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "商机状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714")
|
||||
@DiffLogField(name = "商机状态")
|
||||
@NotNull(message = "商机状态类型不能为空")
|
||||
private Long statusTypeId;
|
||||
|
||||
@Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
|
||||
@DiffLogField(name = "商机状态")
|
||||
@NotNull(message = "商机状态不能为空")
|
||||
private Long statusId;
|
||||
@Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10299")
|
||||
@DiffLogField(name = "客户", function = CrmCustomerParseFunction.NAME)
|
||||
@NotNull(message = "客户不能为空")
|
||||
private Long customerId;
|
||||
|
||||
@Schema(description = "下次联系时间")
|
||||
@DiffLogField(name = "下次联系时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime contactNextTime;
|
||||
|
||||
@Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10299")
|
||||
@DiffLogField(name = "客户", function = CrmCustomerParseFunction.NAME)
|
||||
@NotNull(message = "客户不能为空")
|
||||
private Long customerId;
|
||||
@Schema(description = "负责人用户编号", example = "14334")
|
||||
@NotNull(message = "负责人不能为空")
|
||||
@DiffLogField(name = "负责人", function = SysAdminUserParseFunction.NAME)
|
||||
private Long ownerUserId;
|
||||
|
||||
@Schema(description = "商机状态组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714")
|
||||
@DiffLogField(name = "商机状态组")
|
||||
@NotNull(message = "商机状态组不能为空")
|
||||
private Long statusTypeId;
|
||||
|
||||
@Schema(description = "预计成交日期")
|
||||
@DiffLogField(name = "预计成交日期")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime dealTime;
|
||||
|
||||
@Schema(description = "商机金额", example = "12371")
|
||||
@DiffLogField(name = "商机金额")
|
||||
private Integer price;
|
||||
|
||||
@Schema(description = "整单折扣")
|
||||
@DiffLogField(name = "整单折扣")
|
||||
private Integer discountPercent;
|
||||
|
||||
@Schema(description = "产品总金额", example = "12025")
|
||||
@DiffLogField(name = "产品总金额")
|
||||
private BigDecimal productPrice;
|
||||
@NotNull(message = "整单折扣不能为空")
|
||||
private BigDecimal discountPercent;
|
||||
|
||||
@Schema(description = "备注", example = "随便")
|
||||
@DiffLogField(name = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "结束状态", example = "1")
|
||||
@InEnum(CrmBizEndStatus.class)
|
||||
private Integer endStatus;
|
||||
|
||||
@Schema(description = "联系人编号", example = "110")
|
||||
private Long contactId; // 使用场景,在【联系人详情】添加商机时,如果需要关联两者,需要传递 contactId 字段
|
||||
|
||||
@Schema(description = "产品列表")
|
||||
private List<Item> items;
|
||||
private List<Product> products;
|
||||
|
||||
@Schema(description = "产品列表")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Item {
|
||||
public static class Product {
|
||||
|
||||
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529")
|
||||
@NotNull(message = "产品编号不能为空")
|
||||
private Long id;
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00")
|
||||
@NotNull(message = "产品单价不能为空")
|
||||
private BigDecimal productPrice;
|
||||
|
||||
@Schema(description = "合同价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "123.00")
|
||||
@NotNull(message = "合同价格不能为空")
|
||||
private BigDecimal businessPrice;
|
||||
|
||||
@Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911")
|
||||
@NotNull(message = "产品数量不能为空")
|
||||
private Integer count;
|
||||
|
||||
@Schema(description = "产品折扣")
|
||||
private Integer discountPercent;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,15 +0,0 @@
|
||||
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status;
|
||||
|
||||
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;
|
||||
|
||||
@Schema(description = "管理后台 - 商机状态分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class CrmBusinessStatusPageReqVO extends PageParam {
|
||||
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Schema(description = "管理后台 - 商机状态 Query VO")
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class CrmBusinessStatusQueryVO {
|
||||
|
||||
@Schema(description = "主键集合")
|
||||
private Collection<Long> idList;
|
||||
|
||||
@Schema(description = "状态类型编号")
|
||||
private Long typeId;
|
||||
}
|
@ -1,33 +1,51 @@
|
||||
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 商机状态 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class CrmBusinessStatusRespVO {
|
||||
|
||||
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "23899")
|
||||
@ExcelProperty("主键")
|
||||
@Schema(description = "状态组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2934")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7139")
|
||||
@ExcelProperty("状态类型编号")
|
||||
private Long typeId;
|
||||
|
||||
@Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
|
||||
@ExcelProperty("状态名")
|
||||
@Schema(description = "状态组名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "赢单率")
|
||||
@ExcelProperty("赢单率")
|
||||
private String percent;
|
||||
@Schema(description = "使用的部门编号", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<Long> deptIds;
|
||||
@Schema(description = "使用的部门名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<String> deptNames;
|
||||
|
||||
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@ExcelProperty("排序")
|
||||
private Integer sort;
|
||||
@Schema(description = "创建人", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String creator;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "状态集合", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<Status> statuses;
|
||||
|
||||
@Data
|
||||
public static class Status {
|
||||
|
||||
@Schema(description = "状态编号", example = "23899")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "赢单率", requiredMode = Schema.RequiredMode.REQUIRED, example = "50")
|
||||
private BigDecimal percent;
|
||||
|
||||
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer sort;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,32 +1,50 @@
|
||||
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.status;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 商机状态新增/修改 Request VO")
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 商机状态组新增/修改 Request VO")
|
||||
@Data
|
||||
public class CrmBusinessStatusSaveReqVO {
|
||||
|
||||
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "23899")
|
||||
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "2934")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7139")
|
||||
@NotNull(message = "状态类型编号不能为空")
|
||||
private Long typeId;
|
||||
|
||||
@Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
|
||||
@NotEmpty(message = "状态名不能为空")
|
||||
@Schema(description = "状态类型名", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
|
||||
@NotEmpty(message = "状态类型名不能为空")
|
||||
private String name;
|
||||
|
||||
// TODO @lzxhqs::percent 应该是 Integer;
|
||||
@Schema(description = "赢单率")
|
||||
private String percent;
|
||||
@Schema(description = "使用的部门编号")
|
||||
private List<Long> deptIds;
|
||||
|
||||
// TODO @lzxhqs:这个是不是不用前端新增和修改的时候传递,交给顺序计算出来,存储起来就好了;
|
||||
@Schema(description = "排序")
|
||||
private Integer sort;
|
||||
@Schema(description = "商机状态集合", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "商机状态集合不能为空")
|
||||
@Valid
|
||||
private List<Status> statuses;
|
||||
|
||||
@Data
|
||||
public static class Status {
|
||||
|
||||
@Schema(description = "状态编号", example = "23899")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
|
||||
@NotEmpty(message = "状态名不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "赢单率", requiredMode = Schema.RequiredMode.REQUIRED, example = "50")
|
||||
@NotNull(message = "赢单率不能为空")
|
||||
private BigDecimal percent;
|
||||
|
||||
@Schema(description = "排序", hidden = true, example = "1")
|
||||
private Integer sort;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,15 +0,0 @@
|
||||
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.type;
|
||||
|
||||
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;
|
||||
|
||||
@Schema(description = "管理后台 - 商机状态类型分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class CrmBusinessStatusTypePageReqVO extends PageParam {
|
||||
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.type;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Schema(description = "管理后台 - 商机状态类型 Query VO")
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class CrmBusinessStatusTypeQueryVO {
|
||||
|
||||
@Schema(description = "主键集合")
|
||||
private Collection<Long> idList;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private Integer status;
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.type;
|
||||
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 商机状态类型 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class CrmBusinessStatusTypeRespVO {
|
||||
|
||||
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "2934")
|
||||
@ExcelProperty("主键")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "状态类型名", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
|
||||
@ExcelProperty("状态类型名")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "使用的部门编号", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("使用的部门编号")
|
||||
private List<Long> deptIds;
|
||||
@Schema(description = "使用的部门名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("使用的部门名称")
|
||||
private List<String> deptNames;
|
||||
|
||||
@Schema(description = "创建人", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建人")
|
||||
private String creator;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
// TODO @ljlleo 字段后缀改成 statuses,保持和 deptIds 风格一致;CrmBusinessStatusDO 改成 VO 哈;一般不使用 do 直接返回
|
||||
@Schema(description = "状态集合", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<CrmBusinessStatusDO> statusList;
|
||||
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.type;
|
||||
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO;
|
||||
import com.google.common.collect.Lists;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 商机状态类型新增/修改 Request VO")
|
||||
@Data
|
||||
public class CrmBusinessStatusTypeSaveReqVO {
|
||||
|
||||
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "2934")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "状态类型名", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
|
||||
@NotEmpty(message = "状态类型名不能为空")
|
||||
private String name;
|
||||
|
||||
// TODO @lzxhqs: VO 里面,我们不使用默认值哈。这里 Lists.newArrayList() 看看怎么去掉。上面 deptIds 也是类似噢
|
||||
@Schema(description = "使用的部门编号", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<Long> deptIds = Lists.newArrayList();
|
||||
|
||||
@Schema(description = "商机状态集合", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<CrmBusinessStatusSaveReqVO> statusList;
|
||||
|
||||
}
|
@ -179,7 +179,7 @@ public class CrmContractController {
|
||||
if (contractList.size() == 1) {
|
||||
List<CrmContractProductDO> contractProductList = contractService.getContractProductListByContractId(contractList.get(0).getId());
|
||||
contractProductMap = convertMap(contractProductList, CrmContractProductDO::getProductId);
|
||||
productList = productService.getProductListByIds(convertSet(contractProductList, CrmContractProductDO::getProductId));
|
||||
productList = productService.getProductList(convertSet(contractProductList, CrmContractProductDO::getProductId));
|
||||
}
|
||||
return CrmContractConvert.INSTANCE.convertList(contractList, userMap, customerList, contactMap, businessMap, contractProductMap, productList);
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
package cn.iocoder.yudao.module.crm.controller.admin.product;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
||||
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.product.vo.product.CrmProductPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductSaveReqVO;
|
||||
import cn.iocoder.yudao.module.crm.convert.product.CrmProductConvert;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
|
||||
import cn.iocoder.yudao.module.crm.service.product.CrmProductCategoryService;
|
||||
@ -34,10 +35,9 @@ import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
@Tag(name = "管理后台 - CRM 产品")
|
||||
@RestController
|
||||
@ -49,6 +49,7 @@ public class CrmProductController {
|
||||
private CrmProductService productService;
|
||||
@Resource
|
||||
private CrmProductCategoryService productCategoryService;
|
||||
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
|
||||
@ -82,21 +83,30 @@ public class CrmProductController {
|
||||
@PreAuthorize("@ss.hasPermission('crm:product:query')")
|
||||
public CommonResult<CrmProductRespVO> getProduct(@RequestParam("id") Long id) {
|
||||
CrmProductDO product = productService.getProduct(id);
|
||||
return success(buildProductDetail(product));
|
||||
}
|
||||
|
||||
private CrmProductRespVO buildProductDetail(CrmProductDO product) {
|
||||
if (product == null) {
|
||||
return success(null);
|
||||
return null;
|
||||
}
|
||||
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
|
||||
SetUtils.asSet(Long.valueOf(product.getCreator()), product.getOwnerUserId()));
|
||||
CrmProductCategoryDO category = productCategoryService.getProductCategory(product.getCategoryId());
|
||||
return success(CrmProductConvert.INSTANCE.convert(product, userMap, category));
|
||||
return buildProductDetailList(singletonList(product)).get(0);
|
||||
}
|
||||
|
||||
@GetMapping("/simple-list")
|
||||
@Operation(summary = "获得产品精简列表", description = "只包含被开启的产品,主要用于前端的下拉选项")
|
||||
public CommonResult<List<CrmProductRespVO>> getProductSimpleList() {
|
||||
List<CrmProductDO> list = productService.getProductListByStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
return success(convertList(list, product -> new CrmProductRespVO().setId(product.getId()).setName(product.getName())
|
||||
.setUnit(product.getUnit()).setNo(product.getNo()).setPrice(product.getPrice())));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得产品分页")
|
||||
@PreAuthorize("@ss.hasPermission('crm:product:query')")
|
||||
public CommonResult<PageResult<CrmProductRespVO>> getProductPage(@Valid CrmProductPageReqVO pageVO) {
|
||||
PageResult<CrmProductDO> pageResult = productService.getProductPage(pageVO, getLoginUserId());
|
||||
return success(new PageResult<>(getProductDetailList(pageResult.getList()), pageResult.getTotal()));
|
||||
PageResult<CrmProductDO> pageResult = productService.getProductPage(pageVO);
|
||||
return success(new PageResult<>(buildProductDetailList(pageResult.getList()), pageResult.getTotal()));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@ -106,21 +116,30 @@ public class CrmProductController {
|
||||
public void exportProductExcel(@Valid CrmProductPageReqVO exportReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<CrmProductDO> list = productService.getProductPage(exportReqVO, getLoginUserId()).getList();
|
||||
List<CrmProductDO> list = productService.getProductPage(exportReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "产品.xls", "数据", CrmProductRespVO.class,
|
||||
getProductDetailList(list));
|
||||
buildProductDetailList(list));
|
||||
}
|
||||
|
||||
private List<CrmProductRespVO> getProductDetailList(List<CrmProductDO> list) {
|
||||
private List<CrmProductRespVO> buildProductDetailList(List<CrmProductDO> list) {
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// 1.1 获得用户信息
|
||||
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
|
||||
convertSetByFlatMap(list, user -> Stream.of(Long.valueOf(user.getCreator()), user.getOwnerUserId())));
|
||||
List<CrmProductCategoryDO> productCategoryList = productCategoryService.getProductCategoryList(
|
||||
// 1.2 获得分类信息
|
||||
Map<Long, CrmProductCategoryDO> categoryMap = productCategoryService.getProductCategoryMap(
|
||||
convertSet(list, CrmProductDO::getCategoryId));
|
||||
return CrmProductConvert.INSTANCE.convertList(list, userMap, productCategoryList);
|
||||
// 2. 拼接数据
|
||||
return BeanUtils.toBean(list, CrmProductRespVO.class, productVO -> {
|
||||
// 2.1 设置用户信息
|
||||
MapUtils.findAndThen(userMap, productVO.getOwnerUserId(), user -> productVO.setOwnerUserName(user.getNickname()));
|
||||
MapUtils.findAndThen(userMap, Long.valueOf(productVO.getCreator()), user -> productVO.setCreatorName(user.getNickname()));
|
||||
// 2.2 设置分类名称
|
||||
MapUtils.findAndThen(categoryMap, productVO.getCategoryId(), category -> productVO.setCategoryName(category.getName()));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - CRM 产品 Response VO")
|
||||
@ -34,7 +35,7 @@ public class CrmProductRespVO {
|
||||
|
||||
@Schema(description = "价格, 单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911")
|
||||
@ExcelProperty("价格,单位:分")
|
||||
private Long price;
|
||||
private BigDecimal price;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "上架")
|
||||
@ExcelProperty(value = "单位", converter = DictConvert.class)
|
||||
|
@ -7,6 +7,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Schema(description = "管理后台 - CRM 产品创建/修改 Request VO")
|
||||
@Data
|
||||
public class CrmProductSaveReqVO {
|
||||
@ -28,10 +30,10 @@ public class CrmProductSaveReqVO {
|
||||
@DiffLogField(name = "单位", function = CrmProductUnitParseFunction.NAME)
|
||||
private Integer unit;
|
||||
|
||||
@Schema(description = "价格, 单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911")
|
||||
@Schema(description = "价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911")
|
||||
@NotNull(message = "价格不能为空")
|
||||
@DiffLogField(name = "价格")
|
||||
private Long price;
|
||||
private BigDecimal price;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "上架")
|
||||
@NotNull(message = "状态不能为空")
|
||||
|
@ -1,14 +1,8 @@
|
||||
package cn.iocoder.yudao.module.crm.convert.business;
|
||||
|
||||
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.business.vo.business.CrmBusinessRespVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
|
||||
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
|
||||
import org.mapstruct.Mapper;
|
||||
@ -16,9 +10,6 @@ import org.mapstruct.Mapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
|
||||
/**
|
||||
* 商机 Convert
|
||||
@ -33,20 +24,6 @@ public interface CrmBusinessConvert {
|
||||
@Mapping(target = "bizId", source = "reqVO.id")
|
||||
CrmPermissionTransferReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId);
|
||||
|
||||
default PageResult<CrmBusinessRespVO> convertPage(PageResult<CrmBusinessDO> pageResult, List<CrmCustomerDO> customerList,
|
||||
List<CrmBusinessStatusTypeDO> statusTypeList, List<CrmBusinessStatusDO> statusList) {
|
||||
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);
|
||||
voPageResult.getList().forEach(type -> type
|
||||
.setCustomerName(customerMap.get(type.getCustomerId()))
|
||||
.setStatusTypeName(statusTypeMap.get(type.getStatusTypeId()))
|
||||
.setStatusName(statusMap.get(type.getStatusId())));
|
||||
return voPageResult;
|
||||
}
|
||||
|
||||
@Mapping(target = "id", source = "reqBO.bizId")
|
||||
CrmBusinessDO convert(CrmUpdateFollowUpReqBO reqBO);
|
||||
|
||||
|
@ -1,25 +0,0 @@
|
||||
package cn.iocoder.yudao.module.crm.convert.business;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusRespVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商机状态 Convert
|
||||
*
|
||||
* @author ljlleo
|
||||
*/
|
||||
@Mapper
|
||||
public interface CrmBusinessStatusConvert {
|
||||
|
||||
CrmBusinessStatusConvert INSTANCE = Mappers.getMapper(CrmBusinessStatusConvert.class);
|
||||
|
||||
List<CrmBusinessStatusRespVO> convertList(List<CrmBusinessStatusDO> list);
|
||||
|
||||
PageResult<CrmBusinessStatusRespVO> convertPage(PageResult<CrmBusinessStatusDO> page);
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
package cn.iocoder.yudao.module.crm.convert.business;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeRespVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
|
||||
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
|
||||
// TODO @lzxhqs:看看是不是用 BeanUtils 替代了
|
||||
/**
|
||||
* 商机状态类型 Convert
|
||||
*
|
||||
* @author ljlleo
|
||||
*/
|
||||
@Mapper
|
||||
public interface CrmBusinessStatusTypeConvert {
|
||||
|
||||
CrmBusinessStatusTypeConvert INSTANCE = Mappers.getMapper(CrmBusinessStatusTypeConvert.class);
|
||||
|
||||
CrmBusinessStatusTypeRespVO convert(CrmBusinessStatusTypeDO bean);
|
||||
|
||||
PageResult<CrmBusinessStatusTypeRespVO> convertPage(PageResult<CrmBusinessStatusTypeDO> page);
|
||||
|
||||
default PageResult<CrmBusinessStatusTypeRespVO> convertPage(PageResult<CrmBusinessStatusTypeDO> page, List<DeptRespDTO> deptList) {
|
||||
PageResult<CrmBusinessStatusTypeRespVO> pageResult = convertPage(page);
|
||||
// 拼接关联字段
|
||||
Map<Long, String> deptMap = convertMap(deptList, DeptRespDTO::getId, DeptRespDTO::getName);
|
||||
pageResult.getList().forEach(type -> type.setDeptNames(convertList(type.getDeptIds(), deptMap::get)));
|
||||
return pageResult;
|
||||
}
|
||||
|
||||
default CrmBusinessStatusTypeRespVO convert(CrmBusinessStatusTypeDO bean, List<CrmBusinessStatusDO> statusList) {
|
||||
return convert(bean).setStatusList(statusList);
|
||||
}
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package cn.iocoder.yudao.module.crm.convert.product;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductRespVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
|
||||
/**
|
||||
* 产品 Convert
|
||||
*
|
||||
* @author ZanGe丶
|
||||
*/
|
||||
@Mapper
|
||||
public interface CrmProductConvert {
|
||||
|
||||
CrmProductConvert INSTANCE = Mappers.getMapper(CrmProductConvert.class);
|
||||
|
||||
default List<CrmProductRespVO> convertList(List<CrmProductDO> list,
|
||||
Map<Long, AdminUserRespDTO> userMap,
|
||||
List<CrmProductCategoryDO> categoryList) {
|
||||
Map<Long, CrmProductCategoryDO> categoryMap = convertMap(categoryList, CrmProductCategoryDO::getId);
|
||||
return CollectionUtils.convertList(list,
|
||||
product -> convert(product, userMap, categoryMap.get(product.getCategoryId())));
|
||||
}
|
||||
|
||||
default CrmProductRespVO convert(CrmProductDO product,
|
||||
Map<Long, AdminUserRespDTO> userMap, CrmProductCategoryDO category) {
|
||||
CrmProductRespVO productVO = BeanUtils.toBean(product, CrmProductRespVO.class);
|
||||
Optional.ofNullable(category).ifPresent(c -> productVO.setCategoryName(c.getName()));
|
||||
MapUtils.findAndThen(userMap, productVO.getOwnerUserId(), user -> productVO.setOwnerUserName(user.getNickname()));
|
||||
MapUtils.findAndThen(userMap, Long.valueOf(productVO.getCreator()), user -> productVO.setCreatorName(user.getNickname()));
|
||||
return productVO;
|
||||
}
|
||||
|
||||
}
|
@ -8,10 +8,11 @@ import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 商机 DO
|
||||
* CRM 商机 DO
|
||||
*
|
||||
* @author ljlleo
|
||||
*/
|
||||
@ -26,7 +27,7 @@ import java.time.LocalDateTime;
|
||||
public class CrmBusinessDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
* 编号
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
@ -35,7 +36,34 @@ public class CrmBusinessDO extends BaseDO {
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 商机状态类型编号
|
||||
* 客户编号
|
||||
*
|
||||
* 关联 {@link CrmCustomerDO#getId()}
|
||||
*/
|
||||
private Long customerId;
|
||||
|
||||
/**
|
||||
* 跟进状态
|
||||
*/
|
||||
private Boolean followUpStatus;
|
||||
/**
|
||||
* 最后跟进时间
|
||||
*/
|
||||
private LocalDateTime contactLastTime;
|
||||
/**
|
||||
* 下次联系时间
|
||||
*/
|
||||
private LocalDateTime contactNextTime;
|
||||
|
||||
/**
|
||||
* 负责人的用户编号
|
||||
*
|
||||
* 关联 AdminUserDO 的 id 字段
|
||||
*/
|
||||
private Long ownerUserId;
|
||||
|
||||
/**
|
||||
* 商机状态组编号
|
||||
*
|
||||
* 关联 {@link CrmBusinessStatusTypeDO#getId()}
|
||||
*/
|
||||
@ -46,39 +74,6 @@ public class CrmBusinessDO extends BaseDO {
|
||||
* 关联 {@link CrmBusinessStatusDO#getId()}
|
||||
*/
|
||||
private Long statusId;
|
||||
/**
|
||||
* 下次联系时间
|
||||
*/
|
||||
private LocalDateTime contactNextTime;
|
||||
/**
|
||||
* 客户编号
|
||||
*
|
||||
* TODO @ljileo:这个字段,后续要写下关联的实体哈
|
||||
* 关联 {@link CrmCustomerDO#getId()}
|
||||
*/
|
||||
private Long customerId;
|
||||
/**
|
||||
* 预计成交日期
|
||||
*/
|
||||
private LocalDateTime dealTime;
|
||||
/**
|
||||
* 商机金额
|
||||
*
|
||||
*/
|
||||
private Integer price;
|
||||
/**
|
||||
* 整单折扣
|
||||
*
|
||||
*/
|
||||
private Integer discountPercent;
|
||||
/**
|
||||
* 产品总金额,单位:分
|
||||
*/
|
||||
private Integer productPrice;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
/**
|
||||
* 结束状态
|
||||
*
|
||||
@ -89,20 +84,28 @@ public class CrmBusinessDO extends BaseDO {
|
||||
* 结束时的备注
|
||||
*/
|
||||
private String endRemark;
|
||||
/**
|
||||
* 最后跟进时间
|
||||
*/
|
||||
private LocalDateTime contactLastTime;
|
||||
/**
|
||||
* 跟进状态
|
||||
*/
|
||||
private Boolean followUpStatus;
|
||||
|
||||
/**
|
||||
* 负责人的用户编号
|
||||
*
|
||||
* 关联 AdminUserDO 的 id 字段
|
||||
* 预计成交日期
|
||||
*/
|
||||
private Long ownerUserId;
|
||||
private LocalDateTime dealTime;
|
||||
/**
|
||||
* 产品总金额,单位:元
|
||||
*
|
||||
* productPrice = ∑({@link CrmBusinessProductDO#getTotalPrice()})
|
||||
*/
|
||||
private BigDecimal totalProductPrice;
|
||||
/**
|
||||
* 整单折扣,百分比
|
||||
*/
|
||||
private BigDecimal discountPercent;
|
||||
/**
|
||||
* 商机总金额,单位:元
|
||||
*/
|
||||
private BigDecimal totalPrice;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
|
@ -7,9 +7,13 @@ import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 商机产品关联表 DO
|
||||
*
|
||||
* CrmBusinessDO : CrmBusinessProductDO = 1 : N
|
||||
*
|
||||
* @author lzxhqs
|
||||
*/
|
||||
@TableName("crm_business_product")
|
||||
@ -40,24 +44,24 @@ public class CrmBusinessProductDO extends BaseDO {
|
||||
*/
|
||||
private Long productId;
|
||||
/**
|
||||
* 产品单价
|
||||
* 产品单价,单位:元
|
||||
*
|
||||
* 冗余 {@link CrmProductDO#getPrice()}
|
||||
*/
|
||||
private Integer price;
|
||||
private BigDecimal productPrice;
|
||||
/**
|
||||
* 销售价格, 单位:分
|
||||
* 合同价格, 单位:元
|
||||
*/
|
||||
private Integer salesPrice;
|
||||
private BigDecimal businessPrice;
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
private Integer count;
|
||||
private BigDecimal count;
|
||||
/**
|
||||
* 折扣
|
||||
* 总计价格,单位:元
|
||||
*
|
||||
* totalPrice = businessPrice * count
|
||||
*/
|
||||
private Integer discountPercent;
|
||||
/**
|
||||
* 总计价格(折扣后价格)
|
||||
*/
|
||||
private Integer totalPrice;
|
||||
private BigDecimal totalPrice;
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package cn.iocoder.yudao.module.crm.dal.dataobject.business;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
@ -12,7 +11,7 @@ import lombok.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商机状态类型 DO
|
||||
* 商机状态组 DO
|
||||
*
|
||||
* @author ljlleo
|
||||
*/
|
||||
@ -35,17 +34,11 @@ public class CrmBusinessStatusTypeDO extends BaseDO {
|
||||
* 状态类型名
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 使用的部门编号
|
||||
*/
|
||||
@TableField(typeHandler = LongListTypeHandler.class)
|
||||
private List<Long> deptIds;
|
||||
/**
|
||||
* 开启状态
|
||||
*
|
||||
* TODO 改成 Integer,关联 CommonStatus
|
||||
* 枚举 {@link CommonStatusEnum}
|
||||
*/
|
||||
private Boolean status;
|
||||
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import lombok.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 线索 DO
|
||||
* CRM 线索 DO
|
||||
*
|
||||
* @author Wanwan
|
||||
*/
|
||||
|
@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* CRM 产品 DO
|
||||
*
|
||||
@ -43,9 +45,9 @@ public class CrmProductDO extends BaseDO {
|
||||
*/
|
||||
private Integer unit;
|
||||
/**
|
||||
* 价格,单位:分
|
||||
* 价格,单位:元
|
||||
*/
|
||||
private Integer price;
|
||||
private BigDecimal price;
|
||||
/**
|
||||
* 状态
|
||||
*
|
||||
|
@ -63,4 +63,8 @@ public interface CrmBusinessMapper extends BaseMapperX<CrmBusinessDO> {
|
||||
return selectJoinList(CrmBusinessDO.class, query);
|
||||
}
|
||||
|
||||
default Long selectCountByStatusTypeId(Long statusTypeId) {
|
||||
return selectCount(CrmBusinessDO::getStatusTypeId, statusTypeId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,6 @@
|
||||
package cn.iocoder.yudao.module.crm.dal.mysql.business;
|
||||
|
||||
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.business.vo.status.CrmBusinessStatusPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@ -18,20 +14,12 @@ import java.util.List;
|
||||
@Mapper
|
||||
public interface CrmBusinessStatusMapper extends BaseMapperX<CrmBusinessStatusDO> {
|
||||
|
||||
default PageResult<CrmBusinessStatusDO> selectPage(CrmBusinessStatusPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<CrmBusinessStatusDO>()
|
||||
.orderByDesc(CrmBusinessStatusDO::getId));
|
||||
}
|
||||
|
||||
default List<CrmBusinessStatusDO> selectList(CrmBusinessStatusQueryVO queryVO) {
|
||||
return selectList(new LambdaQueryWrapperX<CrmBusinessStatusDO>()
|
||||
.eqIfPresent(CrmBusinessStatusDO::getTypeId, queryVO.getTypeId())
|
||||
.inIfPresent(CrmBusinessStatusDO::getId, queryVO.getIdList())
|
||||
.orderByDesc(CrmBusinessStatusDO::getId));
|
||||
}
|
||||
|
||||
default int delete(Long typeId) {
|
||||
default int deleteByTypeId(Long typeId) {
|
||||
return delete(CrmBusinessStatusDO::getTypeId, typeId);
|
||||
}
|
||||
|
||||
default List<CrmBusinessStatusDO> selectListByTypeId(Long typeId) {
|
||||
return selectList(CrmBusinessStatusDO::getTypeId, typeId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,44 +1,27 @@
|
||||
package cn.iocoder.yudao.module.crm.dal.mysql.business;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
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.business.vo.type.CrmBusinessStatusTypePageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商机状态类型 Mapper
|
||||
* 商机状态组 Mapper
|
||||
*
|
||||
* @author ljlleo
|
||||
*/
|
||||
@Mapper
|
||||
public interface CrmBusinessStatusTypeMapper extends BaseMapperX<CrmBusinessStatusTypeDO> {
|
||||
|
||||
default PageResult<CrmBusinessStatusTypeDO> selectPage(CrmBusinessStatusTypePageReqVO reqVO) {
|
||||
default PageResult<CrmBusinessStatusTypeDO> selectPage(PageParam reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<CrmBusinessStatusTypeDO>()
|
||||
.orderByDesc(CrmBusinessStatusTypeDO::getId));
|
||||
}
|
||||
|
||||
default List<CrmBusinessStatusTypeDO> selectList(CrmBusinessStatusTypeQueryVO queryVO) {
|
||||
return selectList(new LambdaQueryWrapperX<CrmBusinessStatusTypeDO>()
|
||||
.eqIfPresent(CrmBusinessStatusTypeDO::getStatus, queryVO.getStatus())
|
||||
.inIfPresent(CrmBusinessStatusTypeDO::getId, queryVO.getIdList()));
|
||||
}
|
||||
|
||||
// TODO @lzxhqs:这个可以改成 selectByName。业务上基于在判断 id 匹配;这样更通用一些;mapper 尽量通用,不关注或者特别关联业务;
|
||||
/**
|
||||
* 根据ID和name查询
|
||||
*
|
||||
* @param id 商机状态类型id
|
||||
* @param name 状态类型名
|
||||
* @return result
|
||||
*/
|
||||
default CrmBusinessStatusTypeDO selectByIdAndName(Long id, String name) {
|
||||
return selectOne(CrmBusinessStatusTypeDO::getId, id, CrmBusinessStatusTypeDO::getName, name);
|
||||
default CrmBusinessStatusTypeDO selectByName(String name) {
|
||||
return selectOne(CrmBusinessStatusTypeDO::getName, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* 商机(销售机会)
|
||||
*/
|
||||
package cn.iocoder.yudao.module.crm.dal.mysql.business;
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* 联系人
|
||||
*/
|
||||
package cn.iocoder.yudao.module.crm.dal.mysql.contact;
|
@ -5,10 +5,10 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
|
||||
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* CRM 产品 Mapper
|
||||
*
|
||||
@ -17,21 +17,23 @@ import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper
|
||||
public interface CrmProductMapper extends BaseMapperX<CrmProductDO> {
|
||||
|
||||
default PageResult<CrmProductDO> selectPage(CrmProductPageReqVO reqVO, Long userId) {
|
||||
MPJLambdaWrapperX<CrmProductDO> query = new MPJLambdaWrapperX<>();
|
||||
// 拼接数据权限的查询条件
|
||||
CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_PRODUCT.getType(),
|
||||
CrmProductDO::getId, userId, null, Boolean.FALSE);
|
||||
// 拼接自身的查询条件
|
||||
query.selectAll(CrmProductDO.class)
|
||||
default PageResult<CrmProductDO> selectPage(CrmProductPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new MPJLambdaWrapperX<CrmProductDO>()
|
||||
.likeIfPresent(CrmProductDO::getName, reqVO.getName())
|
||||
.eqIfPresent(CrmProductDO::getStatus, reqVO.getStatus())
|
||||
.orderByDesc(CrmProductDO::getId);
|
||||
return selectJoinPage(reqVO, CrmProductDO.class, query);
|
||||
.orderByDesc(CrmProductDO::getId));
|
||||
}
|
||||
|
||||
default CrmProductDO selectByNo(String no) {
|
||||
return selectOne(CrmProductDO::getNo, no);
|
||||
}
|
||||
|
||||
default Long selectCountByCategoryId(Long categoryId) {
|
||||
return selectCount(CrmProductDO::getCategoryId, categoryId);
|
||||
}
|
||||
|
||||
default List<CrmProductDO> selectListByStatus(Integer status) {
|
||||
return selectList(CrmProductDO::getStatus, status);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusi
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
|
||||
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.contact.CrmContactDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||
import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO;
|
||||
@ -90,6 +91,14 @@ public interface CrmBusinessService {
|
||||
*/
|
||||
List<CrmBusinessDO> getBusinessList(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得指定商机编号的产品列表
|
||||
*
|
||||
* @param businessId 商机编号
|
||||
* @return 商机产品列表
|
||||
*/
|
||||
List<CrmBusinessProductDO> getBusinessProductListByBusinessId(Long businessId);
|
||||
|
||||
/**
|
||||
* 获得商机分页
|
||||
*
|
||||
@ -129,4 +138,12 @@ public interface CrmBusinessService {
|
||||
*/
|
||||
Long getBusinessCountByCustomerId(Long customerId);
|
||||
|
||||
/**
|
||||
* 获得使用指定商机状态组的商机数量
|
||||
*
|
||||
* @param statusTypeId 商机状态组编号
|
||||
* @return 数量
|
||||
*/
|
||||
Long getBusinessCountByStatusTypeId(Long statusTypeId);
|
||||
|
||||
}
|
||||
|
@ -2,9 +2,7 @@ package cn.iocoder.yudao.module.crm.service.business;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
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.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO;
|
||||
@ -14,7 +12,6 @@ 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.CrmBusinessProductDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
|
||||
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.enums.common.CrmBizTypeEnum;
|
||||
@ -22,11 +19,14 @@ 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.bo.CrmBusinessUpdateProductReqBO;
|
||||
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.contract.CrmContractService;
|
||||
import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
|
||||
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.bo.CrmPermissionCreateReqBO;
|
||||
import cn.iocoder.yudao.module.crm.service.product.CrmProductService;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import com.mzt.logapi.context.LogRecordContext;
|
||||
import com.mzt.logapi.service.impl.DiffParseFunction;
|
||||
import com.mzt.logapi.starter.annotation.LogRecord;
|
||||
@ -36,14 +36,14 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_CONTRACT_EXISTS;
|
||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
|
||||
|
||||
/**
|
||||
@ -60,41 +60,54 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||
@Resource
|
||||
private CrmBusinessProductMapper businessProductMapper;
|
||||
|
||||
@Resource
|
||||
private CrmBusinessStatusService businessStatusService;
|
||||
@Resource
|
||||
@Lazy // 延迟加载,避免循环依赖
|
||||
private CrmContractService contractService;
|
||||
@Resource
|
||||
private CrmCustomerService customerService;
|
||||
@Resource
|
||||
@Lazy // 延迟加载,避免循环依赖
|
||||
private CrmContactService contactService;
|
||||
@Resource
|
||||
private CrmPermissionService permissionService;
|
||||
@Resource
|
||||
private CrmContactBusinessService contactBusinessService;
|
||||
@Resource
|
||||
private CrmProductService productService;
|
||||
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_CREATE_SUB_TYPE, bizNo = "{{#business.id}}",
|
||||
success = CRM_BUSINESS_CREATE_SUCCESS)
|
||||
public Long createBusiness(CrmBusinessSaveReqVO createReqVO, Long userId) {
|
||||
createReqVO.setId(null);
|
||||
// 1. 插入商机
|
||||
// 1.1 校验产品项的有效性
|
||||
List<CrmBusinessProductDO> businessProducts = validateBusinessProducts(createReqVO.getProducts());
|
||||
// 1.2 校验关联字段
|
||||
validateBusinessForCreate(createReqVO);
|
||||
|
||||
// 2.1 插入商机
|
||||
CrmBusinessDO business = BeanUtils.toBean(createReqVO, CrmBusinessDO.class).setOwnerUserId(userId);
|
||||
business.setStatusId(businessStatusService.getBusinessStatusListByTypeId(createReqVO.getStatusTypeId()).get(0).getId()); // 默认状态
|
||||
calculateTotalPrice(business, businessProducts);
|
||||
businessMapper.insert(business);
|
||||
// 1.2 插入商机关联商品
|
||||
if (CollUtil.isNotEmpty(createReqVO.getItems())) { // 如果有的话
|
||||
List<CrmBusinessProductDO> productList = buildBusinessProductList(createReqVO.getItems(), business.getId());
|
||||
businessProductMapper.insertBatch(productList);
|
||||
// 更新合同商品总金额
|
||||
businessMapper.updateById(new CrmBusinessDO().setId(business.getId()).setProductPrice(
|
||||
getSumValue(productList, CrmBusinessProductDO::getTotalPrice, Integer::sum)));
|
||||
// 2.2 插入商机关联商品
|
||||
if (CollUtil.isNotEmpty(businessProducts)) {
|
||||
businessProducts.forEach(item -> item.setBusinessId(business.getId()));
|
||||
businessProductMapper.insertBatch(businessProducts);
|
||||
}
|
||||
// 在联系人的详情页,如果直接【新建商机】,则需要关联下。
|
||||
contactBusinessService.createContactBusiness(createReqVO.getContactId(), business.getId());
|
||||
// 2. 创建数据权限
|
||||
// 3. 创建数据权限
|
||||
// 设置当前操作的人为负责人
|
||||
permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())
|
||||
.setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
|
||||
|
||||
// 3. 记录操作日志上下文
|
||||
// 4. 记录操作日志上下文
|
||||
LogRecordContext.putVariable("business", business);
|
||||
return business.getId();
|
||||
}
|
||||
@ -105,15 +118,20 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||
success = CRM_BUSINESS_UPDATE_SUCCESS)
|
||||
@CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
|
||||
public void updateBusiness(CrmBusinessSaveReqVO updateReqVO) {
|
||||
// 1. 校验存在
|
||||
updateReqVO.setOwnerUserId(null).setStatusTypeId(null); // 不允许更新的字段
|
||||
// 1.1 校验存在
|
||||
CrmBusinessDO oldBusiness = validateBusinessExists(updateReqVO.getId());
|
||||
// 1.2 校验产品项的有效性
|
||||
List<CrmBusinessProductDO> businessProducts = validateBusinessProducts(updateReqVO.getProducts());
|
||||
// 1.3 校验关联字段
|
||||
validateBusinessForCreate(updateReqVO);
|
||||
|
||||
// 2.1 更新商机
|
||||
CrmBusinessDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessDO.class);
|
||||
calculateTotalPrice(updateObj, businessProducts);
|
||||
businessMapper.updateById(updateObj);
|
||||
// 2.2 更新商机关联商品
|
||||
List<CrmBusinessProductDO> productList = buildBusinessProductList(updateReqVO.getItems(), updateObj.getId());
|
||||
updateBusinessProduct(productList, updateObj.getId());
|
||||
updateBusinessProduct(updateObj.getId(), businessProducts);
|
||||
|
||||
// TODO @商机待定:如果状态发生变化,插入商机状态变更记录表
|
||||
// 3. 记录操作日志上下文
|
||||
@ -121,6 +139,56 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||
LogRecordContext.putVariable("businessName", oldBusiness.getName());
|
||||
}
|
||||
|
||||
private void updateBusinessProduct(Long id, List<CrmBusinessProductDO> newList) {
|
||||
List<CrmBusinessProductDO> oldList = businessProductMapper.selectListByBusinessId(id);
|
||||
List<List<CrmBusinessProductDO>> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录
|
||||
(oldVal, newVal) -> oldVal.getId().equals(newVal.getId()));
|
||||
if (CollUtil.isNotEmpty(diffList.get(0))) {
|
||||
diffList.get(0).forEach(o -> o.setBusinessId(id));
|
||||
businessProductMapper.insertBatch(diffList.get(0));
|
||||
}
|
||||
if (CollUtil.isNotEmpty(diffList.get(1))) {
|
||||
businessProductMapper.updateBatch(diffList.get(1));
|
||||
}
|
||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||
businessProductMapper.deleteBatchIds(convertSet(diffList.get(2), CrmBusinessProductDO::getId));
|
||||
}
|
||||
}
|
||||
|
||||
private void validateBusinessForCreate(CrmBusinessSaveReqVO saveReqVO) {
|
||||
// 校验商机状态
|
||||
if (saveReqVO.getStatusTypeId() != null) {
|
||||
businessStatusService.validateBusinessStatusType(saveReqVO.getStatusTypeId());
|
||||
}
|
||||
// 校验客户
|
||||
if (saveReqVO.getCustomerId() != null) {
|
||||
customerService.validateCustomer(saveReqVO.getCustomerId());
|
||||
}
|
||||
// 校验联系人
|
||||
if (saveReqVO.getContactId() != null) {
|
||||
contactService.validateContact(saveReqVO.getContactId());
|
||||
}
|
||||
// 校验负责人
|
||||
if (saveReqVO.getOwnerUserId() != null) {
|
||||
adminUserApi.validateUser(saveReqVO.getOwnerUserId());
|
||||
}
|
||||
}
|
||||
|
||||
private List<CrmBusinessProductDO> validateBusinessProducts(List<CrmBusinessSaveReqVO.Product> list) {
|
||||
// 1. 校验产品存在
|
||||
productService.validProductList(convertSet(list, CrmBusinessSaveReqVO.Product::getProductId));
|
||||
// 2. 转化为 CrmBusinessProductDO 列表
|
||||
return convertList(list, o -> BeanUtils.toBean(o, CrmBusinessProductDO.class, item -> {
|
||||
item.setTotalPrice(MoneyUtils.priceMultiply(item.getBusinessPrice(), item.getCount()));
|
||||
}));
|
||||
}
|
||||
|
||||
private void calculateTotalPrice(CrmBusinessDO business, List<CrmBusinessProductDO> businessProducts) {
|
||||
business.setTotalProductPrice(getSumValue(businessProducts, CrmBusinessProductDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO));
|
||||
BigDecimal discountPrice = MoneyUtils.priceMultiplyPercent(business.getTotalProductPrice(), business.getDiscountPercent());
|
||||
business.setTotalPrice(business.getTotalProductPrice().subtract(discountPrice));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBusinessFollowUpBatch(List<CrmUpdateFollowUpReqBO> updateFollowUpReqBOList) {
|
||||
businessMapper.updateBatch(CrmBusinessConvert.INSTANCE.convertList(updateFollowUpReqBOList));
|
||||
@ -146,43 +214,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||
LogRecordContext.putVariable("businessName", business.getName());
|
||||
}
|
||||
|
||||
private void updateBusinessProduct(List<CrmBusinessProductDO> newProductList, Long businessId) {
|
||||
List<CrmBusinessProductDO> oldProducts = businessProductMapper.selectListByBusinessId(businessId);
|
||||
List<List<CrmBusinessProductDO>> diffList = CollectionUtils.diffList(oldProducts, newProductList, (oldValue, newValue) -> {
|
||||
boolean condition = ObjectUtil.equal(oldValue.getProductId(), newValue.getProductId());
|
||||
if (condition) {
|
||||
newValue.setId(oldValue.getId()); // 更新需要原始编号
|
||||
}
|
||||
return condition;
|
||||
});
|
||||
if (CollUtil.isNotEmpty(diffList.get(0))) {
|
||||
businessProductMapper.insertBatch(diffList.get(0));
|
||||
}
|
||||
if (CollUtil.isNotEmpty(diffList.get(1))) {
|
||||
businessProductMapper.updateBatch(diffList.get(1));
|
||||
}
|
||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||
businessProductMapper.deleteBatchIds(convertSet(diffList.get(2), CrmBusinessProductDO::getId));
|
||||
}
|
||||
}
|
||||
|
||||
private List<CrmBusinessProductDO> buildBusinessProductList(List<CrmBusinessSaveReqVO.Item> productItems, Long businessId) {
|
||||
// 校验商品存在
|
||||
Set<Long> productIds = convertSet(productItems, CrmBusinessSaveReqVO.Item::getId);
|
||||
List<CrmProductDO> productList = productService.getProductList(productIds);
|
||||
if (CollUtil.isEmpty(productIds) || productList.size() != productIds.size()) {
|
||||
throw exception(PRODUCT_NOT_EXISTS);
|
||||
}
|
||||
Map<Long, CrmProductDO> productMap = convertMap(productList, CrmProductDO::getId);
|
||||
return convertList(productItems, productItem -> {
|
||||
CrmProductDO product = productMap.get(productItem.getId());
|
||||
return BeanUtils.toBean(product, CrmBusinessProductDO.class)
|
||||
.setId(null).setProductId(productItem.getId()).setBusinessId(businessId)
|
||||
.setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent())
|
||||
.setTotalPrice(MoneyUtils.calculator(product.getPrice(), productItem.getCount(), productItem.getDiscountPercent()));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除校验合同是关联合同
|
||||
*
|
||||
@ -225,10 +256,10 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||
|
||||
@Override
|
||||
public void updateBusinessProduct(CrmBusinessUpdateProductReqBO updateProductReqBO) {
|
||||
// 更新商机关联商品
|
||||
List<CrmBusinessProductDO> productList = buildBusinessProductList(
|
||||
BeanUtils.toBean(updateProductReqBO.getItems(), CrmBusinessSaveReqVO.Item.class), updateProductReqBO.getId());
|
||||
updateBusinessProduct(productList, updateProductReqBO.getId());
|
||||
// 更新商机关联商品 TODO yunai
|
||||
// List<CrmBusinessProductDO> productList = buildBusinessProductList(
|
||||
// BeanUtils.toBean(updateProductReqBO.getProductItems(), CrmBusinessSaveReqVO.Product.class), updateProductReqBO.getId());
|
||||
// updateBusinessProduct(productList, updateProductReqBO.getId());
|
||||
}
|
||||
|
||||
//======================= 查询相关 =======================
|
||||
@ -255,6 +286,11 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||
return businessMapper.selectBatchIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmBusinessProductDO> getBusinessProductListByBusinessId(Long businessId) {
|
||||
return businessProductMapper.selectListByBusinessId(businessId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<CrmBusinessDO> getBusinessPage(CrmBusinessPageReqVO pageReqVO, Long userId) {
|
||||
return businessMapper.selectPage(pageReqVO, userId);
|
||||
@ -285,4 +321,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||
return businessMapper.selectCount(CrmBusinessDO::getCustomerId, customerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getBusinessCountByStatusTypeId(Long statusTypeId) {
|
||||
return businessMapper.selectCountByStatusTypeId(statusTypeId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,15 +1,17 @@
|
||||
package cn.iocoder.yudao.module.crm.service.business;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
|
||||
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
|
||||
/**
|
||||
* 商机状态 Service 接口
|
||||
@ -38,33 +40,63 @@ public interface CrmBusinessStatusService {
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteBusinessStatus(Long id);
|
||||
void deleteBusinessStatusType(Long id);
|
||||
|
||||
/**
|
||||
* 获得商机状态
|
||||
* 获得商机状态组
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 商机状态
|
||||
* @return 商机状态组
|
||||
*/
|
||||
CrmBusinessStatusDO getBusinessStatus(Long id);
|
||||
CrmBusinessStatusTypeDO getBusinessStatusType(Long id);
|
||||
|
||||
/**
|
||||
* 获得商机状态分页
|
||||
* 校验商机状态组
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void validateBusinessStatusType(Long id);
|
||||
|
||||
/**
|
||||
* 获得商机状态组列表
|
||||
*
|
||||
* @return 商机状态组列表
|
||||
*/
|
||||
List<CrmBusinessStatusTypeDO> getBusinessStatusTypeList();
|
||||
|
||||
/**
|
||||
* 获得商机状态组分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 商机状态分页
|
||||
* @return 商机状态组分页
|
||||
*/
|
||||
PageResult<CrmBusinessStatusDO> getBusinessStatusPage(CrmBusinessStatusPageReqVO pageReqVO);
|
||||
PageResult<CrmBusinessStatusTypeDO> getBusinessStatusTypePage(PageParam pageReqVO);
|
||||
|
||||
// TODO @ljlleo 常用的 ids 之类的查询,可以封装单独的方法,不用走类似 QueryVO,用起来更方便。
|
||||
// TODO @ljlleo 方法名用 getBusinessStatusList
|
||||
/**
|
||||
* 获得商机状态分页
|
||||
* 获得商机状态组列表
|
||||
*
|
||||
* @param queryVO 查询参数
|
||||
* @return 商机状态分页
|
||||
* @param ids 编号数组
|
||||
* @return 商机状态组列表
|
||||
*/
|
||||
List<CrmBusinessStatusDO> selectList(CrmBusinessStatusQueryVO queryVO);
|
||||
List<CrmBusinessStatusTypeDO> getBusinessStatusTypeList(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得商机状态组 Map
|
||||
*
|
||||
* @param ids 编号数组
|
||||
* @return 商机状态组 Map
|
||||
*/
|
||||
default Map<Long, CrmBusinessStatusTypeDO> getBusinessStatusTypeMap(Collection<Long> ids) {
|
||||
return convertMap(getBusinessStatusTypeList(ids), CrmBusinessStatusTypeDO::getId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得指定类型的商机状态列表
|
||||
*
|
||||
* @param typeId 商机状态组编号
|
||||
* @return 商机状态列表
|
||||
*/
|
||||
List<CrmBusinessStatusDO> getBusinessStatusListByTypeId(Long typeId);
|
||||
|
||||
/**
|
||||
* 获得商机状态列表
|
||||
@ -74,4 +106,14 @@ public interface CrmBusinessStatusService {
|
||||
*/
|
||||
List<CrmBusinessStatusDO> getBusinessStatusList(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得商机状态 Map
|
||||
*
|
||||
* @param ids 编号数组
|
||||
* @return 商机状态 Map
|
||||
*/
|
||||
default Map<Long, CrmBusinessStatusDO> getBusinessStatusMap(Collection<Long> ids) {
|
||||
return convertMap(getBusinessStatusList(ids), CrmBusinessStatusDO::getId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,22 +1,29 @@
|
||||
package cn.iocoder.yudao.module.crm.service.business;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
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.status.CrmBusinessStatusPageReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessStatusMapper;
|
||||
import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessStatusTypeMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
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_STATUS_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList;
|
||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 商机状态 Service 实现类
|
||||
@ -27,59 +34,147 @@ import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STAT
|
||||
@Validated
|
||||
public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService {
|
||||
|
||||
@Resource
|
||||
private CrmBusinessStatusTypeMapper businessStatusTypeMapper;
|
||||
@Resource
|
||||
private CrmBusinessStatusMapper businessStatusMapper;
|
||||
|
||||
@Resource
|
||||
@Lazy // 延迟加载,避免循环依赖
|
||||
private CrmBusinessService businessService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createBusinessStatus(CrmBusinessStatusSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
CrmBusinessStatusDO businessStatus = BeanUtils.toBean(createReqVO, CrmBusinessStatusDO.class);
|
||||
businessStatusMapper.insert(businessStatus);
|
||||
// 返回
|
||||
return businessStatus.getId();
|
||||
// 1.1 检验名称是否存在
|
||||
validateBusinessStatusTypeNameUnique(createReqVO.getName(), null);
|
||||
// 1.2 设置状态的排序
|
||||
int sort = 0;
|
||||
for (CrmBusinessStatusSaveReqVO.Status status : createReqVO.getStatuses()) {
|
||||
status.setSort(sort++);
|
||||
}
|
||||
|
||||
// 2.1 插入类型
|
||||
CrmBusinessStatusTypeDO statusType = BeanUtils.toBean(createReqVO, CrmBusinessStatusTypeDO.class);
|
||||
businessStatusTypeMapper.insert(statusType);
|
||||
// 2.2 插入状态
|
||||
List<CrmBusinessStatusDO> statuses = BeanUtils.toBean(createReqVO.getStatuses(), CrmBusinessStatusDO.class,
|
||||
status -> status.setTypeId(statusType.getId()));
|
||||
businessStatusMapper.insertBatch(statuses);
|
||||
return statusType.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateBusinessStatus(CrmBusinessStatusSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateBusinessStatusExists(updateReqVO.getId());
|
||||
// 更新
|
||||
CrmBusinessStatusDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessStatusDO.class);
|
||||
businessStatusMapper.updateById(updateObj);
|
||||
// 1.1 校验存在
|
||||
validateBusinessStatusTypeExists(updateReqVO.getId());
|
||||
// 1.2 校验名称是否存在
|
||||
validateBusinessStatusTypeNameUnique(updateReqVO.getName(), updateReqVO.getId());
|
||||
// 1.3 设置状态的排序
|
||||
int sort = 0;
|
||||
for (CrmBusinessStatusSaveReqVO.Status status : updateReqVO.getStatuses()) {
|
||||
status.setSort(sort++);
|
||||
}
|
||||
// 1.4 已经使用,无法更新
|
||||
if (businessService.getBusinessCountByStatusTypeId(updateReqVO.getId()) > 0) {
|
||||
throw exception(BUSINESS_STATUS_UPDATE_FAIL_USED);
|
||||
}
|
||||
|
||||
// 2.1 更新类型
|
||||
CrmBusinessStatusTypeDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessStatusTypeDO.class);
|
||||
businessStatusTypeMapper.updateById(updateObj);
|
||||
// 2.2 更新状态
|
||||
updateBusinessStatus(updateReqVO.getId(), BeanUtils.toBean(updateReqVO.getStatuses(), CrmBusinessStatusDO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBusinessStatus(Long id) {
|
||||
// 校验存在
|
||||
validateBusinessStatusExists(id);
|
||||
// TODO @ljlleo 这里可以考虑,如果有商机在使用,不允许删除
|
||||
// 删除
|
||||
businessStatusMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private void validateBusinessStatusExists(Long id) {
|
||||
if (businessStatusMapper.selectById(id) == null) {
|
||||
throw exception(BUSINESS_STATUS_NOT_EXISTS);
|
||||
private void updateBusinessStatus(Long id, List<CrmBusinessStatusDO> newList) {
|
||||
List<CrmBusinessStatusDO> oldList = businessStatusMapper.selectListByTypeId(id);
|
||||
List<List<CrmBusinessStatusDO>> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录
|
||||
(oldVal, newVal) -> oldVal.getId().equals(newVal.getId()));
|
||||
if (CollUtil.isNotEmpty(diffList.get(0))) {
|
||||
diffList.get(0).forEach(o -> o.setTypeId(id));
|
||||
businessStatusMapper.insertBatch(diffList.get(0));
|
||||
}
|
||||
if (CollUtil.isNotEmpty(diffList.get(1))) {
|
||||
businessStatusMapper.updateBatch(diffList.get(1));
|
||||
}
|
||||
if (CollUtil.isNotEmpty(diffList.get(2))) {
|
||||
businessStatusMapper.deleteBatchIds(convertSet(diffList.get(2), CrmBusinessStatusDO::getId));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CrmBusinessStatusDO getBusinessStatus(Long id) {
|
||||
return businessStatusMapper.selectById(id);
|
||||
private void validateBusinessStatusTypeExists(Long id) {
|
||||
if (businessStatusTypeMapper.selectById(id) == null) {
|
||||
throw exception(BUSINESS_STATUS_TYPE_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateBusinessStatusTypeNameUnique(String name, Long id) {
|
||||
CrmBusinessStatusTypeDO statusType = businessStatusTypeMapper.selectByName(name);
|
||||
if (statusType == null
|
||||
|| statusType.getId().equals(id)) {
|
||||
return;
|
||||
}
|
||||
throw exception(BUSINESS_STATUS_TYPE_NAME_EXISTS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<CrmBusinessStatusDO> getBusinessStatusPage(CrmBusinessStatusPageReqVO pageReqVO) {
|
||||
return businessStatusMapper.selectPage(pageReqVO);
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteBusinessStatusType(Long id) {
|
||||
// 1.1 校验存在
|
||||
validateBusinessStatusTypeExists(id);
|
||||
// 1.2 已经使用,无法更新
|
||||
if (businessService.getBusinessCountByStatusTypeId(id) > 0) {
|
||||
throw exception(BUSINESS_STATUS_DELETE_FAIL_USED);
|
||||
}
|
||||
|
||||
// 2.1 删除类型
|
||||
businessStatusTypeMapper.deleteById(id);
|
||||
// 2.2 删除状态
|
||||
businessStatusMapper.deleteByTypeId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmBusinessStatusDO> selectList(CrmBusinessStatusQueryVO queryVO) {
|
||||
return businessStatusMapper.selectList(queryVO);
|
||||
public CrmBusinessStatusTypeDO getBusinessStatusType(Long id) {
|
||||
return businessStatusTypeMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateBusinessStatusType(Long id) {
|
||||
validateBusinessStatusTypeExists(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmBusinessStatusTypeDO> getBusinessStatusTypeList() {
|
||||
return businessStatusTypeMapper.selectList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<CrmBusinessStatusTypeDO> getBusinessStatusTypePage(PageParam pageReqVO) {
|
||||
return businessStatusTypeMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmBusinessStatusTypeDO> getBusinessStatusTypeList(Collection<Long> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return businessStatusTypeMapper.selectBatchIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmBusinessStatusDO> getBusinessStatusListByTypeId(Long typeId) {
|
||||
List<CrmBusinessStatusDO> list = businessStatusMapper.selectListByTypeId(typeId);
|
||||
list.sort(Comparator.comparingInt(CrmBusinessStatusDO::getSort));
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmBusinessStatusDO> getBusinessStatusList(Collection<Long> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return businessStatusMapper.selectBatchIds(ids);
|
||||
}
|
||||
|
||||
|
@ -1,75 +0,0 @@
|
||||
package cn.iocoder.yudao.module.crm.service.business;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypePageReqVO;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 商机状态类型 Service 接口
|
||||
*
|
||||
* @author ljlleo
|
||||
*/
|
||||
public interface CrmBusinessStatusTypeService {
|
||||
|
||||
/**
|
||||
* 创建商机状态类型
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createBusinessStatusType(@Valid CrmBusinessStatusTypeSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新商机状态类型
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateBusinessStatusType(@Valid CrmBusinessStatusTypeSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除商机状态类型
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteBusinessStatusType(Long id);
|
||||
|
||||
/**
|
||||
* 获得商机状态类型
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 商机状态类型
|
||||
*/
|
||||
CrmBusinessStatusTypeDO getBusinessStatusType(Long id);
|
||||
|
||||
/**
|
||||
* 获得商机状态类型分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 商机状态类型分页
|
||||
*/
|
||||
PageResult<CrmBusinessStatusTypeDO> getBusinessStatusTypePage(CrmBusinessStatusTypePageReqVO pageReqVO);
|
||||
|
||||
// TODO @ljlleo 常用的 ids 之类的查询,可以封装单独的方法,不用走类似 QueryVO,用起来更方便。
|
||||
/**
|
||||
* 获得商机状态类型列表
|
||||
*
|
||||
* @param queryVO 查询参数
|
||||
* @return 商机状态类型列表
|
||||
*/
|
||||
List<CrmBusinessStatusTypeDO> selectList(CrmBusinessStatusTypeQueryVO queryVO);
|
||||
|
||||
/**
|
||||
* 获得商机状态类型列表
|
||||
*
|
||||
* @param ids 编号数组
|
||||
* @return 商机状态类型列表
|
||||
*/
|
||||
List<CrmBusinessStatusTypeDO> getBusinessStatusTypeList(Collection<Long> ids);
|
||||
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
package cn.iocoder.yudao.module.crm.service.business;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
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.type.CrmBusinessStatusTypePageReqVO;
|
||||
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.CrmBusinessStatusDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
|
||||
import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessStatusMapper;
|
||||
import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessStatusTypeMapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
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;
|
||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_TYPE_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_TYPE_NAME_EXISTS;
|
||||
|
||||
/**
|
||||
* 商机状态类型 Service 实现类
|
||||
*
|
||||
* @author ljlleo
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class CrmBusinessStatusTypeServiceImpl implements CrmBusinessStatusTypeService {
|
||||
|
||||
@Resource
|
||||
private CrmBusinessStatusTypeMapper businessStatusTypeMapper;
|
||||
|
||||
@Resource
|
||||
private CrmBusinessStatusMapper businessStatusMapper;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createBusinessStatusType(CrmBusinessStatusTypeSaveReqVO createReqVO) {
|
||||
//检验名称是否存在
|
||||
validateBusinessStatusTypeExists(createReqVO.getName(), null);
|
||||
// 插入类型
|
||||
CrmBusinessStatusTypeDO businessStatusType = BeanUtils.toBean(createReqVO, CrmBusinessStatusTypeDO.class);
|
||||
businessStatusTypeMapper.insert(businessStatusType);
|
||||
// 插入状态
|
||||
if (CollUtil.isNotEmpty(createReqVO.getStatusList())) {
|
||||
createReqVO.getStatusList().forEach(status -> status.setTypeId(businessStatusType.getId()));
|
||||
businessStatusMapper.insertBatch(BeanUtils.toBean(createReqVO.getStatusList(), CrmBusinessStatusDO.class));
|
||||
}
|
||||
return businessStatusType.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateBusinessStatusType(CrmBusinessStatusTypeSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateBusinessStatusTypeExists(updateReqVO.getId());
|
||||
// 校验名称是否存在
|
||||
validateBusinessStatusTypeExists(updateReqVO.getName(), updateReqVO.getId());
|
||||
// 更新类型
|
||||
CrmBusinessStatusTypeDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessStatusTypeDO.class);
|
||||
businessStatusTypeMapper.updateById(updateObj);
|
||||
// 更新状态(删除 + 更新)
|
||||
// TODO @ljlleo 可以参考 DeliveryExpressTemplateServiceImpl 的 updateExpressTemplateFree 方法;主要没变化的,还是不删除了哈。
|
||||
businessStatusMapper.delete(updateReqVO.getId());
|
||||
updateReqVO.getStatusList().forEach(status -> status.setTypeId(updateReqVO.getId()));
|
||||
businessStatusMapper.insertBatch(BeanUtils.toBean(updateReqVO.getStatusList(), CrmBusinessStatusDO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteBusinessStatusType(Long id) {
|
||||
// TODO 待添加被引用校验
|
||||
//...
|
||||
|
||||
// 校验存在
|
||||
validateBusinessStatusTypeExists(id);
|
||||
// 删除类型
|
||||
businessStatusTypeMapper.deleteById(id);
|
||||
// 删除状态
|
||||
businessStatusMapper.delete(id);
|
||||
}
|
||||
|
||||
private void validateBusinessStatusTypeExists(Long id) {
|
||||
if (businessStatusTypeMapper.selectById(id) == null) {
|
||||
throw exception(BUSINESS_STATUS_TYPE_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO @ljlleo 这个方法,这个参考 validateDeptNameUnique 实现。
|
||||
private void validateBusinessStatusTypeExists(String name, Long id) {
|
||||
CrmBusinessStatusTypeDO businessStatusTypeDO = businessStatusTypeMapper.selectByIdAndName(id, name);
|
||||
if (businessStatusTypeDO != null) {
|
||||
throw exception(BUSINESS_STATUS_TYPE_NAME_EXISTS);
|
||||
}
|
||||
// LambdaQueryWrapper<CrmBusinessStatusTypeDO> wrapper = new LambdaQueryWrapperX<>();
|
||||
// if(null != id) {
|
||||
// wrapper.ne(CrmBusinessStatusTypeDO::getId, id);
|
||||
// }
|
||||
// long cnt = businessStatusTypeMapper.selectCount(wrapper.eq(CrmBusinessStatusTypeDO::getName, name));
|
||||
// if (cnt > 0) {
|
||||
// throw exception(BUSINESS_STATUS_TYPE_NAME_EXISTS);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public CrmBusinessStatusTypeDO getBusinessStatusType(Long id) {
|
||||
return businessStatusTypeMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<CrmBusinessStatusTypeDO> getBusinessStatusTypePage(CrmBusinessStatusTypePageReqVO pageReqVO) {
|
||||
return businessStatusTypeMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmBusinessStatusTypeDO> selectList(CrmBusinessStatusTypeQueryVO queryVO) {
|
||||
return businessStatusTypeMapper.selectList(queryVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmBusinessStatusTypeDO> getBusinessStatusTypeList(Collection<Long> ids) {
|
||||
return businessStatusTypeMapper.selectBatchIds(ids);
|
||||
}
|
||||
|
||||
}
|
@ -88,6 +88,13 @@ public interface CrmContactService {
|
||||
*/
|
||||
CrmContactDO getContact(Long id);
|
||||
|
||||
/**
|
||||
* 校验联系人
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void validateContact(Long id);
|
||||
|
||||
/**
|
||||
* 获得联系人列表
|
||||
*
|
||||
|
@ -251,6 +251,11 @@ public class CrmContactServiceImpl implements CrmContactService {
|
||||
return contactMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateContact(Long id) {
|
||||
validateContactExists(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmContactDO> getContactListByIds(Collection<Long> ids, Long userId) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
|
@ -184,7 +184,8 @@ public class CrmContractServiceImpl implements CrmContractService {
|
||||
return BeanUtils.toBean(product, CrmContractProductDO.class)
|
||||
.setId(null).setProductId(productItem.getId()).setContractId(contractId)
|
||||
.setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent())
|
||||
.setTotalPrice(MoneyUtils.calculator(product.getPrice(), productItem.getCount(), productItem.getDiscountPercent()));
|
||||
// TODO 芋艿:这里临时注释掉
|
||||
.setTotalPrice(MoneyUtils.calculator(null, productItem.getCount(), productItem.getDiscountPercent()));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -3,10 +3,13 @@ package cn.iocoder.yudao.module.crm.service.product;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryCreateReqVO;
|
||||
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryListReqVO;
|
||||
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
|
||||
/**
|
||||
* CRM 产品分类 Service 接口
|
||||
@ -61,4 +64,14 @@ public interface CrmProductCategoryService {
|
||||
*/
|
||||
List<CrmProductCategoryDO> getProductCategoryList(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得产品分类 Map
|
||||
*
|
||||
* @param ids 编号数组
|
||||
* @return 产品分类 Map
|
||||
*/
|
||||
default Map<Long, CrmProductCategoryDO> getProductCategoryMap(Collection<Long> ids) {
|
||||
return convertMap(getProductCategoryList(ids), CrmProductCategoryDO::getId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,9 @@ import jakarta.validation.Valid;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
|
||||
/**
|
||||
* CRM 产品 Service 接口
|
||||
@ -54,28 +57,46 @@ public interface CrmProductService {
|
||||
*/
|
||||
List<CrmProductDO> getProductList(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得产品 Map
|
||||
*
|
||||
* @param ids 编号
|
||||
* @return 产品 Map
|
||||
*/
|
||||
default Map<Long, CrmProductDO> getProductMap(Collection<Long> ids) {
|
||||
return convertMap(getProductList(ids), CrmProductDO::getId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得产品分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 产品分页
|
||||
*/
|
||||
PageResult<CrmProductDO> getProductPage(CrmProductPageReqVO pageReqVO, Long userId);
|
||||
PageResult<CrmProductDO> getProductPage(CrmProductPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 获得产品
|
||||
* 获得产品数量
|
||||
*
|
||||
* @param categoryId 分类编号
|
||||
* @return 产品
|
||||
*/
|
||||
CrmProductDO getProductByCategoryId(Long categoryId);
|
||||
Long getProductByCategoryId(Long categoryId);
|
||||
|
||||
/**
|
||||
* 获得产品列表
|
||||
* 获得指定状态的产品列表
|
||||
*
|
||||
* @param ids 产品编号
|
||||
* @param status 状态
|
||||
* @return 产品列表
|
||||
*/
|
||||
List<CrmProductDO> getProductListByIds(Collection<Long> ids);
|
||||
List<CrmProductDO> getProductListByStatus(Integer status);
|
||||
|
||||
/**
|
||||
* 校验产品们的有效性
|
||||
*
|
||||
* @param ids 编号数组
|
||||
* @return 产品列表
|
||||
*/
|
||||
List<CrmProductDO> validProductList(Collection<Long> ids);
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package cn.iocoder.yudao.module.crm.service.product;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
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.product.vo.product.CrmProductPageReqVO;
|
||||
@ -15,7 +15,6 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm
|
||||
import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
|
||||
import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.mzt.logapi.context.LogRecordContext;
|
||||
import com.mzt.logapi.service.impl.DiffParseFunction;
|
||||
import com.mzt.logapi.starter.annotation.LogRecord;
|
||||
@ -27,8 +26,10 @@ import org.springframework.validation.annotation.Validated;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
|
||||
|
||||
@ -138,25 +139,41 @@ public class CrmProductServiceImpl implements CrmProductService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmProductDO> getProductList(Collection<Long> ids) {
|
||||
public PageResult<CrmProductDO> getProductPage(CrmProductPageReqVO pageReqVO) {
|
||||
return productMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getProductByCategoryId(Long categoryId) {
|
||||
return productMapper.selectCountByCategoryId(categoryId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmProductDO> getProductListByStatus(Integer status) {
|
||||
return productMapper.selectListByStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmProductDO> validProductList(Collection<Long> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return ListUtil.empty();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return productMapper.selectBatchIds(ids);
|
||||
List<CrmProductDO> list = productMapper.selectBatchIds(ids);
|
||||
Map<Long, CrmProductDO> productMap = convertMap(list, CrmProductDO::getId);
|
||||
for (Long id : ids) {
|
||||
CrmProductDO product = productMap.get(id);
|
||||
if (productMap.get(id) == null) {
|
||||
throw exception(PRODUCT_NOT_EXISTS);
|
||||
}
|
||||
if (CommonStatusEnum.isDisable(product.getStatus())) {
|
||||
throw exception(PRODUCT_NOT_ENABLE, product.getName());
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<CrmProductDO> getProductPage(CrmProductPageReqVO pageReqVO, Long userId) {
|
||||
return productMapper.selectPage(pageReqVO, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CrmProductDO getProductByCategoryId(Long categoryId) {
|
||||
return productMapper.selectOne(new LambdaQueryWrapper<CrmProductDO>().eq(CrmProductDO::getCategoryId, categoryId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CrmProductDO> getProductListByIds(Collection<Long> ids) {
|
||||
public List<CrmProductDO> getProductList(Collection<Long> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user