CRM:重构商机状态的代码实现,不调整表结构

This commit is contained in:
YunaiV 2024-02-21 20:10:13 +08:00
parent e01dda9baf
commit f76a7cd941
28 changed files with 385 additions and 754 deletions

View File

@ -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, "联系人商机关联不存在");
@ -77,12 +75,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 +89,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 ==========
}

View File

@ -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}}

View File

@ -20,7 +20,6 @@ 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;
@ -62,7 +61,7 @@ public class CrmBusinessController {
@Resource
private CrmCustomerService customerService;
@Resource
private CrmBusinessStatusTypeService businessStatusTypeService;
private CrmBusinessStatusService businessStatusTypeService;
@Resource
private CrmBusinessStatusService businessStatusService;
@Resource

View File

@ -0,0 +1,118 @@
package cn.iocoder.yudao.module.crm.controller.admin.business;
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.*;
@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-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<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-type:query')")
public CommonResult<PageResult<CrmBusinessStatusRespVO>> getBusinessStatusTypePage(@Valid PageParam pageReqVO) {
// 1. 查询数据
PageResult<CrmBusinessStatusTypeDO> pageResult = businessStatusTypeService.getBusinessStatusTypePage(pageReqVO);
// 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();
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));
}
}

View File

@ -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));
}
}

View File

@ -52,10 +52,10 @@ public class CrmBusinessRespVO {
@ExcelProperty("负责人部门")
private String ownerUserDeptName;
@Schema(description = "商机状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714")
@Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714")
private Long statusTypeId;
@Schema(description = "状态类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "进行中")
@ExcelProperty("商机状态类型")
@Schema(description = "商机状组名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "进行中")
@ExcelProperty("商机状态")
private String statusTypeName;
@Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")

View File

@ -43,9 +43,9 @@ public class CrmBusinessSaveReqVO {
@DiffLogField(name = "负责人", function = SysAdminUserParseFunction.NAME)
private Long ownerUserId;
@Schema(description = "商机状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714")
@DiffLogField(name = "商机状态")
@NotNull(message = "商机状态类型不能为空")
@Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714")
@DiffLogField(name = "商机状态")
@NotNull(message = "商机状态不能为空")
private Long statusTypeId;
@Schema(description = "预计成交日期")

View File

@ -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 {
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -1,32 +1,48 @@
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.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 @lzxhqspercent 应该是 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 = "商机状态集合不能为空")
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;
}
}

View File

@ -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 {
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -63,7 +63,7 @@ public class CrmBusinessDO extends BaseDO {
private Long ownerUserId;
/**
* 商机状态类型编号
* 商机状态编号
*
* 关联 {@link CrmBusinessStatusTypeDO#getId()}
*/

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -138,4 +138,12 @@ public interface CrmBusinessService {
*/
Long getBusinessCountByCustomerId(Long customerId);
/**
* 获得使用指定商机状态组的商机数量
*
* @param statusTypeId 商机状态组编号
* @return 数量
*/
Long getBusinessCountByStatusTypeId(Long statusTypeId);
}

View File

@ -295,4 +295,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
return businessMapper.selectCount(CrmBusinessDO::getCustomerId, customerId);
}
@Override
public Long getBusinessCountByStatusTypeId(Long statusTypeId) {
return businessMapper.selectCountByStatusTypeId(statusTypeId);
}
}

View File

@ -1,10 +1,10 @@
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;
@ -40,33 +40,56 @@ 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);
/**
* 获得商机状态分页
* 获得商机状态组列表
*
* @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);
/**
* 获得商机状态列表

View File

@ -1,24 +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 org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
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 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 实现类
@ -29,55 +34,135 @@ 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 校验存在
validateBusinessStatusTypeNameUnique(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 validateBusinessStatusTypeNameUnique(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 校验存在
validateBusinessStatusTypeNameUnique(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 List<CrmBusinessStatusTypeDO> getBusinessStatusTypeList() {
return businessStatusTypeMapper.selectList();
}
@Override
public PageResult<CrmBusinessStatusTypeDO> getBusinessStatusTypePage(PageParam pageReqVO) {
return null;
}
@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

View File

@ -1,88 +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;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
/**
* 商机状态类型 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);
/**
* 获得商机状态类型 Map
*
* @param ids 编号数组
* @return 商机状态类型 Map
*/
default Map<Long, CrmBusinessStatusTypeDO> getBusinessStatusTypeMap(Collection<Long> ids) {
return convertMap(getBusinessStatusTypeList(ids), CrmBusinessStatusTypeDO::getId);
}
}

View File

@ -1,133 +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.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 jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.Collection;
import java.util.Collections;
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_NAME_EXISTS;
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_TYPE_NOT_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) {
if (CollUtil.isEmpty(ids)) {
return Collections.emptyList();
}
return businessStatusTypeMapper.selectBatchIds(ids);
}
}