Merge branch 'develop' of https://gitee.com/aberizofur/ruoyi-vue-pro into develop
This commit is contained in:
commit
9819e05d4e
|
@ -0,0 +1,55 @@
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for crm_business_product
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `crm_business_product`;
|
||||||
|
CREATE TABLE `crm_business_product` (
|
||||||
|
`id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||||
|
`business_id` bigint(0) NOT NULL COMMENT '商机ID',
|
||||||
|
`product_id` bigint(0) NOT NULL COMMENT '产品ID',
|
||||||
|
`price` decimal(18, 2) NOT NULL COMMENT '产品单价',
|
||||||
|
`sales_price` decimal(18, 2) NULL DEFAULT NULL COMMENT '销售价格',
|
||||||
|
`num` int(0) NULL DEFAULT NULL COMMENT '数量',
|
||||||
|
`discount` decimal(10, 2) NULL DEFAULT NULL COMMENT '折扣',
|
||||||
|
`subtotal` decimal(18, 2) NULL DEFAULT NULL COMMENT '小计(折扣后价格)',
|
||||||
|
`unit` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '单位',
|
||||||
|
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||||
|
`create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||||
|
`update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间',
|
||||||
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
|
`tenant_id` bigint(0) NOT NULL DEFAULT 1 COMMENT '租户编号',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 29 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商机产品关联表' ROW_FORMAT = Dynamic;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for crm_business_status
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `crm_business_status`;
|
||||||
|
CREATE TABLE `crm_business_status` (
|
||||||
|
`id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||||
|
`type_id` bigint(0) NOT NULL COMMENT '状态类型编号',
|
||||||
|
`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '状态名',
|
||||||
|
`percent` bigint(0) NULL DEFAULT NULL COMMENT '赢单率',
|
||||||
|
`sort` int(0) NULL DEFAULT NULL COMMENT '排序',
|
||||||
|
`tenant_id` bigint(0) NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商机状态' ROW_FORMAT = Dynamic;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for crm_business_status_type
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `crm_business_status_type`;
|
||||||
|
CREATE TABLE `crm_business_status_type` (
|
||||||
|
`id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||||
|
`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '状态类型名',
|
||||||
|
`dept_ids` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '使用的部门编号',
|
||||||
|
`status` int(0) NOT NULL DEFAULT 1 COMMENT '开启状态',
|
||||||
|
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者',
|
||||||
|
`create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
|
||||||
|
`update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新时间',
|
||||||
|
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||||||
|
`tenant_id` bigint(0) NOT NULL DEFAULT 0 COMMENT '租户编号',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '商机状态类型' ROW_FORMAT = Dynamic;
|
|
@ -19,6 +19,7 @@ public interface ErrorCodeConstants {
|
||||||
|
|
||||||
// ========== 商机管理 1-020-002-000 ==========
|
// ========== 商机管理 1-020-002-000 ==========
|
||||||
ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在");
|
ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在");
|
||||||
|
ErrorCode BUSINESS_CONTRACT_EXISTS = new ErrorCode(1_020_002_001, "商机已关联合同,不能删除");
|
||||||
|
|
||||||
// TODO @lilleo:商机状态、商机类型,都单独错误码段
|
// TODO @lilleo:商机状态、商机类型,都单独错误码段
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
package cn.iocoder.yudao.module.crm.enums.business;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lzxhqs
|
||||||
|
* @version 1.0
|
||||||
|
* @title CrmBizEndStatus
|
||||||
|
* @description
|
||||||
|
* @create 2024/1/12
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum CrmBizEndStatus implements IntArrayValuable {
|
||||||
|
WIN(1, "赢单"),
|
||||||
|
LOSE(2, "输单"),
|
||||||
|
INVALID(3, "无效");
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBizEndStatus::getStatus).toArray();
|
||||||
|
|
||||||
|
public static boolean isWin(Integer status) {
|
||||||
|
return ObjectUtil.equal(WIN.getStatus(), status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isLose(Integer status) {
|
||||||
|
return ObjectUtil.equal(LOSE.getStatus(), status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isInvalid(Integer status) {
|
||||||
|
return ObjectUtil.equal(INVALID.getStatus(), status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 场景类型
|
||||||
|
*/
|
||||||
|
private final Integer status;
|
||||||
|
/**
|
||||||
|
* 场景名称
|
||||||
|
*/
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,11 @@
|
||||||
<artifactId>yudao-module-system-api</artifactId>
|
<artifactId>yudao-module-system-api</artifactId>
|
||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<artifactId>yudao-module-system-biz</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.iocoder.boot</groupId>
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
<artifactId>yudao-module-crm-api</artifactId>
|
<artifactId>yudao-module-crm-api</artifactId>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
||||||
|
@ -101,11 +102,12 @@ public class CrmBusinessStatusTypeController {
|
||||||
PageResult<CrmBusinessStatusTypeDO> pageResult = businessStatusTypeService.getBusinessStatusTypePage(pageReqVO);
|
PageResult<CrmBusinessStatusTypeDO> pageResult = businessStatusTypeService.getBusinessStatusTypePage(pageReqVO);
|
||||||
// 处理部门回显
|
// 处理部门回显
|
||||||
// TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈;
|
// TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈;
|
||||||
Set<Long> deptIds = pageResult.getList().stream()
|
// Set<Long> deptIds = pageResult.getList().stream()
|
||||||
.map(CrmBusinessStatusTypeDO::getDeptIds)
|
// .map(CrmBusinessStatusTypeDO::getDeptIds)
|
||||||
.filter(Objects::nonNull)
|
// .filter(Objects::nonNull)
|
||||||
.flatMap(Collection::stream)
|
// .flatMap(Collection::stream)
|
||||||
.collect(Collectors.toSet());
|
// .collect(Collectors.toSet());
|
||||||
|
Set<Long> deptIds = CollectionUtils.convertSetByFlatMap(pageResult.getList(), CrmBusinessStatusTypeDO::getDeptIds,Collection::stream);
|
||||||
List<DeptRespDTO> deptList = deptApi.getDeptList(deptIds);
|
List<DeptRespDTO> deptList = deptApi.getDeptList(deptIds);
|
||||||
return success(CrmBusinessStatusTypeConvert.INSTANCE.convertPage(pageResult, deptList));
|
return success(CrmBusinessStatusTypeConvert.INSTANCE.convertPage(pageResult, deptList));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
|
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||||
|
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.product.CrmBusinessProductSaveReqVO;
|
||||||
|
import cn.iocoder.yudao.module.crm.enums.business.CrmBizEndStatus;
|
||||||
import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerParseFunction;
|
import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerParseFunction;
|
||||||
import com.mzt.logapi.starter.annotation.DiffLogField;
|
import com.mzt.logapi.starter.annotation.DiffLogField;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
@ -9,6 +12,8 @@ import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||||
|
|
||||||
|
@ -66,7 +71,17 @@ public class CrmBusinessSaveReqVO {
|
||||||
@Schema(description = "备注", example = "随便")
|
@Schema(description = "备注", example = "随便")
|
||||||
@DiffLogField(name = "备注")
|
@DiffLogField(name = "备注")
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
// TODO @ljileo:修改的时候,应该可以传递添加的产品;
|
// TODO @ljileo:修改的时候,应该可以传递添加的产品;
|
||||||
|
@Schema(description = "联系人编号", example = "110")
|
||||||
|
@NotNull(message = "联系人编号不能为空")
|
||||||
|
private Long contactId;
|
||||||
|
|
||||||
|
@Schema(description = "1赢单2输单3无效", example = "1")
|
||||||
|
@InEnum(CrmBizEndStatus.class)
|
||||||
|
private Integer endStatus;
|
||||||
|
|
||||||
|
@Schema(description = "商机产品列表", example = "")
|
||||||
|
private List<CrmBusinessProductSaveReqVO> products = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.product;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lzxhqs
|
||||||
|
*/
|
||||||
|
@Schema(description = "管理后台 - 商机产品分页 Request VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
public class CrmBusinessProductPageReqVO extends PageParam {
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.product;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lzxhqs
|
||||||
|
*/
|
||||||
|
@Schema(description = "管理后台 - 商机产品关联 Response VO")
|
||||||
|
@Data
|
||||||
|
@ExcelIgnoreUnannotated
|
||||||
|
public class CrmBusinessProductRespVO {
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package cn.iocoder.yudao.module.crm.controller.admin.business.vo.product;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lzxhqs
|
||||||
|
*/
|
||||||
|
@Schema(description = "管理后台 - CRM 商机产品关联表 创建/更新 Request VO")
|
||||||
|
@Data
|
||||||
|
public class CrmBusinessProductSaveReqVO {
|
||||||
|
|
||||||
|
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "商机ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
|
||||||
|
@NotNull(message = "商机ID不能为空")
|
||||||
|
private Integer businessId;
|
||||||
|
|
||||||
|
@Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
|
||||||
|
@NotNull(message = "产品ID不能为空")
|
||||||
|
private Integer productId;
|
||||||
|
|
||||||
|
@Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
|
||||||
|
@NotNull(message = "产品单价不能为空")
|
||||||
|
private BigDecimal price;
|
||||||
|
|
||||||
|
@Schema(description = "销售价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
|
||||||
|
@NotNull(message = "销售价格不能为空")
|
||||||
|
private BigDecimal salesPrice;
|
||||||
|
|
||||||
|
@Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
|
||||||
|
@NotNull(message = "数量不能为空")
|
||||||
|
private BigDecimal num;
|
||||||
|
|
||||||
|
@Schema(description = "折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
|
||||||
|
@NotNull(message = "折扣不能为空")
|
||||||
|
private BigDecimal discount;
|
||||||
|
|
||||||
|
@Schema(description = "小计(折扣后价格)", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
|
||||||
|
@NotNull(message = "小计(折扣后价格)不能为空")
|
||||||
|
private BigDecimal subtotal;
|
||||||
|
|
||||||
|
@Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320")
|
||||||
|
@NotNull(message = "单位不能为空")
|
||||||
|
private String unit;
|
||||||
|
}
|
|
@ -24,6 +24,6 @@ public class CrmBusinessStatusTypeSaveReqVO {
|
||||||
|
|
||||||
// TODO @ljlleo VO 里面,我们不使用默认值哈。这里 Lists.newArrayList() 看看怎么去掉。上面 deptIds 也是类似噢
|
// TODO @ljlleo VO 里面,我们不使用默认值哈。这里 Lists.newArrayList() 看看怎么去掉。上面 deptIds 也是类似噢
|
||||||
@Schema(description = "商机状态集合", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "商机状态集合", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private List<CrmBusinessStatusSaveReqVO> statusList = Lists.newArrayList();
|
private List<CrmBusinessStatusSaveReqVO> statusList;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package cn.iocoder.yudao.module.crm.convert.businessproduct;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.product.CrmBusinessProductSaveReqVO;
|
||||||
|
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lzxhqs
|
||||||
|
* @version 1.0
|
||||||
|
* @title CrmBusinessProductConvert
|
||||||
|
* @description
|
||||||
|
* @create 2024/1/12
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface CrmBusinessProductConvert {
|
||||||
|
CrmBusinessProductConvert INSTANCE = Mappers.getMapper(CrmBusinessProductConvert.class);
|
||||||
|
|
||||||
|
CrmBusinessProductDO convert(CrmBusinessProductSaveReqVO product);
|
||||||
|
}
|
|
@ -39,9 +39,9 @@ public interface CrmBusinessStatusTypeConvert {
|
||||||
|
|
||||||
default CrmBusinessStatusTypeRespVO convert(CrmBusinessStatusTypeDO bean, List<CrmBusinessStatusDO> statusList) {
|
default CrmBusinessStatusTypeRespVO convert(CrmBusinessStatusTypeDO bean, List<CrmBusinessStatusDO> statusList) {
|
||||||
// TODO @ljlleo 可以链式赋值,简化成一行;
|
// TODO @ljlleo 可以链式赋值,简化成一行;
|
||||||
CrmBusinessStatusTypeRespVO result = convert(bean);
|
// CrmBusinessStatusTypeRespVO result = convert(bean);
|
||||||
result.setStatusList(statusList);
|
// result.setStatusList(statusList);
|
||||||
return result;
|
return convert(bean).setStatusList(statusList);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package cn.iocoder.yudao.module.crm.dal.dataobject.business;
|
package cn.iocoder.yudao.module.crm.dal.dataobject.business;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
|
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
|
||||||
|
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
@ -52,6 +54,7 @@ public class CrmBusinessDO extends BaseDO {
|
||||||
* 客户编号
|
* 客户编号
|
||||||
*
|
*
|
||||||
* TODO @ljileo:这个字段,后续要写下关联的实体哈
|
* TODO @ljileo:这个字段,后续要写下关联的实体哈
|
||||||
|
* 关联 {@link CrmCustomerDO#getId()}
|
||||||
*/
|
*/
|
||||||
private Long customerId;
|
private Long customerId;
|
||||||
/**
|
/**
|
||||||
|
@ -101,6 +104,7 @@ public class CrmBusinessDO extends BaseDO {
|
||||||
* 负责人的用户编号
|
* 负责人的用户编号
|
||||||
*
|
*
|
||||||
* 关联 AdminUserDO 的 id 字段
|
* 关联 AdminUserDO 的 id 字段
|
||||||
|
* {@link AdminUserDO#getId()}
|
||||||
*/
|
*/
|
||||||
private Long ownerUserId;
|
private Long ownerUserId;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
package cn.iocoder.yudao.module.crm.dal.dataobject.business;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
|
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
|
||||||
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商机产品关联表 DO
|
||||||
|
*
|
||||||
|
* @author lzxhqs
|
||||||
|
*/
|
||||||
|
@TableName("crm_business_product")
|
||||||
|
@KeySequence("crm_business_product_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class CrmBusinessProductDO extends BaseDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键
|
||||||
|
*/
|
||||||
|
@TableId
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商机ID
|
||||||
|
* 关联 {@link CrmBusinessDO#getId()}
|
||||||
|
*/
|
||||||
|
private Long businessId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品ID
|
||||||
|
* 关联{@link CrmProductDO#getId()}
|
||||||
|
*/
|
||||||
|
private Long productId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品单价
|
||||||
|
*/
|
||||||
|
private BigDecimal price;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 销售价格
|
||||||
|
*/
|
||||||
|
private BigDecimal salesPrice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数量
|
||||||
|
*/
|
||||||
|
private BigDecimal num;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 折扣
|
||||||
|
*/
|
||||||
|
private BigDecimal discount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小计(折扣后价格)
|
||||||
|
*/
|
||||||
|
private BigDecimal subtotal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单位
|
||||||
|
*/
|
||||||
|
private String unit;
|
||||||
|
}
|
|
@ -39,7 +39,7 @@ public class CrmBusinessStatusDO {
|
||||||
*
|
*
|
||||||
* TODO 这里是不是改成 Integer 存储,百分比 * 100 ;
|
* TODO 这里是不是改成 Integer 存储,百分比 * 100 ;
|
||||||
*/
|
*/
|
||||||
private String percent;
|
private Integer percent;
|
||||||
/**
|
/**
|
||||||
* 排序
|
* 排序
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.crm.dal.dataobject.business;
|
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.dataobject.BaseDO;
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
|
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
|
||||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
|
@ -43,6 +44,7 @@ public class CrmBusinessStatusTypeDO extends BaseDO {
|
||||||
* 开启状态
|
* 开启状态
|
||||||
*
|
*
|
||||||
* TODO 改成 Integer,关联 CommonStatus
|
* TODO 改成 Integer,关联 CommonStatus
|
||||||
|
* {@link CommonStatusEnum}
|
||||||
*/
|
*/
|
||||||
private Boolean status;
|
private Boolean status;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package cn.iocoder.yudao.module.crm.dal.mysql.business;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商机产品 Mapper
|
||||||
|
* @author lzxhqs
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface CrmBusinessProductMapper extends BaseMapperX<CrmBusinessProductDO> {
|
||||||
|
default void deleteByBusinessId(Long id) {
|
||||||
|
delete(CrmBusinessProductDO::getBusinessId, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
default CrmBusinessProductDO selectByBusinessId(Long id) {
|
||||||
|
return selectOne(CrmBusinessProductDO::getBusinessId, id);
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,4 +28,15 @@ public interface CrmBusinessStatusTypeMapper extends BaseMapperX<CrmBusinessStat
|
||||||
.eqIfPresent(CrmBusinessStatusTypeDO::getStatus, queryVO.getStatus())
|
.eqIfPresent(CrmBusinessStatusTypeDO::getStatus, queryVO.getStatus())
|
||||||
.inIfPresent(CrmBusinessStatusTypeDO::getId, queryVO.getIdList()));
|
.inIfPresent(CrmBusinessStatusTypeDO::getId, queryVO.getIdList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID和name查询
|
||||||
|
*
|
||||||
|
* @param id 商机状态类型id
|
||||||
|
* @param name 状态类型名
|
||||||
|
* @return result
|
||||||
|
*/
|
||||||
|
default CrmBusinessStatusTypeDO selectByIdAndName(Long id, String name) {
|
||||||
|
return selectOne(CrmBusinessStatusTypeDO::getId, id, CrmBusinessStatusTypeDO::getName, name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,5 +63,8 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> {
|
||||||
default Long selectCountByContactId(Long contactId) {
|
default Long selectCountByContactId(Long contactId) {
|
||||||
return selectCount(CrmContractDO::getContactId, contactId);
|
return selectCount(CrmContractDO::getContactId, contactId);
|
||||||
}
|
}
|
||||||
|
default CrmContractDO selectByBizId(Long businessId) {
|
||||||
|
return selectOne(CrmContractDO::getBusinessId, businessId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,18 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO;
|
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO;
|
||||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
|
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
|
||||||
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
|
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
|
||||||
|
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.product.CrmBusinessProductSaveReqVO;
|
||||||
|
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductSaveReqVO;
|
||||||
import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert;
|
import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert;
|
||||||
|
import cn.iocoder.yudao.module.crm.convert.businessproduct.CrmBusinessProductConvert;
|
||||||
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
|
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
|
||||||
|
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
|
||||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
|
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
|
||||||
|
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
|
||||||
import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper;
|
import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper;
|
||||||
|
import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper;
|
||||||
|
import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessMapper;
|
||||||
|
import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper;
|
||||||
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
|
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
|
||||||
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
|
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
|
||||||
import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission;
|
import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission;
|
||||||
|
@ -25,11 +33,14 @@ import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
|
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_CONTRACT_EXISTS;
|
||||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS;
|
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS;
|
||||||
import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
|
import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
|
||||||
|
|
||||||
|
@ -45,6 +56,13 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||||
@Resource
|
@Resource
|
||||||
private CrmBusinessMapper businessMapper;
|
private CrmBusinessMapper businessMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CrmBusinessProductMapper businessProductMapper;
|
||||||
|
@Resource
|
||||||
|
private CrmContractMapper contractMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CrmContactBusinessMapper contactBusinessMapper;
|
||||||
@Resource
|
@Resource
|
||||||
private CrmPermissionService permissionService;
|
private CrmPermissionService permissionService;
|
||||||
@Resource
|
@Resource
|
||||||
|
@ -61,17 +79,65 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||||
.setOwnerUserId(userId);
|
.setOwnerUserId(userId);
|
||||||
businessMapper.insert(business);
|
businessMapper.insert(business);
|
||||||
// TODO 商机待定:插入商机与产品的关联表;校验商品存在
|
// TODO 商机待定:插入商机与产品的关联表;校验商品存在
|
||||||
|
verifyCrmBusinessProduct(business.getId());
|
||||||
|
if (!createReqVO.getProducts().isEmpty()) {
|
||||||
|
createBusinessProducts(createReqVO.getProducts(), business.getId());
|
||||||
|
}
|
||||||
// TODO 商机待定:在联系人的详情页,如果直接【新建商机】,则需要关联下。这里要搞个 CrmContactBusinessDO 表
|
// TODO 商机待定:在联系人的详情页,如果直接【新建商机】,则需要关联下。这里要搞个 CrmContactBusinessDO 表
|
||||||
|
createContactBusiness(business.getId(), createReqVO.getContactId());
|
||||||
|
|
||||||
// 2. 创建数据权限
|
// 2. 创建数据权限
|
||||||
|
// 设置当前操作的人为负责人
|
||||||
permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())
|
permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())
|
||||||
.setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人
|
.setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
|
||||||
|
|
||||||
// 4. 记录操作日志上下文
|
// 4. 记录操作日志上下文
|
||||||
LogRecordContext.putVariable("business", business);
|
LogRecordContext.putVariable("business", business);
|
||||||
return business.getId();
|
return business.getId();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @param businessId 商机id
|
||||||
|
* @param contactId 联系人id
|
||||||
|
* @throws
|
||||||
|
* @description 联系人与商机的关联
|
||||||
|
* @author lzxhqs
|
||||||
|
*/
|
||||||
|
private void createContactBusiness(Long businessId, Long contactId) {
|
||||||
|
CrmContactBusinessDO contactBusiness = new CrmContactBusinessDO();
|
||||||
|
contactBusiness.setBusinessId(businessId);
|
||||||
|
contactBusiness.setContactId(contactId);
|
||||||
|
contactBusinessMapper.insert(contactBusiness);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param products 产品集合
|
||||||
|
* @description 插入商机产品关联表
|
||||||
|
* @author lzxhqs
|
||||||
|
*/
|
||||||
|
private void createBusinessProducts(List<CrmBusinessProductSaveReqVO> products, Long businessId) {
|
||||||
|
List<CrmBusinessProductDO> list = new ArrayList<>();
|
||||||
|
for (CrmBusinessProductSaveReqVO product : products) {
|
||||||
|
CrmBusinessProductDO businessProductDO = CrmBusinessProductConvert.INSTANCE.convert(product);
|
||||||
|
businessProductDO.setBusinessId(businessId);
|
||||||
|
list.add(businessProductDO);
|
||||||
|
}
|
||||||
|
businessProductMapper.insertBatch(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id businessId
|
||||||
|
* @description 校验管理的产品存在则删除
|
||||||
|
* @author lzxhqs
|
||||||
|
*/
|
||||||
|
private void verifyCrmBusinessProduct(Long id) {
|
||||||
|
CrmBusinessProductDO businessProductDO = businessProductMapper.selectByBusinessId(id);
|
||||||
|
if (businessProductDO != null) {
|
||||||
|
//通过商机Id删除
|
||||||
|
businessProductMapper.deleteByBusinessId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
@ -86,6 +152,10 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||||
CrmBusinessDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessDO.class);
|
CrmBusinessDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessDO.class);
|
||||||
businessMapper.updateById(updateObj);
|
businessMapper.updateById(updateObj);
|
||||||
// TODO 商机待定:插入商机与产品的关联表;校验商品存在
|
// TODO 商机待定:插入商机与产品的关联表;校验商品存在
|
||||||
|
verifyCrmBusinessProduct(updateReqVO.getId());
|
||||||
|
if (!updateReqVO.getProducts().isEmpty()) {
|
||||||
|
createBusinessProducts(updateReqVO.getProducts(), updateReqVO.getId());
|
||||||
|
}
|
||||||
|
|
||||||
// TODO @商机待定:如果状态发生变化,插入商机状态变更记录表
|
// TODO @商机待定:如果状态发生变化,插入商机状态变更记录表
|
||||||
// 3. 记录操作日志上下文
|
// 3. 记录操作日志上下文
|
||||||
|
@ -102,6 +172,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||||
// 校验存在
|
// 校验存在
|
||||||
CrmBusinessDO business = validateBusinessExists(id);
|
CrmBusinessDO business = validateBusinessExists(id);
|
||||||
// TODO @商机待定:需要校验有没关联合同。CrmContractDO 的 businessId 字段
|
// TODO @商机待定:需要校验有没关联合同。CrmContractDO 的 businessId 字段
|
||||||
|
validateContractExists(id);
|
||||||
|
|
||||||
// 删除
|
// 删除
|
||||||
businessMapper.deleteById(id);
|
businessMapper.deleteById(id);
|
||||||
|
@ -112,6 +183,19 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
|
||||||
LogRecordContext.putVariable("businessName", business.getName());
|
LogRecordContext.putVariable("businessName", business.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param businessId 商机id
|
||||||
|
* @throws
|
||||||
|
* @description 删除校验合同是关联合同
|
||||||
|
* @author lzxhqs
|
||||||
|
*/
|
||||||
|
private void validateContractExists(Long businessId) {
|
||||||
|
CrmContractDO contract = contractMapper.selectByBizId(businessId);
|
||||||
|
if(contract != null) {
|
||||||
|
throw exception(BUSINESS_CONTRACT_EXISTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private CrmBusinessDO validateBusinessExists(Long id) {
|
private CrmBusinessDO validateBusinessExists(Long id) {
|
||||||
CrmBusinessDO crmBusiness = businessMapper.selectById(id);
|
CrmBusinessDO crmBusiness = businessMapper.selectById(id);
|
||||||
if (crmBusiness == null) {
|
if (crmBusiness == null) {
|
||||||
|
|
|
@ -95,14 +95,18 @@ public class CrmBusinessStatusTypeServiceImpl implements CrmBusinessStatusTypeSe
|
||||||
|
|
||||||
// TODO @ljlleo 这个方法,这个参考 validateDeptNameUnique 实现。
|
// TODO @ljlleo 这个方法,这个参考 validateDeptNameUnique 实现。
|
||||||
private void validateBusinessStatusTypeExists(String name, Long id) {
|
private void validateBusinessStatusTypeExists(String name, Long id) {
|
||||||
LambdaQueryWrapper<CrmBusinessStatusTypeDO> wrapper = new LambdaQueryWrapperX<>();
|
CrmBusinessStatusTypeDO businessStatusTypeDO = businessStatusTypeMapper.selectByIdAndName(id, name);
|
||||||
if(null != id) {
|
if (businessStatusTypeDO != null) {
|
||||||
wrapper.ne(CrmBusinessStatusTypeDO::getId, id);
|
|
||||||
}
|
|
||||||
long cnt = businessStatusTypeMapper.selectCount(wrapper.eq(CrmBusinessStatusTypeDO::getName, name));
|
|
||||||
if (cnt > 0) {
|
|
||||||
throw exception(BUSINESS_STATUS_TYPE_NAME_EXISTS);
|
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
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue