mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 20:28:44 +08:00 
			
		
		
		
	
							
								
								
									
										39
									
								
								sql/mysql/crm.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								sql/mysql/crm.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
SET NAMES utf8mb4;
 | 
			
		||||
 | 
			
		||||
-- ----------------------------
 | 
			
		||||
-- 合同表
 | 
			
		||||
-- ----------------------------
 | 
			
		||||
DROP TABLE IF EXISTS `crm_contract`;
 | 
			
		||||
CREATE TABLE `crm_contract`
 | 
			
		||||
(
 | 
			
		||||
    `id`                  bigint                                                        NOT NULL AUTO_INCREMENT COMMENT '编号,主键自增',
 | 
			
		||||
    `name`                varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '合同名称',
 | 
			
		||||
    `customer_id`         bigint                                                                 DEFAULT NULL COMMENT '客户编号',
 | 
			
		||||
    `business_id`         bigint                                                                 DEFAULT NULL COMMENT '商机编号',
 | 
			
		||||
    `process_instance_id` bigint                                                                 DEFAULT NULL COMMENT '工作流编号',
 | 
			
		||||
    `order_date`          datetime                                                               DEFAULT NULL COMMENT '下单日期',
 | 
			
		||||
    `owner_user_id`       bigint                                                                 DEFAULT NULL COMMENT '负责人的用户编号',
 | 
			
		||||
    `no`                  varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci          DEFAULT NULL COMMENT '合同编号',
 | 
			
		||||
    `start_time`          datetime                                                               DEFAULT NULL COMMENT '开始时间',
 | 
			
		||||
    `end_time`            datetime                                                               DEFAULT NULL COMMENT '结束时间',
 | 
			
		||||
    `price`               int                                                                    DEFAULT NULL COMMENT '合同金额',
 | 
			
		||||
    `discount_percent`    int                                                                    DEFAULT NULL COMMENT '整单折扣',
 | 
			
		||||
    `product_price`       int                                                                    DEFAULT NULL COMMENT '产品总金额',
 | 
			
		||||
    `ro_user_ids`         varchar(4096)                                                          DEFAULT NULL COMMENT '只读权限的用户编号数组',
 | 
			
		||||
    `rw_user_ids`         varchar(4096)                                                          DEFAULT NULL COMMENT '读写权限的用户编号数组',
 | 
			
		||||
    `contact_id`          bigint                                                                 DEFAULT NULL COMMENT '联系人编号',
 | 
			
		||||
    `sign_user_id`        bigint                                                                 DEFAULT NULL COMMENT '公司签约人',
 | 
			
		||||
    `contact_last_time`   datetime                                                               DEFAULT NULL COMMENT '最后跟进时间',
 | 
			
		||||
 | 
			
		||||
    -- 通用字段
 | 
			
		||||
    `remark`              varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL     DEFAULT NULL COMMENT '备注',
 | 
			
		||||
    `creator`             varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci  NULL     DEFAULT '' COMMENT '创建者',
 | 
			
		||||
    `create_time`         datetime                                                      NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
 | 
			
		||||
    `updater`             varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci  NULL     DEFAULT '' COMMENT '更新者',
 | 
			
		||||
    `update_time`         datetime                                                      NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
 | 
			
		||||
    `deleted`             bit(1)                                                        NOT NULL DEFAULT b'0' COMMENT '是否删除',
 | 
			
		||||
    `tenant_id`           bigint                                                        NOT NULL DEFAULT 0 COMMENT '租户编号',
 | 
			
		||||
    PRIMARY KEY (`id`) USING BTREE
 | 
			
		||||
) ENGINE = InnoDB
 | 
			
		||||
  CHARACTER SET = utf8mb4
 | 
			
		||||
  COLLATE = utf8mb4_unicode_ci COMMENT ='合同表';
 | 
			
		||||
							
								
								
									
										63
									
								
								sql/mysql/crm_menu.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								sql/mysql/crm_menu.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
-- ----------------------------
 | 
			
		||||
-- 合同菜单
 | 
			
		||||
-- ----------------------------
 | 
			
		||||
 | 
			
		||||
-- 菜单 SQL
 | 
			
		||||
INSERT INTO system_menu(
 | 
			
		||||
    name, permission, type, sort, parent_id,
 | 
			
		||||
    path, icon, component, status, component_name
 | 
			
		||||
)
 | 
			
		||||
