Commit f361d05940e3e5ac91004fd5e51cad5e34749858
1 parent
ed34b18d
商机模块
Showing
25 changed files
with
527 additions
and
36 deletions
sql/mysql/optinal/crm_20240114.sql
0 → 100644
| 1 | + | |
| 2 | +-- ---------------------------- | |
| 3 | +-- Table structure for crm_business_product | |
| 4 | +-- ---------------------------- | |
| 5 | +DROP TABLE IF EXISTS `crm_business_product`; | |
| 6 | +CREATE TABLE `crm_business_product` ( | |
| 7 | + `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键', | |
| 8 | + `business_id` bigint(0) NOT NULL COMMENT '商机ID', | |
| 9 | + `product_id` bigint(0) NOT NULL COMMENT '产品ID', | |
| 10 | + `price` decimal(18, 2) NOT NULL COMMENT '产品单价', | |
| 11 | + `sales_price` decimal(18, 2) NULL DEFAULT NULL COMMENT '销售价格', | |
| 12 | + `num` int(0) NULL DEFAULT NULL COMMENT '数量', | |
| 13 | + `discount` decimal(10, 2) NULL DEFAULT NULL COMMENT '折扣', | |
| 14 | + `subtotal` decimal(18, 2) NULL DEFAULT NULL COMMENT '小计(折扣后价格)', | |
| 15 | + `unit` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '单位', | |
| 16 | + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', | |
| 17 | + `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | |
| 18 | + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', | |
| 19 | + `update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间', | |
| 20 | + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | |
| 21 | + `tenant_id` bigint(0) NOT NULL DEFAULT 1 COMMENT '租户编号', | |
| 22 | + PRIMARY KEY (`id`) USING BTREE | |
| 23 | +) ENGINE = InnoDB AUTO_INCREMENT = 29 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商机产品关联表' ROW_FORMAT = Dynamic; | |
| 24 | + | |
| 25 | +-- ---------------------------- | |
| 26 | +-- Table structure for crm_business_status | |
| 27 | +-- ---------------------------- | |
| 28 | +DROP TABLE IF EXISTS `crm_business_status`; | |
| 29 | +CREATE TABLE `crm_business_status` ( | |
| 30 | + `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键ID', | |
| 31 | + `type_id` bigint(0) NOT NULL COMMENT '状态类型编号', | |
| 32 | + `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '状态名', | |
| 33 | + `percent` bigint(0) NULL DEFAULT NULL COMMENT '赢单率', | |
| 34 | + `sort` int(0) NULL DEFAULT NULL COMMENT '排序', | |
| 35 | + `tenant_id` bigint(0) NOT NULL DEFAULT 0 COMMENT '租户编号', | |
| 36 | + PRIMARY KEY (`id`) USING BTREE | |
| 37 | +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商机状态' ROW_FORMAT = Dynamic; | |
| 38 | + | |
| 39 | +-- ---------------------------- | |
| 40 | +-- Table structure for crm_business_status_type | |
| 41 | +-- ---------------------------- | |
| 42 | +DROP TABLE IF EXISTS `crm_business_status_type`; | |
| 43 | +CREATE TABLE `crm_business_status_type` ( | |
| 44 | + `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键ID', | |
| 45 | + `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '状态类型名', | |
| 46 | + `dept_ids` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '使用的部门编号', | |
| 47 | + `status` int(0) NOT NULL DEFAULT 1 COMMENT '开启状态', | |
| 48 | + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', | |
| 49 | + `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', | |
| 50 | + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', | |
| 51 | + `update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间', | |
| 52 | + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', | |
| 53 | + `tenant_id` bigint(0) NOT NULL DEFAULT 0 COMMENT '租户编号', | |
| 54 | + PRIMARY KEY (`id`) USING BTREE | |
| 55 | +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商机状态类型' ROW_FORMAT = Dynamic; | ... | ... |
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
| ... | ... | @@ -17,6 +17,7 @@ public interface ErrorCodeConstants { |
| 17 | 17 | |
| 18 | 18 | // ========== 商机管理 1-020-002-000 ========== |
| 19 | 19 | ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在"); |
| 20 | + ErrorCode BUSINESS_CONTRACT_EXISTS = new ErrorCode(1_020_002_001, "商机已关联合同,不能删除"); | |
| 20 | 21 | |
| 21 | 22 | // TODO @lilleo:商机状态、商机类型,都单独错误码段 |
| 22 | 23 | ... | ... |
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBizEndStatus.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.enums.business; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.ObjUtil; | |
| 4 | +import cn.hutool.core.util.ObjectUtil; | |
| 5 | +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; | |
| 6 | +import lombok.Getter; | |
| 7 | +import lombok.RequiredArgsConstructor; | |
| 8 | + | |
| 9 | +import java.util.Arrays; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * @author lzxhqs | |
| 13 | + * @version 1.0 | |
| 14 | + * @title CrmBizEndStatus | |
| 15 | + * @description | |
| 16 | + * @create 2024/1/12 | |
| 17 | + */ | |
| 18 | +@RequiredArgsConstructor | |
| 19 | +@Getter | |
| 20 | +public enum CrmBizEndStatus implements IntArrayValuable { | |
| 21 | + WIN(1, "赢单"), | |
| 22 | + LOSE(2, "输单"), | |
| 23 | + INVALID(3, "无效"); | |
| 24 | + | |
| 25 | + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBizEndStatus::getStatus).toArray(); | |
| 26 | + | |
| 27 | + public static boolean isWin(Integer status) { | |
| 28 | + return ObjectUtil.equal(WIN.getStatus(), status); | |
| 29 | + } | |
| 30 | + | |
| 31 | + public static boolean isLose(Integer status) { | |
| 32 | + return ObjectUtil.equal(LOSE.getStatus(), status); | |
| 33 | + } | |
| 34 | + | |
| 35 | + public static boolean isInvalid(Integer status) { | |
| 36 | + return ObjectUtil.equal(INVALID.getStatus(), status); | |
| 37 | + } | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * 场景类型 | |
| 41 | + */ | |
| 42 | + private final Integer status; | |
| 43 | + /** | |
| 44 | + * 场景名称 | |
| 45 | + */ | |
| 46 | + private final String name; | |
| 47 | + | |
| 48 | + @Override | |
| 49 | + public int[] array() { | |
| 50 | + return ARRAYS; | |
| 51 | + } | |
| 52 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/pom.xml
| ... | ... | @@ -24,6 +24,11 @@ |
| 24 | 24 | </dependency> |
| 25 | 25 | <dependency> |
| 26 | 26 | <groupId>cn.iocoder.boot</groupId> |
| 27 | + <artifactId>yudao-module-system-biz</artifactId> | |
| 28 | + <version>${revision}</version> | |
| 29 | + </dependency> | |
| 30 | + <dependency> | |
| 31 | + <groupId>cn.iocoder.boot</groupId> | |
| 27 | 32 | <artifactId>yudao-module-crm-api</artifactId> |
| 28 | 33 | <version>${revision}</version> |
| 29 | 34 | </dependency> | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java
| ... | ... | @@ -55,14 +55,14 @@ public class CrmBusinessController { |
| 55 | 55 | @PostMapping("/create") |
| 56 | 56 | @Operation(summary = "创建商机") |
| 57 | 57 | @PreAuthorize("@ss.hasPermission('crm:business:create')") |
| 58 | - public CommonResult<Long> createBusiness(@Valid @RequestBody CrmBusinessCreateReqVO createReqVO) { | |
| 58 | + public CommonResult<Long> createBusiness(@Valid @RequestBody CrmBusinessSaveReqVO createReqVO) { | |
| 59 | 59 | return success(businessService.createBusiness(createReqVO, getLoginUserId())); |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | 62 | @PutMapping("/update") |
| 63 | 63 | @Operation(summary = "更新商机") |
| 64 | 64 | @PreAuthorize("@ss.hasPermission('crm:business:update')") |
| 65 | - public CommonResult<Boolean> updateBusiness(@Valid @RequestBody CrmBusinessUpdateReqVO updateReqVO) { | |
| 65 | + public CommonResult<Boolean> updateBusiness(@Valid @RequestBody CrmBusinessSaveReqVO updateReqVO) { | |
| 66 | 66 | businessService.updateBusiness(updateReqVO); |
| 67 | 67 | return success(true); |
| 68 | 68 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java
| ... | ... | @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 6 | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 7 | 8 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 8 | 9 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| 9 | 10 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; |
| ... | ... | @@ -101,11 +102,12 @@ public class CrmBusinessStatusTypeController { |
| 101 | 102 | PageResult<CrmBusinessStatusTypeDO> pageResult = businessStatusTypeService.getBusinessStatusTypePage(pageReqVO); |
| 102 | 103 | // 处理部门回显 |
| 103 | 104 | // TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈; |
| 104 | - Set<Long> deptIds = pageResult.getList().stream() | |
| 105 | - .map(CrmBusinessStatusTypeDO::getDeptIds) | |
| 106 | - .filter(Objects::nonNull) | |
| 107 | - .flatMap(Collection::stream) | |
| 108 | - .collect(Collectors.toSet()); | |
| 105 | +// Set<Long> deptIds = pageResult.getList().stream() | |
| 106 | +// .map(CrmBusinessStatusTypeDO::getDeptIds) | |
| 107 | +// .filter(Objects::nonNull) | |
| 108 | +// .flatMap(Collection::stream) | |
| 109 | +// .collect(Collectors.toSet()); | |
| 110 | + Set<Long> deptIds = CollectionUtils.convertSetByFlatMap(pageResult.getList(), CrmBusinessStatusTypeDO::getDeptIds,Collection::stream); | |
| 109 | 111 | List<DeptRespDTO> deptList = deptApi.getDeptList(deptIds); |
| 110 | 112 | return success(CrmBusinessStatusTypeConvert.INSTANCE.convertPage(pageResult, deptList)); |
| 111 | 113 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | |
| 4 | +import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductSaveReqVO; | |
| 5 | +import cn.iocoder.yudao.module.crm.enums.business.CrmBizEndStatus; | |
| 6 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 7 | +import jakarta.validation.constraints.NotNull; | |
| 8 | +import lombok.Data; | |
| 9 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 10 | + | |
| 11 | +import java.math.BigDecimal; | |
| 12 | +import java.time.LocalDateTime; | |
| 13 | +import java.util.ArrayList; | |
| 14 | +import java.util.List; | |
| 15 | + | |
| 16 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 17 | + | |
| 18 | +/** | |
| 19 | + * @author lzxhqs | |
| 20 | + */ | |
| 21 | +@Schema(description = "管理后台 - CRM 商机创建/更新 Request VO") | |
| 22 | +@Data | |
| 23 | +public class CrmBusinessSaveReqVO { | |
| 24 | + | |
| 25 | + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129") | |
| 26 | + private Long id; | |
| 27 | + | |
| 28 | + @Schema(description = "商机名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") | |
| 29 | + @NotNull(message = "商机名称不能为空") | |
| 30 | + private String name; | |
| 31 | + | |
| 32 | + @Schema(description = "商机状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714") | |
| 33 | + @NotNull(message = "商机状态类型不能为空") | |
| 34 | + private Long statusTypeId; | |
| 35 | + | |
| 36 | + @Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") | |
| 37 | + @NotNull(message = "商机状态不能为空") | |
| 38 | + private Long statusId; | |
| 39 | + | |
| 40 | + @Schema(description = "下次联系时间") | |
| 41 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 42 | + private LocalDateTime contactNextTime; | |
| 43 | + | |
| 44 | + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10299") | |
| 45 | + @NotNull(message = "客户不能为空") | |
| 46 | + private Long customerId; | |
| 47 | + | |
| 48 | + @Schema(description = "预计成交日期") | |
| 49 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 50 | + private LocalDateTime dealTime; | |
| 51 | + | |
| 52 | + @Schema(description = "商机金额", example = "12371") | |
| 53 | + private Integer price; | |
| 54 | + | |
| 55 | + @Schema(description = "整单折扣") | |
| 56 | + private Integer discountPercent; | |
| 57 | + | |
| 58 | + @Schema(description = "产品总金额", example = "12025") | |
| 59 | + private BigDecimal productPrice; | |
| 60 | + | |
| 61 | + @Schema(description = "备注", example = "随便") | |
| 62 | + private String remark; | |
| 63 | + | |
| 64 | + @Schema(description = "联系人编号", example = "110") | |
| 65 | + @NotNull(message = "联系人编号不能为空") | |
| 66 | + private Long contactId; | |
| 67 | + | |
| 68 | + @Schema(description = "1赢单2输单3无效", example = "1") | |
| 69 | + @InEnum(CrmBizEndStatus.class) | |
| 70 | + private Integer endStatus; | |
| 71 | + | |
| 72 | + @Schema(description = "产品列表", example = "") | |
| 73 | + private List<CrmProductSaveReqVO> product = new ArrayList<>(); | |
| 74 | + | |
| 75 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.controller.admin.business.vo.product; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 5 | +import lombok.Data; | |
| 6 | +import lombok.EqualsAndHashCode; | |
| 7 | +import lombok.ToString; | |
| 8 | + | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * @author lzxhqs | |
| 12 | + */ | |
| 13 | +@Schema(description = "管理后台 - 商机产品分页 Request VO") | |
| 14 | +@Data | |
| 15 | +@EqualsAndHashCode(callSuper = true) | |
| 16 | +@ToString(callSuper = true) | |
| 17 | +public class CrmBusinessProductPageReqVO extends PageParam { | |
| 18 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.controller.admin.business.vo.product; | |
| 2 | + | |
| 3 | +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; | |
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +/** | |
| 8 | + * @author lzxhqs | |
| 9 | + */ | |
| 10 | +@Schema(description = "管理后台 - 商机产品关联 Response VO") | |
| 11 | +@Data | |
| 12 | +@ExcelIgnoreUnannotated | |
| 13 | +public class CrmBusinessProductRespVO { | |
| 14 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.controller.admin.business.vo.product; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import jakarta.validation.constraints.NotNull; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +import java.math.BigDecimal; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * @author lzxhqs | |
| 11 | + */ | |
| 12 | +@Schema(description = "管理后台 - CRM 商机产品关联表 创建/更新 Request VO") | |
| 13 | +@Data | |
| 14 | +public class CrmBusinessProductSaveReqVO { | |
| 15 | + | |
| 16 | + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129") | |
| 17 | + private Long id; | |
| 18 | + | |
| 19 | + @Schema(description = "商机ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") | |
| 20 | + @NotNull(message = "商机ID不能为空") | |
| 21 | + private Integer businessId; | |
| 22 | + | |
| 23 | + @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") | |
| 24 | + @NotNull(message = "产品ID不能为空") | |
| 25 | + private Integer productId; | |
| 26 | + | |
| 27 | + @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") | |
| 28 | + @NotNull(message = "产品单价不能为空") | |
| 29 | + private BigDecimal price; | |
| 30 | + | |
| 31 | + @Schema(description = "销售价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") | |
| 32 | + @NotNull(message = "销售价格不能为空") | |
| 33 | + private BigDecimal salesPrice; | |
| 34 | + | |
| 35 | + @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") | |
| 36 | + @NotNull(message = "数量不能为空") | |
| 37 | + private BigDecimal num; | |
| 38 | + | |
| 39 | + @Schema(description = "折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") | |
| 40 | + @NotNull(message = "折扣不能为空") | |
| 41 | + private BigDecimal discount; | |
| 42 | + | |
| 43 | + @Schema(description = "小计(折扣后价格)", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") | |
| 44 | + @NotNull(message = "小计(折扣后价格)不能为空") | |
| 45 | + private BigDecimal subtotal; | |
| 46 | + | |
| 47 | + @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") | |
| 48 | + @NotNull(message = "单位不能为空") | |
| 49 | + private String unit; | |
| 50 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/type/CrmBusinessStatusTypeSaveReqVO.java
| ... | ... | @@ -24,6 +24,6 @@ public class CrmBusinessStatusTypeSaveReqVO { |
| 24 | 24 | |
| 25 | 25 | // TODO @ljlleo VO 里面,我们不使用默认值哈。这里 Lists.newArrayList() 看看怎么去掉。上面 deptIds 也是类似噢 |
| 26 | 26 | @Schema(description = "商机状态集合", requiredMode = Schema.RequiredMode.REQUIRED) |
| 27 | - private List<CrmBusinessStatusSaveReqVO> statusList = Lists.newArrayList(); | |
| 27 | + private List<CrmBusinessStatusSaveReqVO> statusList; | |
| 28 | 28 | |
| 29 | 29 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java
| ... | ... | @@ -27,7 +27,7 @@ public interface CrmBusinessConvert { |
| 27 | 27 | |
| 28 | 28 | CrmBusinessConvert INSTANCE = Mappers.getMapper(CrmBusinessConvert.class); |
| 29 | 29 | |
| 30 | - CrmBusinessDO convert(CrmBusinessCreateReqVO bean); | |
| 30 | + CrmBusinessDO convert(CrmBusinessSaveReqVO bean); | |
| 31 | 31 | |
| 32 | 32 | CrmBusinessDO convert(CrmBusinessUpdateReqVO bean); |
| 33 | 33 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessproduct/CrmBusinessProductConvert.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.convert.businessproduct; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductSaveReqVO; | |
| 4 | +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; | |
| 5 | +import org.mapstruct.Mapper; | |
| 6 | +import org.mapstruct.factory.Mappers; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * @author lzxhqs | |
| 10 | + * @version 1.0 | |
| 11 | + * @title CrmBusinessProductConvert | |
| 12 | + * @description | |
| 13 | + * @create 2024/1/12 | |
| 14 | + */ | |
| 15 | +@Mapper | |
| 16 | +public interface CrmBusinessProductConvert { | |
| 17 | + CrmBusinessProductConvert INSTANCE = Mappers.getMapper(CrmBusinessProductConvert.class); | |
| 18 | + | |
| 19 | + CrmBusinessProductDO convert(CrmProductSaveReqVO product); | |
| 20 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatustype/CrmBusinessStatusTypeConvert.java
| ... | ... | @@ -41,9 +41,9 @@ public interface CrmBusinessStatusTypeConvert { |
| 41 | 41 | |
| 42 | 42 | default CrmBusinessStatusTypeRespVO convert(CrmBusinessStatusTypeDO bean, List<CrmBusinessStatusDO> statusList) { |
| 43 | 43 | // TODO @ljlleo 可以链式赋值,简化成一行; |
| 44 | - CrmBusinessStatusTypeRespVO result = convert(bean); | |
| 45 | - result.setStatusList(statusList); | |
| 46 | - return result; | |
| 44 | +// CrmBusinessStatusTypeRespVO result = convert(bean); | |
| 45 | +// result.setStatusList(statusList); | |
| 46 | + return convert(bean).setStatusList(statusList); | |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | 49 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.dal.dataobject.business; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 4 | +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | |
| 5 | +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; | |
| 4 | 6 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| 5 | 7 | import com.baomidou.mybatisplus.annotation.TableId; |
| 6 | 8 | import com.baomidou.mybatisplus.annotation.TableName; |
| ... | ... | @@ -52,6 +54,7 @@ public class CrmBusinessDO extends BaseDO { |
| 52 | 54 | * 客户编号 |
| 53 | 55 | * |
| 54 | 56 | * TODO @ljileo:这个字段,后续要写下关联的实体哈 |
| 57 | + * 关联 {@link CrmCustomerDO#getId()} | |
| 55 | 58 | */ |
| 56 | 59 | private Long customerId; |
| 57 | 60 | /** |
| ... | ... | @@ -101,6 +104,7 @@ public class CrmBusinessDO extends BaseDO { |
| 101 | 104 | * 负责人的用户编号 |
| 102 | 105 | * |
| 103 | 106 | * 关联 AdminUserDO 的 id 字段 |
| 107 | + * {@link AdminUserDO#getId()} | |
| 104 | 108 | */ |
| 105 | 109 | private Long ownerUserId; |
| 106 | 110 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.dal.dataobject.business; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | |
| 4 | +import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; | |
| 5 | +import com.baomidou.mybatisplus.annotation.KeySequence; | |
| 6 | +import com.baomidou.mybatisplus.annotation.TableId; | |
| 7 | +import com.baomidou.mybatisplus.annotation.TableName; | |
| 8 | +import lombok.*; | |
| 9 | + | |
| 10 | +import java.math.BigDecimal; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * 商机产品关联表 DO | |
| 14 | + * | |
| 15 | + * @author lzxhqs | |
| 16 | + */ | |
| 17 | +@TableName("crm_business_product") | |
| 18 | +@KeySequence("crm_business_product_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 | |
| 19 | +@Data | |
| 20 | +@EqualsAndHashCode(callSuper = true) | |
| 21 | +@ToString(callSuper = true) | |
| 22 | +@Builder | |
| 23 | +@NoArgsConstructor | |
| 24 | +@AllArgsConstructor | |
| 25 | +public class CrmBusinessProductDO extends BaseDO { | |
| 26 | + | |
| 27 | + /** | |
| 28 | + * 主键 | |
| 29 | + */ | |
| 30 | + @TableId | |
| 31 | + private Long id; | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 商机ID | |
| 35 | + * 关联 {@link CrmBusinessDO#getId()} | |
| 36 | + */ | |
| 37 | + private Long businessId; | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * 产品ID | |
| 41 | + * 关联{@link CrmProductDO#getId()} | |
| 42 | + */ | |
| 43 | + private Long productId; | |
| 44 | + | |
| 45 | + /** | |
| 46 | + * 产品单价 | |
| 47 | + */ | |
| 48 | + private BigDecimal price; | |
| 49 | + | |
| 50 | + /** | |
| 51 | + * 销售价格 | |
| 52 | + */ | |
| 53 | + private BigDecimal salesPrice; | |
| 54 | + | |
| 55 | + /** | |
| 56 | + * 数量 | |
| 57 | + */ | |
| 58 | + private BigDecimal num; | |
| 59 | + | |
| 60 | + /** | |
| 61 | + * 折扣 | |
| 62 | + */ | |
| 63 | + private BigDecimal discount; | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * 小计(折扣后价格) | |
| 67 | + */ | |
| 68 | + private BigDecimal subtotal; | |
| 69 | + | |
| 70 | + /** | |
| 71 | + * 单位 | |
| 72 | + */ | |
| 73 | + private String unit; | |
| 74 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusDO.java
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusTypeDO.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.dal.dataobject.business; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | |
| 3 | 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 4 | 5 | import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; |
| 5 | 6 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| ... | ... | @@ -43,6 +44,7 @@ public class CrmBusinessStatusTypeDO extends BaseDO { |
| 43 | 44 | * 开启状态 |
| 44 | 45 | * |
| 45 | 46 | * TODO 改成 Integer,关联 CommonStatus |
| 47 | + * {@link CommonStatusEnum} | |
| 46 | 48 | */ |
| 47 | 49 | private Boolean status; |
| 48 | 50 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.dal.mysql.business; | |
| 2 | + | |
| 3 | + | |
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 5 | +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; | |
| 6 | +import org.apache.ibatis.annotations.Mapper; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * 商机产品 Mapper | |
| 10 | + * @author lzxhqs | |
| 11 | + */ | |
| 12 | +@Mapper | |
| 13 | +public interface CrmBusinessProductMapper extends BaseMapperX<CrmBusinessProductDO> { | |
| 14 | + default void deleteByBusinessId(Long id) { | |
| 15 | + delete(CrmBusinessProductDO::getBusinessId, id); | |
| 16 | + } | |
| 17 | + | |
| 18 | + default CrmBusinessProductDO selectByBusinessId(Long id) { | |
| 19 | + return selectOne(CrmBusinessProductDO::getBusinessId, id); | |
| 20 | + } | |
| 21 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusTypeMapper.java
| ... | ... | @@ -28,4 +28,15 @@ public interface CrmBusinessStatusTypeMapper extends BaseMapperX<CrmBusinessStat |
| 28 | 28 | .eqIfPresent(CrmBusinessStatusTypeDO::getStatus, queryVO.getStatus()) |
| 29 | 29 | .inIfPresent(CrmBusinessStatusTypeDO::getId, queryVO.getIdList())); |
| 30 | 30 | } |
| 31 | + | |
| 32 | + /** | |
| 33 | + * 根据ID和name查询 | |
| 34 | + * | |
| 35 | + * @param id 商机状态类型id | |
| 36 | + * @param name 状态类型名 | |
| 37 | + * @return result | |
| 38 | + */ | |
| 39 | + default CrmBusinessStatusTypeDO selectByIdAndName(Long id, String name) { | |
| 40 | + return selectOne(CrmBusinessStatusTypeDO::getId, id, CrmBusinessStatusTypeDO::getName, name); | |
| 41 | + } | |
| 31 | 42 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
| ... | ... | @@ -63,5 +63,8 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> { |
| 63 | 63 | default Long selectCountByContactId(Long contactId) { |
| 64 | 64 | return selectCount(CrmContractDO::getContactId, contactId); |
| 65 | 65 | } |
| 66 | + default CrmContractDO selectByBizId(Long businessId) { | |
| 67 | + return selectOne(CrmContractDO::getBusinessId, businessId); | |
| 68 | + } | |
| 66 | 69 | |
| 67 | 70 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.service.business; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessCreateReqVO; | |
| 5 | -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; | |
| 6 | -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; | |
| 7 | -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessUpdateReqVO; | |
| 4 | +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.*; | |
| 8 | 5 | import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; |
| 9 | 6 | import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; |
| 10 | 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| ... | ... | @@ -27,14 +24,14 @@ public interface CrmBusinessService { |
| 27 | 24 | * @param userId 用户编号 |
| 28 | 25 | * @return 编号 |
| 29 | 26 | */ |
| 30 | - Long createBusiness(@Valid CrmBusinessCreateReqVO createReqVO, Long userId); | |
| 27 | + Long createBusiness(@Valid CrmBusinessSaveReqVO createReqVO, Long userId); | |
| 31 | 28 | |
| 32 | 29 | /** |
| 33 | 30 | * 更新商机 |
| 34 | 31 | * |
| 35 | 32 | * @param updateReqVO 更新信息 |
| 36 | 33 | */ |
| 37 | - void updateBusiness(@Valid CrmBusinessUpdateReqVO updateReqVO); | |
| 34 | + void updateBusiness(@Valid CrmBusinessSaveReqVO updateReqVO); | |
| 38 | 35 | |
| 39 | 36 | /** |
| 40 | 37 | * 删除商机 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
| ... | ... | @@ -4,14 +4,18 @@ import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.collection.ListUtil; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | 6 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 7 | -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessCreateReqVO; | |
| 8 | -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; | |
| 9 | -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; | |
| 10 | -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessUpdateReqVO; | |
| 7 | +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.*; | |
| 8 | +import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductSaveReqVO; | |
| 11 | 9 | import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; |
| 10 | +import cn.iocoder.yudao.module.crm.convert.businessproduct.CrmBusinessProductConvert; | |
| 12 | 11 | import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; |
| 12 | +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; | |
| 13 | 13 | import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; |
| 14 | +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | |
| 14 | 15 | import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; |
| 16 | +import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper; | |
| 17 | +import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessMapper; | |
| 18 | +import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; | |
| 15 | 19 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 16 | 20 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 17 | 21 | import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; |
| ... | ... | @@ -26,11 +30,14 @@ import org.springframework.stereotype.Service; |
| 26 | 30 | import org.springframework.transaction.annotation.Transactional; |
| 27 | 31 | import org.springframework.validation.annotation.Validated; |
| 28 | 32 | |
| 33 | +import java.math.BigDecimal; | |
| 34 | +import java.util.ArrayList; | |
| 29 | 35 | import java.util.Collection; |
| 30 | 36 | import java.util.List; |
| 31 | 37 | |
| 32 | 38 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 33 | 39 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 40 | +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_CONTRACT_EXISTS; | |
| 34 | 41 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS; |
| 35 | 42 | import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; |
| 36 | 43 | |
| ... | ... | @@ -47,6 +54,13 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { |
| 47 | 54 | private CrmBusinessMapper businessMapper; |
| 48 | 55 | |
| 49 | 56 | @Resource |
| 57 | + private CrmBusinessProductMapper businessProductMapper; | |
| 58 | + @Resource | |
| 59 | + private CrmContractMapper contractMapper; | |
| 60 | + | |
| 61 | + @Resource | |
| 62 | + private CrmContactBusinessMapper contactBusinessMapper; | |
| 63 | + @Resource | |
| 50 | 64 | private CrmPermissionService permissionService; |
| 51 | 65 | @Resource |
| 52 | 66 | private CrmContactBusinessService contactBusinessService; |
| ... | ... | @@ -55,29 +69,79 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { |
| 55 | 69 | @Transactional(rollbackFor = Exception.class) |
| 56 | 70 | @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_CREATE_SUB_TYPE, bizNo = "{{#business.id}}", |
| 57 | 71 | success = CRM_BUSINESS_CREATE_SUCCESS) |
| 58 | - public Long createBusiness(CrmBusinessCreateReqVO createReqVO, Long userId) { | |
| 72 | + public Long createBusiness(CrmBusinessSaveReqVO createReqVO, Long userId) { | |
| 59 | 73 | // 1. 插入商机 |
| 60 | 74 | CrmBusinessDO business = CrmBusinessConvert.INSTANCE.convert(createReqVO); |
| 61 | 75 | businessMapper.insert(business); |
| 62 | 76 | // TODO 商机待定:插入商机与产品的关联表;校验商品存在 |
| 63 | - | |
| 77 | + verifyCrmBusinessProduct(business.getId()); | |
| 78 | + if (!createReqVO.getProduct().isEmpty()) { | |
| 79 | + createBusinessProducts(createReqVO.getProduct(), business.getId()); | |
| 80 | + } | |
| 64 | 81 | // TODO 商机待定:在联系人的详情页,如果直接【新建商机】,则需要关联下。这里要搞个 CrmContactBusinessDO 表 |
| 82 | + createContactBusiness(business.getId(), createReqVO.getContactId()); | |
| 65 | 83 | |
| 66 | 84 | // 2. 创建数据权限 |
| 85 | + // 设置当前操作的人为负责人 | |
| 67 | 86 | permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()) |
| 68 | - .setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 | |
| 87 | + .setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); | |
| 69 | 88 | |
| 70 | 89 | // 4. 记录操作日志上下文 |
| 71 | 90 | LogRecordContext.putVariable("business", business); |
| 72 | 91 | return business.getId(); |
| 73 | 92 | } |
| 93 | + /** | |
| 94 | + * @param businessId 商机id | |
| 95 | + * @param contactId 联系人id | |
| 96 | + * @throws | |
| 97 | + * @description 联系人与商机的关联 | |
| 98 | + * @author lzxhqs | |
| 99 | + */ | |
| 100 | + private void createContactBusiness(Long businessId, Long contactId) { | |
| 101 | + CrmContactBusinessDO contactBusiness = new CrmContactBusinessDO(); | |
| 102 | + contactBusiness.setBusinessId(businessId); | |
| 103 | + contactBusiness.setContactId(contactId); | |
| 104 | + contactBusinessMapper.insert(contactBusiness); | |
| 105 | + | |
| 106 | + } | |
| 107 | + | |
| 108 | + /** | |
| 109 | + * @param products 产品集合 | |
| 110 | + * @description 插入商机产品关联表 | |
| 111 | + * @author lzxhqs | |
| 112 | + */ | |
| 113 | + private void createBusinessProducts(List<CrmProductSaveReqVO> products, Long businessId) { | |
| 114 | + List<CrmBusinessProductDO> list = new ArrayList<>(); | |
| 115 | + for (CrmProductSaveReqVO product : products) { | |
| 116 | + CrmBusinessProductDO businessProductDO = new CrmBusinessProductDO(); | |
| 117 | + businessProductDO.setBusinessId(businessId) | |
| 118 | + .setProductId(product.getId()) | |
| 119 | + .setPrice(BigDecimal.valueOf(product.getPrice())); | |
| 120 | + list.add(businessProductDO); | |
| 121 | + } | |
| 122 | + businessProductMapper.insertBatch(list); | |
| 123 | + } | |
| 124 | + | |
| 125 | + /** | |
| 126 | + * @param id businessId | |
| 127 | + * @description 校验管理的产品存在则删除 | |
| 128 | + * @author lzxhqs | |
| 129 | + */ | |
| 130 | + private void verifyCrmBusinessProduct(Long id) { | |
| 131 | + CrmBusinessProductDO businessProductDO = businessProductMapper.selectByBusinessId(id); | |
| 132 | + if (businessProductDO != null) { | |
| 133 | + //通过商机Id删除 | |
| 134 | + businessProductMapper.deleteByBusinessId(id); | |
| 135 | + } | |
| 136 | + | |
| 137 | + } | |
| 74 | 138 | |
| 75 | 139 | @Override |
| 76 | 140 | @Transactional(rollbackFor = Exception.class) |
| 77 | 141 | @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", |
| 78 | 142 | success = CRM_BUSINESS_UPDATE_SUCCESS) |
| 79 | 143 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) |
| 80 | - public void updateBusiness(CrmBusinessUpdateReqVO updateReqVO) { | |
| 144 | + public void updateBusiness(CrmBusinessSaveReqVO updateReqVO) { | |
| 81 | 145 | // 1. 校验存在 |
| 82 | 146 | CrmBusinessDO oldBusiness = validateBusinessExists(updateReqVO.getId()); |
| 83 | 147 | |
| ... | ... | @@ -85,6 +149,10 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { |
| 85 | 149 | CrmBusinessDO updateObj = CrmBusinessConvert.INSTANCE.convert(updateReqVO); |
| 86 | 150 | businessMapper.updateById(updateObj); |
| 87 | 151 | // TODO 商机待定:插入商机与产品的关联表;校验商品存在 |
| 152 | + verifyCrmBusinessProduct(updateReqVO.getId()); | |
| 153 | + if (!updateReqVO.getProduct().isEmpty()) { | |
| 154 | + createBusinessProducts(updateReqVO.getProduct(), updateReqVO.getId()); | |
| 155 | + } | |
| 88 | 156 | |
| 89 | 157 | // TODO @商机待定:如果状态发生变化,插入商机状态变更记录表 |
| 90 | 158 | // 3. 记录操作日志上下文 |
| ... | ... | @@ -101,6 +169,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { |
| 101 | 169 | // 校验存在 |
| 102 | 170 | CrmBusinessDO business = validateBusinessExists(id); |
| 103 | 171 | // TODO @商机待定:需要校验有没关联合同。CrmContractDO 的 businessId 字段 |
| 172 | + validateContractExists(id); | |
| 104 | 173 | |
| 105 | 174 | // 删除 |
| 106 | 175 | businessMapper.deleteById(id); |
| ... | ... | @@ -111,6 +180,19 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { |
| 111 | 180 | LogRecordContext.putVariable("businessName", business.getName()); |
| 112 | 181 | } |
| 113 | 182 | |
| 183 | + /** | |
| 184 | + * @param businessId 商机id | |
| 185 | + * @throws | |
| 186 | + * @description 删除校验合同是关联合同 | |
| 187 | + * @author lzxhqs | |
| 188 | + */ | |
| 189 | + private void validateContractExists(Long businessId) { | |
| 190 | + CrmContractDO contract = contractMapper.selectByBizId(businessId); | |
| 191 | + if(contract != null) { | |
| 192 | + throw exception(BUSINESS_CONTRACT_EXISTS); | |
| 193 | + } | |
| 194 | + } | |
| 195 | + | |
| 114 | 196 | private CrmBusinessDO validateBusinessExists(Long id) { |
| 115 | 197 | CrmBusinessDO crmBusiness = businessMapper.selectById(id); |
| 116 | 198 | if (crmBusiness == null) { | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeServiceImpl.java
| ... | ... | @@ -95,14 +95,18 @@ public class CrmBusinessStatusTypeServiceImpl implements CrmBusinessStatusTypeSe |
| 95 | 95 | |
| 96 | 96 | // TODO @ljlleo 这个方法,这个参考 validateDeptNameUnique 实现。 |
| 97 | 97 | private void validateBusinessStatusTypeExists(String name, Long id) { |
| 98 | - LambdaQueryWrapper<CrmBusinessStatusTypeDO> wrapper = new LambdaQueryWrapperX<>(); | |
| 99 | - if(null != id) { | |
| 100 | - wrapper.ne(CrmBusinessStatusTypeDO::getId, id); | |
| 101 | - } | |
| 102 | - long cnt = businessStatusTypeMapper.selectCount(wrapper.eq(CrmBusinessStatusTypeDO::getName, name)); | |
| 103 | - if (cnt > 0) { | |
| 98 | + CrmBusinessStatusTypeDO businessStatusTypeDO = businessStatusTypeMapper.selectByIdAndName(id, name); | |
| 99 | + if (businessStatusTypeDO != null) { | |
| 104 | 100 | throw exception(BUSINESS_STATUS_TYPE_NAME_EXISTS); |
| 105 | 101 | } |
| 102 | +// LambdaQueryWrapper<CrmBusinessStatusTypeDO> wrapper = new LambdaQueryWrapperX<>(); | |
| 103 | +// if(null != id) { | |
| 104 | +// wrapper.ne(CrmBusinessStatusTypeDO::getId, id); | |
| 105 | +// } | |
| 106 | +// long cnt = businessStatusTypeMapper.selectCount(wrapper.eq(CrmBusinessStatusTypeDO::getName, name)); | |
| 107 | +// if (cnt > 0) { | |
| 108 | +// throw exception(BUSINESS_STATUS_TYPE_NAME_EXISTS); | |
| 109 | +// } | |
| 106 | 110 | } |
| 107 | 111 | |
| 108 | 112 | @Override | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImplTest.java
| ... | ... | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.service.business; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 4 | 4 | import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessCreateReqVO; |
| 5 | +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO; | |
| 5 | 6 | import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessUpdateReqVO; |
| 6 | 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; |
| 7 | 8 | import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; |
| ... | ... | @@ -39,7 +40,7 @@ public class CrmBusinessServiceImplTest extends BaseDbUnitTest { |
| 39 | 40 | @Test |
| 40 | 41 | public void testCreateBusiness_success() { |
| 41 | 42 | // 准备参数 |
| 42 | - CrmBusinessCreateReqVO reqVO = randomPojo(CrmBusinessCreateReqVO.class); | |
| 43 | + CrmBusinessSaveReqVO reqVO = randomPojo(CrmBusinessSaveReqVO.class); | |
| 43 | 44 | |
| 44 | 45 | // 调用 |
| 45 | 46 | Long businessId = businessService.createBusiness(reqVO, getLoginUserId()); |
| ... | ... | @@ -56,7 +57,7 @@ public class CrmBusinessServiceImplTest extends BaseDbUnitTest { |
| 56 | 57 | CrmBusinessDO dbBusiness = randomPojo(CrmBusinessDO.class); |
| 57 | 58 | businessMapper.insert(dbBusiness);// @Sql: 先插入出一条存在的数据 |
| 58 | 59 | // 准备参数 |
| 59 | - CrmBusinessUpdateReqVO reqVO = randomPojo(CrmBusinessUpdateReqVO.class, o -> { | |
| 60 | + CrmBusinessSaveReqVO reqVO = randomPojo(CrmBusinessSaveReqVO.class, o -> { | |
| 60 | 61 | o.setId(dbBusiness.getId()); // 设置更新的 ID |
| 61 | 62 | }); |
| 62 | 63 | |
| ... | ... | @@ -70,7 +71,7 @@ public class CrmBusinessServiceImplTest extends BaseDbUnitTest { |
| 70 | 71 | @Test |
| 71 | 72 | public void testUpdateBusiness_notExists() { |
| 72 | 73 | // 准备参数 |
| 73 | - CrmBusinessUpdateReqVO reqVO = randomPojo(CrmBusinessUpdateReqVO.class); | |
| 74 | + CrmBusinessSaveReqVO reqVO = randomPojo(CrmBusinessSaveReqVO.class); | |
| 74 | 75 | |
| 75 | 76 | // 调用, 并断言异常 |
| 76 | 77 | assertServiceException(() -> businessService.updateBusiness(reqVO), BUSINESS_NOT_EXISTS); | ... | ... |