VALUES (
 | 
			
		||||
    '合同管理', '', 2, 0, 1254,
 | 
			
		||||
    'contract', '', 'crm/contract/index', 0, 'Contract'
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
-- 按钮父菜单ID
 | 
			
		||||
-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码
 | 
			
		||||
SELECT @parentId := LAST_INSERT_ID();
 | 
			
		||||
 | 
			
		||||
-- 按钮 SQL
 | 
			
		||||
INSERT INTO system_menu(
 | 
			
		||||
    name, permission, type, sort, parent_id,
 | 
			
		||||
    path, icon, component, status
 | 
			
		||||
)
 | 
			
		||||
VALUES (
 | 
			
		||||
    '合同查询', 'crm:contract:query', 3, 1, @parentId,
 | 
			
		||||
    '', '', '', 0
 | 
			
		||||
);
 | 
			
		||||
INSERT INTO system_menu(
 | 
			
		||||
    name, permission, type, sort, parent_id,
 | 
			
		||||
    path, icon, component, status
 | 
			
		||||
)
 | 
			
		||||
VALUES (
 | 
			
		||||
    '合同创建', 'crm:contract:create', 3, 2, @parentId,
 | 
			
		||||
    '', '', '', 0
 | 
			
		||||
);
 | 
			
		||||
INSERT INTO system_menu(
 | 
			
		||||
    name, permission, type, sort, parent_id,
 | 
			
		||||
    path, icon, component, status
 | 
			
		||||
)
 | 
			
		||||
VALUES (
 | 
			
		||||
    '合同更新', 'crm:contract:update', 3, 3, @parentId,
 | 
			
		||||
    '', '', '', 0
 | 
			
		||||
);
 | 
			
		||||
INSERT INTO system_menu(
 | 
			
		||||
    name, permission, type, sort, parent_id,
 | 
			
		||||
    path, icon, component, status
 | 
			
		||||
)
 | 
			
		||||
VALUES (
 | 
			
		||||
    '合同删除', 'crm:contract:delete', 3, 4, @parentId,
 | 
			
		||||
    '', '', '', 0
 | 
			
		||||
);
 | 
			
		||||
INSERT INTO system_menu(
 | 
			
		||||
    name, permission, type, sort, parent_id,
 | 
			
		||||
    path, icon, component, status
 | 
			
		||||
)
 | 
			
		||||
VALUES (
 | 
			
		||||
    '合同导出', 'crm:contract:export', 3, 5, @parentId,
 | 
			
		||||
    '', '', '', 0
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
-- ----------------------------
 | 
			
		||||
-- ...菜单
 | 
			
		||||
-- ----------------------------
 | 
			
		||||
@@ -1,5 +1,7 @@
 | 
			
		||||
package cn.iocoder.yudao.module.crm.enums;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * CRM 错误码枚举类
 | 
			
		||||
 * <p>
 | 
			
		||||
@@ -7,6 +9,7 @@ package cn.iocoder.yudao.module.crm.enums;
 | 
			
		||||
 */
 | 
			
		||||
public interface ErrorCodeConstants {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // ========== 合同管理 1-020-000-000 ==========
 | 
			
		||||
    ErrorCode CONTRACT_NOT_EXISTS = new ErrorCode(1_020_000_000, "合同不存在");
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
 | 
			
		||||
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 | 
			
		||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 | 
			
		||||
         xmlns="http://maven.apache.org/POM/4.0.0"
 | 
			
		||||
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 | 
			
		||||
    <parent>
 | 
			
		||||
        <groupId>cn.iocoder.boot</groupId>
 | 
			
		||||
@@ -22,6 +22,11 @@
 | 
			
		||||
            <artifactId>yudao-module-system-api</artifactId>
 | 
			
		||||
            <version>${revision}</version>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>cn.iocoder.boot</groupId>
 | 
			
		||||
            <artifactId>yudao-module-crm-api</artifactId>
 | 
			
		||||
            <version>${revision}</version>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- 业务组件 -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
@@ -46,6 +51,12 @@
 | 
			
		||||
            <artifactId>yudao-spring-boot-starter-mybatis</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- 工具类相关 -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>cn.iocoder.boot</groupId>
 | 
			
		||||
            <artifactId>yudao-spring-boot-starter-excel</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <!-- Test 测试相关 -->
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>cn.iocoder.boot</groupId>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * 联系人
 | 
			
		||||
 */
 | 
			
		||||
package cn.iocoder.yudao.module.crm.controller.admin.contact;
 | 
			
		||||
@@ -0,0 +1,99 @@
 | 
			
		||||
package cn.iocoder.yudao.module.crm.controller.admin.contract;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
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.contract.vo.*;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.convert.contract.ContractConvert;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.service.contract.ContractService;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Parameter;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Resource;
 | 
			
		||||
import javax.servlet.http.HttpServletResponse;
 | 
			
		||||
import javax.validation.Valid;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 | 
			
		||||
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
 | 
			
		||||
 | 
			
		||||
@Tag(name = "管理后台 - 合同")
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/crm/contract")
 | 
			
		||||
@Validated
 | 
			
		||||
public class ContractController {
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private ContractService contractService;
 | 
			
		||||
 | 
			
		||||
    @PostMapping("/create")
 | 
			
		||||
    @Operation(summary = "创建合同")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermission('crm:contract:create')")
 | 
			
		||||
    public CommonResult<Long> createContract(@Valid @RequestBody ContractCreateReqVO createReqVO) {
 | 
			
		||||
        return success(contractService.createContract(createReqVO));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PutMapping("/update")
 | 
			
		||||
    @Operation(summary = "更新合同")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermission('crm:contract:update')")
 | 
			
		||||
    public CommonResult<Boolean> updateContract(@Valid @RequestBody ContractUpdateReqVO updateReqVO) {
 | 
			
		||||
        contractService.updateContract(updateReqVO);
 | 
			
		||||
        return success(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @DeleteMapping("/delete")
 | 
			
		||||
    @Operation(summary = "删除合同")
 | 
			
		||||
    @Parameter(name = "id", description = "编号", required = true)
 | 
			
		||||
    @PreAuthorize("@ss.hasPermission('crm:contract:delete')")
 | 
			
		||||
    public CommonResult<Boolean> deleteContract(@RequestParam("id") Long id) {
 | 
			
		||||
        contractService.deleteContract(id);
 | 
			
		||||
        return success(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/get")
 | 
			
		||||
    @Operation(summary = "获得合同")
 | 
			
		||||
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermission('crm:contract:query')")
 | 
			
		||||
    public CommonResult<ContractRespVO> getContract(@RequestParam("id") Long id) {
 | 
			
		||||
        ContractDO contract = contractService.getContract(id);
 | 
			
		||||
        return success(ContractConvert.INSTANCE.convert(contract));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/list")
 | 
			
		||||
    @Operation(summary = "获得合同列表")
 | 
			
		||||
    @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermission('crm:contract:query')")
 | 
			
		||||
    public CommonResult<List<ContractRespVO>> getContractList(@RequestParam("ids") Collection<Long> ids) {
 | 
			
		||||
        List<ContractDO> list = contractService.getContractList(ids);
 | 
			
		||||
        return success(ContractConvert.INSTANCE.convertList(list));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/page")
 | 
			
		||||
    @Operation(summary = "获得合同分页")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermission('crm:contract:query')")
 | 
			
		||||
    public CommonResult<PageResult<ContractRespVO>> getContractPage(@Valid ContractPageReqVO pageVO) {
 | 
			
		||||
        PageResult<ContractDO> pageResult = contractService.getContractPage(pageVO);
 | 
			
		||||
        return success(ContractConvert.INSTANCE.convertPage(pageResult));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/export-excel")
 | 
			
		||||
    @Operation(summary = "导出合同 Excel")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermission('crm:contract:export')")
 | 
			
		||||
    @OperateLog(type = EXPORT)
 | 
			
		||||
    public void exportContractExcel(@Valid ContractExportReqVO exportReqVO,
 | 
			
		||||
                                    HttpServletResponse response) throws IOException {
 | 
			
		||||
        List<ContractDO> list = contractService.getContractList(exportReqVO);
 | 
			
		||||
        // 导出 Excel
 | 
			
		||||
        List<ContractExcelVO> datas = ContractConvert.INSTANCE.convertList02(list);
 | 
			
		||||
        ExcelUtils.write(response, "合同.xls", "数据", ContractExcelVO.class, datas);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,72 @@
 | 
			
		||||
package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
 | 
			
		||||
 | 
			
		||||
import io.swagger.v3.oas.annotations.media.Schema;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import org.springframework.format.annotation.DateTimeFormat;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.NotNull;
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 合同 Base VO,提供给添加、修改、详细的子 VO 使用
 | 
			
		||||
 * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
public class ContractBaseVO {
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "合同名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
 | 
			
		||||
    @NotNull(message = "合同名称不能为空")
 | 
			
		||||
    private String name;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "客户编号", example = "18336")
 | 
			
		||||
    private Long customerId;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "商机编号", example = "10864")
 | 
			
		||||
    private Long businessId;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "工作流编号", example = "1043")
 | 
			
		||||
    private Long processInstanceId;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "下单日期")
 | 
			
		||||
    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
 | 
			
		||||
    private LocalDateTime orderDate;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "负责人的用户编号", example = "17144")
 | 
			
		||||
    private Long ownerUserId;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "合同编号")
 | 
			
		||||
    private String no;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "开始时间")
 | 
			
		||||
    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
 | 
			
		||||
    private LocalDateTime startTime;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "结束时间")
 | 
			
		||||
    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
 | 
			
		||||
    private LocalDateTime endTime;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "合同金额", example = "5617")
 | 
			
		||||
    private Integer price;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "整单折扣")
 | 
			
		||||
    private Integer discountPercent;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "产品总金额", example = "19510")
 | 
			
		||||
    private Integer productPrice;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "联系人编号", example = "18546")
 | 
			
		||||
    private Long contactId;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "公司签约人", example = "14036")
 | 
			
		||||
    private Long signUserId;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "最后跟进时间")
 | 
			
		||||
    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
 | 
			
		||||
    private LocalDateTime contactLastTime;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "备注", example = "你猜")
 | 
			
		||||
    private String remark;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,20 @@
 | 
			
		||||
package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
 | 
			
		||||
 | 
			
		||||
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 ContractCreateReqVO extends ContractBaseVO {
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "只读权限的用户编号数组")
 | 
			
		||||
    private String roUserIds;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "读写权限的用户编号数组")
 | 
			
		||||
    private String rwUserIds;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,70 @@
 | 
			
		||||
package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
 | 
			
		||||
 | 
			
		||||
import com.alibaba.excel.annotation.ExcelProperty;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 合同 Excel VO
 | 
			
		||||
 *
 | 
			
		||||
 * @author dhb52
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
public class ContractExcelVO {
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("合同编号")
 | 
			
		||||
    private Long id;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("合同名称")
 | 
			
		||||
    private String name;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("客户编号")
 | 
			
		||||
    private Long customerId;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("商机编号")
 | 
			
		||||
    private Long businessId;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("工作流编号")
 | 
			
		||||
    private Long processInstanceId;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("下单日期")
 | 
			
		||||
    private LocalDateTime orderDate;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("负责人的用户编号")
 | 
			
		||||
    private Long ownerUserId;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("合同编号")
 | 
			
		||||
    private String no;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("开始时间")
 | 
			
		||||
    private LocalDateTime startTime;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("结束时间")
 | 
			
		||||
    private LocalDateTime endTime;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("合同金额")
 | 
			
		||||
    private Integer price;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("整单折扣")
 | 
			
		||||
    private Integer discountPercent;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("产品总金额")
 | 
			
		||||
    private Integer productPrice;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("联系人编号")
 | 
			
		||||
    private Long contactId;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("公司签约人")
 | 
			
		||||
    private Long signUserId;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("最后跟进时间")
 | 
			
		||||
    private LocalDateTime contactLastTime;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("备注")
 | 
			
		||||
    private String remark;
 | 
			
		||||
 | 
			
		||||
    @ExcelProperty("创建时间")
 | 
			
		||||
    private LocalDateTime createTime;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,37 @@
 | 
			
		||||
package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
 | 
			
		||||
 | 
			
		||||
import io.swagger.v3.oas.annotations.media.Schema;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import org.springframework.format.annotation.DateTimeFormat;
 | 
			
		||||
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 | 
			
		||||
 | 
			
		||||
@Schema(description = "管理后台 - 合同 Excel 导出 Request VO,参数和 ContractPageReqVO 是一致的")
 | 
			
		||||
@Data
 | 
			
		||||
public class ContractExportReqVO {
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "合同名称", example = "王五")
 | 
			
		||||
    private String name;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "客户编号", example = "18336")
 | 
			
		||||
    private Long customerId;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "商机编号", example = "10864")
 | 
			
		||||
    private Long businessId;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "下单日期")
 | 
			
		||||
    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
 | 
			
		||||
    private LocalDateTime[] orderDate;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "合同编号")
 | 
			
		||||
    private String no;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "整单折扣")
 | 
			
		||||
    private Integer discountPercent;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "产品总金额", example = "19510")
 | 
			
		||||
    private Integer productPrice;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,42 @@
 | 
			
		||||
package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
import org.springframework.format.annotation.DateTimeFormat;
 | 
			
		||||
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 | 
			
		||||
 | 
			
		||||
@Schema(description = "管理后台 - 合同分页 Request VO")
 | 
			
		||||
@Data
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
@ToString(callSuper = true)
 | 
			
		||||
public class ContractPageReqVO extends PageParam {
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "合同名称", example = "王五")
 | 
			
		||||
    private String name;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "客户编号", example = "18336")
 | 
			
		||||
    private Long customerId;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "商机编号", example = "10864")
 | 
			
		||||
    private Long businessId;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "下单日期")
 | 
			
		||||
    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
 | 
			
		||||
    private LocalDateTime[] orderDate;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "合同编号")
 | 
			
		||||
    private String no;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "整单折扣")
 | 
			
		||||
    private Integer discountPercent;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "产品总金额", example = "19510")
 | 
			
		||||
    private Integer productPrice;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,22 @@
 | 
			
		||||
package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
 | 
			
		||||
 | 
			
		||||
import io.swagger.v3.oas.annotations.media.Schema;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import lombok.ToString;
 | 
			
		||||
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
 | 
			
		||||
@Schema(description = "管理后台 - 合同 Response VO")
 | 
			
		||||
@Data
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
@ToString(callSuper = true)
 | 
			
		||||
public class ContractRespVO extends ContractBaseVO {
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
 | 
			
		||||
    private Long id;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
 | 
			
		||||
    private LocalDateTime createTime;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,26 @@
 | 
			
		||||
package cn.iocoder.yudao.module.crm.controller.admin.contract.vo;
 | 
			
		||||
 | 
			
		||||
import io.swagger.v3.oas.annotations.media.Schema;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import lombok.ToString;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.NotNull;
 | 
			
		||||
 | 
			
		||||
@Schema(description = "管理后台 - 合同更新 Request VO")
 | 
			
		||||
@Data
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
@ToString(callSuper = true)
 | 
			
		||||
public class ContractUpdateReqVO extends ContractBaseVO {
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430")
 | 
			
		||||
    @NotNull(message = "合同编号不能为空")
 | 
			
		||||
    private Long id;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "只读权限的用户编号数组")
 | 
			
		||||
    private String roUserIds;
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "读写权限的用户编号数组")
 | 
			
		||||
    private String rwUserIds;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,36 @@
 | 
			
		||||
package cn.iocoder.yudao.module.crm.convert.contract;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractCreateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractExcelVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractRespVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractUpdateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
 | 
			
		||||
import org.mapstruct.Mapper;
 | 
			
		||||
import org.mapstruct.factory.Mappers;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 合同 Convert
 | 
			
		||||
 *
 | 
			
		||||
 * @author dhb52
 | 
			
		||||
 */
 | 
			
		||||
@Mapper
 | 
			
		||||
public interface ContractConvert {
 | 
			
		||||
 | 
			
		||||
    ContractConvert INSTANCE = Mappers.getMapper(ContractConvert.class);
 | 
			
		||||
 | 
			
		||||
    ContractDO convert(ContractCreateReqVO bean);
 | 
			
		||||
 | 
			
		||||
    ContractDO convert(ContractUpdateReqVO bean);
 | 
			
		||||
 | 
			
		||||
    ContractRespVO convert(ContractDO bean);
 | 
			
		||||
 | 
			
		||||
    List<ContractRespVO> convertList(List<ContractDO> list);
 | 
			
		||||
 | 
			
		||||
    PageResult<ContractRespVO> convertPage(PageResult<ContractDO> page);
 | 
			
		||||
 | 
			
		||||
    List<ContractExcelVO> convertList02(List<ContractDO> list);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,104 @@
 | 
			
		||||
package cn.iocoder.yudao.module.crm.dal.dataobject.contract;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.KeySequence;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableId;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableName;
 | 
			
		||||
import lombok.*;
 | 
			
		||||
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 合同 DO
 | 
			
		||||
 *
 | 
			
		||||
 * @author dhb52
 | 
			
		||||
 */
 | 
			
		||||
@TableName("crm_contract")
 | 
			
		||||
@KeySequence("crm_contract_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
 | 
			
		||||
@Data
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
@ToString(callSuper = true)
 | 
			
		||||
@Builder
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
@AllArgsConstructor
 | 
			
		||||
public class ContractDO extends BaseDO {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 合同编号
 | 
			
		||||
     */
 | 
			
		||||
    @TableId
 | 
			
		||||
    private Long id;
 | 
			
		||||
    /**
 | 
			
		||||
     * 合同名称
 | 
			
		||||
     */
 | 
			
		||||
    private String name;
 | 
			
		||||
    /**
 | 
			
		||||
     * 客户编号
 | 
			
		||||
     */
 | 
			
		||||
    private Long customerId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 商机编号
 | 
			
		||||
     */
 | 
			
		||||
    private Long businessId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 工作流编号
 | 
			
		||||
     */
 | 
			
		||||
    private Long processInstanceId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 下单日期
 | 
			
		||||
     */
 | 
			
		||||
    private LocalDateTime orderDate;
 | 
			
		||||
    /**
 | 
			
		||||
     * 负责人的用户编号
 | 
			
		||||
     */
 | 
			
		||||
    private Long ownerUserId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 合同编号
 | 
			
		||||
     */
 | 
			
		||||
    private String no;
 | 
			
		||||
    /**
 | 
			
		||||
     * 开始时间
 | 
			
		||||
     */
 | 
			
		||||
    private LocalDateTime startTime;
 | 
			
		||||
    /**
 | 
			
		||||
     * 结束时间
 | 
			
		||||
     */
 | 
			
		||||
    private LocalDateTime endTime;
 | 
			
		||||
    /**
 | 
			
		||||
     * 合同金额
 | 
			
		||||
     */
 | 
			
		||||
    private Integer price;
 | 
			
		||||
    /**
 | 
			
		||||
     * 整单折扣
 | 
			
		||||
     */
 | 
			
		||||
    private Integer discountPercent;
 | 
			
		||||
    /**
 | 
			
		||||
     * 产品总金额
 | 
			
		||||
     */
 | 
			
		||||
    private Integer productPrice;
 | 
			
		||||
    /**
 | 
			
		||||
     * 只读权限的用户编号数组
 | 
			
		||||
     */
 | 
			
		||||
    private String roUserIds;
 | 
			
		||||
    /**
 | 
			
		||||
     * 读写权限的用户编号数组
 | 
			
		||||
     */
 | 
			
		||||
    private String rwUserIds;
 | 
			
		||||
    /**
 | 
			
		||||
     * 联系人编号
 | 
			
		||||
     */
 | 
			
		||||
    private Long contactId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 公司签约人
 | 
			
		||||
     */
 | 
			
		||||
    private Long signUserId;
 | 
			
		||||
    /**
 | 
			
		||||
     * 最后跟进时间
 | 
			
		||||
     */
 | 
			
		||||
    private LocalDateTime contactLastTime;
 | 
			
		||||
    /**
 | 
			
		||||
     * 备注
 | 
			
		||||
     */
 | 
			
		||||
    private String remark;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,45 @@
 | 
			
		||||
package cn.iocoder.yudao.module.crm.dal.mysql.contract;
 | 
			
		||||
 | 
			
		||||
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.contract.vo.ContractExportReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractPageReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
 | 
			
		||||
import org.apache.ibatis.annotations.Mapper;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 合同 Mapper
 | 
			
		||||
 *
 | 
			
		||||
 * @author dhb52
 | 
			
		||||
 */
 | 
			
		||||
@Mapper
 | 
			
		||||
public interface ContractMapper extends BaseMapperX<ContractDO> {
 | 
			
		||||
 | 
			
		||||
    default PageResult<ContractDO> selectPage(ContractPageReqVO reqVO) {
 | 
			
		||||
        return selectPage(reqVO, new LambdaQueryWrapperX<ContractDO>()
 | 
			
		||||
            .likeIfPresent(ContractDO::getName, reqVO.getName())
 | 
			
		||||
            .eqIfPresent(ContractDO::getCustomerId, reqVO.getCustomerId())
 | 
			
		||||
            .eqIfPresent(ContractDO::getBusinessId, reqVO.getBusinessId())
 | 
			
		||||
            .betweenIfPresent(ContractDO::getOrderDate, reqVO.getOrderDate())
 | 
			
		||||
            .eqIfPresent(ContractDO::getNo, reqVO.getNo())
 | 
			
		||||
            .eqIfPresent(ContractDO::getDiscountPercent, reqVO.getDiscountPercent())
 | 
			
		||||
            .eqIfPresent(ContractDO::getProductPrice, reqVO.getProductPrice())
 | 
			
		||||
            .orderByDesc(ContractDO::getId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    default List<ContractDO> selectList(ContractExportReqVO reqVO) {
 | 
			
		||||
        return selectList(new LambdaQueryWrapperX<ContractDO>()
 | 
			
		||||
            .likeIfPresent(ContractDO::getName, reqVO.getName())
 | 
			
		||||
            .eqIfPresent(ContractDO::getCustomerId, reqVO.getCustomerId())
 | 
			
		||||
            .eqIfPresent(ContractDO::getBusinessId, reqVO.getBusinessId())
 | 
			
		||||
            .betweenIfPresent(ContractDO::getOrderDate, reqVO.getOrderDate())
 | 
			
		||||
            .eqIfPresent(ContractDO::getNo, reqVO.getNo())
 | 
			
		||||
            .eqIfPresent(ContractDO::getDiscountPercent, reqVO.getDiscountPercent())
 | 
			
		||||
            .eqIfPresent(ContractDO::getProductPrice, reqVO.getProductPrice())
 | 
			
		||||
            .orderByDesc(ContractDO::getId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,75 @@
 | 
			
		||||
package cn.iocoder.yudao.module.crm.service.contract;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractCreateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractExportReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractPageReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractUpdateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
 | 
			
		||||
 | 
			
		||||
import javax.validation.Valid;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 合同 Service 接口
 | 
			
		||||
 *
 | 
			
		||||
 * @author dhb52
 | 
			
		||||
 */
 | 
			
		||||
public interface ContractService {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 创建合同
 | 
			
		||||
     *
 | 
			
		||||
     * @param createReqVO 创建信息
 | 
			
		||||
     * @return 编号
 | 
			
		||||
     */
 | 
			
		||||
    Long createContract(@Valid ContractCreateReqVO createReqVO);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 更新合同
 | 
			
		||||
     *
 | 
			
		||||
     * @param updateReqVO 更新信息
 | 
			
		||||
     */
 | 
			
		||||
    void updateContract(@Valid ContractUpdateReqVO updateReqVO);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 删除合同
 | 
			
		||||
     *
 | 
			
		||||
     * @param id 编号
 | 
			
		||||
     */
 | 
			
		||||
    void deleteContract(Long id);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获得合同
 | 
			
		||||
     *
 | 
			
		||||
     * @param id 编号
 | 
			
		||||
     * @return 合同
 | 
			
		||||
     */
 | 
			
		||||
    ContractDO getContract(Long id);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获得合同列表
 | 
			
		||||
     *
 | 
			
		||||
     * @param ids 编号
 | 
			
		||||
     * @return 合同列表
 | 
			
		||||
     */
 | 
			
		||||
    List<ContractDO> getContractList(Collection<Long> ids);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获得合同分页
 | 
			
		||||
     *
 | 
			
		||||
     * @param pageReqVO 分页查询
 | 
			
		||||
     * @return 合同分页
 | 
			
		||||
     */
 | 
			
		||||
    PageResult<ContractDO> getContractPage(ContractPageReqVO pageReqVO);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获得合同列表, 用于 Excel 导出
 | 
			
		||||
     *
 | 
			
		||||
     * @param exportReqVO 查询条件
 | 
			
		||||
     * @return 合同列表
 | 
			
		||||
     */
 | 
			
		||||
    List<ContractDO> getContractList(ContractExportReqVO exportReqVO);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,90 @@
 | 
			
		||||
package cn.iocoder.yudao.module.crm.service.contract;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.collection.CollUtil;
 | 
			
		||||
import cn.hutool.core.collection.ListUtil;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractCreateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractExportReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractPageReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractUpdateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.convert.contract.ContractConvert;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.dal.mysql.contract.ContractMapper;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Resource;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 | 
			
		||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTRACT_NOT_EXISTS;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 合同 Service 实现类
 | 
			
		||||
 *
 | 
			
		||||
 * @author dhb52
 | 
			
		||||
 */
 | 
			
		||||
@Service
 | 
			
		||||
@Validated
 | 
			
		||||
public class ContractServiceImpl implements ContractService {
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private ContractMapper contractMapper;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Long createContract(ContractCreateReqVO createReqVO) {
 | 
			
		||||
        // 插入
 | 
			
		||||
        ContractDO contract = ContractConvert.INSTANCE.convert(createReqVO);
 | 
			
		||||
        contractMapper.insert(contract);
 | 
			
		||||
        // 返回
 | 
			
		||||
        return contract.getId();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void updateContract(ContractUpdateReqVO updateReqVO) {
 | 
			
		||||
        // 校验存在
 | 
			
		||||
        validateContractExists(updateReqVO.getId());
 | 
			
		||||
        // 更新
 | 
			
		||||
        ContractDO updateObj = ContractConvert.INSTANCE.convert(updateReqVO);
 | 
			
		||||
        contractMapper.updateById(updateObj);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void deleteContract(Long id) {
 | 
			
		||||
        // 校验存在
 | 
			
		||||
        validateContractExists(id);
 | 
			
		||||
        // 删除
 | 
			
		||||
        contractMapper.deleteById(id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void validateContractExists(Long id) {
 | 
			
		||||
        if (contractMapper.selectById(id) == null) {
 | 
			
		||||
            throw exception(CONTRACT_NOT_EXISTS);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ContractDO getContract(Long id) {
 | 
			
		||||
        return contractMapper.selectById(id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<ContractDO> getContractList(Collection<Long> ids) {
 | 
			
		||||
        if (CollUtil.isEmpty(ids)) {
 | 
			
		||||
            return ListUtil.empty();
 | 
			
		||||
        }
 | 
			
		||||
        return contractMapper.selectBatchIds(ids);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public PageResult<ContractDO> getContractPage(ContractPageReqVO pageReqVO) {
 | 
			
		||||
        return contractMapper.selectPage(pageReqVO);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<ContractDO> getContractList(ContractExportReqVO exportReqVO) {
 | 
			
		||||
        return contractMapper.selectList(exportReqVO);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,195 @@
 | 
			
		||||
package cn.iocoder.yudao.module.crm.service.contract;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractCreateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractExportReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractPageReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractUpdateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO;
 | 
			
		||||
import cn.iocoder.yudao.module.crm.dal.mysql.contract.ContractMapper;
 | 
			
		||||
import org.junit.jupiter.api.Disabled;
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
import org.springframework.context.annotation.Import;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Resource;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
 | 
			
		||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
 | 
			
		||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
 | 
			
		||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
 | 
			
		||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
 | 
			
		||||
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTRACT_NOT_EXISTS;
 | 
			
		||||
import static org.junit.jupiter.api.Assertions.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * {@link ContractServiceImpl} 的单元测试类
 | 
			
		||||
 *
 | 
			
		||||
 * @author dhb52
 | 
			
		||||
 */
 | 
			
		||||
@Import(ContractServiceImpl.class)
 | 
			
		||||
public class ContractServiceImplTest extends BaseDbUnitTest {
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private ContractServiceImpl contractService;
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private ContractMapper contractMapper;
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testCreateContract_success() {
 | 
			
		||||
        // 准备参数
 | 
			
		||||
        ContractCreateReqVO reqVO = randomPojo(ContractCreateReqVO.class);
 | 
			
		||||
 | 
			
		||||
        // 调用
 | 
			
		||||
        Long contractId = contractService.createContract(reqVO);
 | 
			
		||||
        // 断言
 | 
			
		||||
        assertNotNull(contractId);
 | 
			
		||||
        // 校验记录的属性是否正确
 | 
			
		||||
        ContractDO contract = contractMapper.selectById(contractId);
 | 
			
		||||
        assertPojoEquals(reqVO, contract);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testUpdateContract_success() {
 | 
			
		||||
        // mock 数据
 | 
			
		||||
        ContractDO dbContract = randomPojo(ContractDO.class);
 | 
			
		||||
        contractMapper.insert(dbContract);// @Sql: 先插入出一条存在的数据
 | 
			
		||||
        // 准备参数
 | 
			
		||||
        ContractUpdateReqVO reqVO = randomPojo(ContractUpdateReqVO.class, o -> {
 | 
			
		||||
            o.setId(dbContract.getId()); // 设置更新的 ID
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // 调用
 | 
			
		||||
        contractService.updateContract(reqVO);
 | 
			
		||||
        // 校验是否更新正确
 | 
			
		||||
        ContractDO contract = contractMapper.selectById(reqVO.getId()); // 获取最新的
 | 
			
		||||
        assertPojoEquals(reqVO, contract);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testUpdateContract_notExists() {
 | 
			
		||||
        // 准备参数
 | 
			
		||||
        ContractUpdateReqVO reqVO = randomPojo(ContractUpdateReqVO.class);
 | 
			
		||||
 | 
			
		||||
        // 调用, 并断言异常
 | 
			
		||||
        assertServiceException(() -> contractService.updateContract(reqVO), CONTRACT_NOT_EXISTS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testDeleteContract_success() {
 | 
			
		||||
        // mock 数据
 | 
			
		||||
        ContractDO dbContract = randomPojo(ContractDO.class);
 | 
			
		||||
        contractMapper.insert(dbContract);// @Sql: 先插入出一条存在的数据
 | 
			
		||||
        // 准备参数
 | 
			
		||||
        Long id = dbContract.getId();
 | 
			
		||||
 | 
			
		||||
        // 调用
 | 
			
		||||
        contractService.deleteContract(id);
 | 
			
		||||
        // 校验数据不存在了
 | 
			
		||||
        assertNull(contractMapper.selectById(id));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testDeleteContract_notExists() {
 | 
			
		||||
        // 准备参数
 | 
			
		||||
        Long id = randomLongId();
 | 
			
		||||
 | 
			
		||||
        // 调用, 并断言异常
 | 
			
		||||
        assertServiceException(() -> contractService.deleteContract(id), CONTRACT_NOT_EXISTS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
 | 
			
		||||
    public void testGetContractPage() {
 | 
			
		||||
        // mock 数据
 | 
			
		||||
        ContractDO dbContract = randomPojo(ContractDO.class, o -> { // 等会查询到
 | 
			
		||||
            o.setName(null);
 | 
			
		||||
            o.setCustomerId(null);
 | 
			
		||||
            o.setBusinessId(null);
 | 
			
		||||
            o.setOrderDate(null);
 | 
			
		||||
            o.setNo(null);
 | 
			
		||||
            o.setDiscountPercent(null);
 | 
			
		||||
            o.setProductPrice(null);
 | 
			
		||||
        });
 | 
			
		||||
        contractMapper.insert(dbContract);
 | 
			
		||||
        // 测试 name 不匹配
 | 
			
		||||
        contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setName(null)));
 | 
			
		||||
        // 测试 customerId 不匹配
 | 
			
		||||
        contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setCustomerId(null)));
 | 
			
		||||
        // 测试 businessId 不匹配
 | 
			
		||||
        contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setBusinessId(null)));
 | 
			
		||||
        // 测试 orderDate 不匹配
 | 
			
		||||
        contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setOrderDate(null)));
 | 
			
		||||
        // 测试 no 不匹配
 | 
			
		||||
        contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setNo(null)));
 | 
			
		||||
        // 测试 discountPercent 不匹配
 | 
			
		||||
        contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setDiscountPercent(null)));
 | 
			
		||||
        // 测试 productPrice 不匹配
 | 
			
		||||
        contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setProductPrice(null)));
 | 
			
		||||
        // 准备参数
 | 
			
		||||
        ContractPageReqVO reqVO = new ContractPageReqVO();
 | 
			
		||||
        reqVO.setName(null);
 | 
			
		||||
        reqVO.setCustomerId(null);
 | 
			
		||||
        reqVO.setBusinessId(null);
 | 
			
		||||
        reqVO.setOrderDate(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
 | 
			
		||||
        reqVO.setNo(null);
 | 
			
		||||
        reqVO.setDiscountPercent(null);
 | 
			
		||||
        reqVO.setProductPrice(null);
 | 
			
		||||
 | 
			
		||||
        // 调用
 | 
			
		||||
        PageResult<ContractDO> pageResult = contractService.getContractPage(reqVO);
 | 
			
		||||
        // 断言
 | 
			
		||||
        assertEquals(1, pageResult.getTotal());
 | 
			
		||||
        assertEquals(1, pageResult.getList().size());
 | 
			
		||||
        assertPojoEquals(dbContract, pageResult.getList().get(0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
 | 
			
		||||
    public void testGetContractList() {
 | 
			
		||||
        // mock 数据
 | 
			
		||||
        ContractDO dbContract = randomPojo(ContractDO.class, o -> { // 等会查询到
 | 
			
		||||
            o.setName("合同名称");
 | 
			
		||||
            o.setCustomerId(null);
 | 
			
		||||
            o.setBusinessId(null);
 | 
			
		||||
            o.setOrderDate(null);
 | 
			
		||||
            o.setNo(null);
 | 
			
		||||
            o.setDiscountPercent(null);
 | 
			
		||||
            o.setProductPrice(null);
 | 
			
		||||
        });
 | 
			
		||||
        contractMapper.insert(dbContract);
 | 
			
		||||
        // 测试 name 不匹配
 | 
			
		||||
        contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setName(null)));
 | 
			
		||||
        // 测试 customerId 不匹配
 | 
			
		||||
        contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setCustomerId(null)));
 | 
			
		||||
        // 测试 businessId 不匹配
 | 
			
		||||
        contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setBusinessId(null)));
 | 
			
		||||
        // 测试 orderDate 不匹配
 | 
			
		||||
        contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setOrderDate(null)));
 | 
			
		||||
        // 测试 no 不匹配
 | 
			
		||||
        contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setNo(null)));
 | 
			
		||||
        // 测试 discountPercent 不匹配
 | 
			
		||||
        contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setDiscountPercent(null)));
 | 
			
		||||
        // 测试 productPrice 不匹配
 | 
			
		||||
        contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setProductPrice(null)));
 | 
			
		||||
        // 准备参数
 | 
			
		||||
        ContractExportReqVO reqVO = new ContractExportReqVO();
 | 
			
		||||
        reqVO.setName(null);
 | 
			
		||||
        reqVO.setCustomerId(null);
 | 
			
		||||
        reqVO.setBusinessId(null);
 | 
			
		||||
        reqVO.setOrderDate(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
 | 
			
		||||
        reqVO.setNo(null);
 | 
			
		||||
        reqVO.setDiscountPercent(null);
 | 
			
		||||
        reqVO.setProductPrice(null);
 | 
			
		||||
 | 
			
		||||
        // 调用
 | 
			
		||||
        List<ContractDO> list = contractService.getContractList(reqVO);
 | 
			
		||||
        // 断言
 | 
			
		||||
        assertEquals(1, list.size());
 | 
			
		||||
        assertPojoEquals(dbContract, list.get(0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,50 @@
 | 
			
		||||
spring:
 | 
			
		||||
    main:
 | 
			
		||||
        lazy-initialization: true # 开启懒加载,加快速度
 | 
			
		||||
        banner-mode: off # 单元测试,禁用 Banner
 | 
			
		||||
 | 
			
		||||
--- #################### 数据库相关配置 ####################
 | 
			
		||||
 | 
			
		||||
spring:
 | 
			
		||||
    # 数据源配置项
 | 
			
		||||
    datasource:
 | 
			
		||||
        name: ruoyi-vue-pro
 | 
			
		||||
        url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
 | 
			
		||||
        driver-class-name: org.h2.Driver
 | 
			
		||||
        username: sa
 | 
			
		||||
        password:
 | 
			
		||||
        druid:
 | 
			
		||||
            async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
 | 
			
		||||
            initial-size: 1 # 单元测试,配置为 1,提升启动速度
 | 
			
		||||
    sql:
 | 
			
		||||
        init:
 | 
			
		||||
            schema-locations: classpath:/sql/create_tables.sql
 | 
			
		||||
 | 
			
		||||
    # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
 | 
			
		||||
    redis:
 | 
			
		||||
        host: 127.0.0.1 # 地址
 | 
			
		||||
        port: 16379 # 端口(单元测试,使用 16379 端口)
 | 
			
		||||
        database: 0 # 数据库索引
 | 
			
		||||
 | 
			
		||||
mybatis-plus:
 | 
			
		||||
    lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
 | 
			
		||||
    type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject
 | 
			
		||||
 | 
			
		||||
--- #################### 定时任务相关配置 ####################
 | 
			
		||||
 | 
			
		||||
--- #################### 配置中心相关配置 ####################
 | 
			
		||||
 | 
			
		||||
--- #################### 服务保障相关配置 ####################
 | 
			
		||||
 | 
			
		||||
# Lock4j 配置项(单元测试,禁用 Lock4j)
 | 
			
		||||
 | 
			
		||||
# Resilience4j 配置项
 | 
			
		||||
 | 
			
		||||
--- #################### 监控相关配置 ####################
 | 
			
		||||
 | 
			
		||||
--- #################### 芋道相关配置 ####################
 | 
			
		||||
 | 
			
		||||
# 芋道配置项,设置当前项目所有自定义的配置
 | 
			
		||||
yudao:
 | 
			
		||||
  info:
 | 
			
		||||
    base-package: cn.iocoder.yudao
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
<configuration>
 | 
			
		||||
    <!-- 引用 Spring Boot 的 logback 基础配置 -->
 | 
			
		||||
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
 | 
			
		||||
</configuration>
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
DELETE FROM "crm_contract";
 | 
			
		||||
@@ -0,0 +1,27 @@
 | 
			
		||||
CREATE TABLE IF NOT EXISTS "crm_contract" (
 | 
			
		||||
  "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
 | 
			
		||||
  "name" varchar NOT NULL,
 | 
			
		||||
  "customer_id" bigint,
 | 
			
		||||
  "business_id" bigint,
 | 
			
		||||
  "process_instance_id" bigint,
 | 
			
		||||
  "order_date" varchar,
 | 
			
		||||
  "owner_user_id" bigint,
 | 
			
		||||
  "no" varchar,
 | 
			
		||||
  "start_time" varchar,
 | 
			
		||||
  "end_time" varchar,
 | 
			
		||||
  "price" int,
 | 
			
		||||
  "discount_percent" int,
 | 
			
		||||
  "product_price" int,
 | 
			
		||||
  "ro_user_ids" varchar,
 | 
			
		||||
  "rw_user_ids" varchar,
 | 
			
		||||
  "contact_id" bigint,
 | 
			
		||||
  "sign_user_id" bigint,
 | 
			
		||||
  "contact_last_time" varchar,
 | 
			
		||||
  "remark" varchar,
 | 
			
		||||
  "creator" varchar DEFAULT '',
 | 
			
		||||
  "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
 | 
			
		||||
  "updater" varchar DEFAULT '',
 | 
			
		||||
  "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 | 
			
		||||
  "deleted" bit NOT NULL DEFAULT FALSE,
 | 
			
		||||
  PRIMARY KEY ("id")
 | 
			
		||||
    ) COMMENT '合同表';
 | 
			
		||||
		Reference in New Issue
	
	Block a user