客户类型字段更新
This commit is contained in:
360
openspec/changes/split-pricing-creation-interface/design.md
Normal file
360
openspec/changes/split-pricing-creation-interface/design.md
Normal file
@@ -0,0 +1,360 @@
|
||||
# Design: 拆分个人和企业利率定价发起接口
|
||||
|
||||
## 数据库变更
|
||||
|
||||
### 缺失字段分析
|
||||
|
||||
经过对比 `person.csv` 和 `corp.csv` 中定义的字段与现有数据库表 `loan_pricing_workflow`,发现以下字段缺失:
|
||||
|
||||
#### 个人客户缺失字段
|
||||
|
||||
| 字段名 | 中文名 | 类型 | 说明 |
|
||||
|-----------|------|--------------|-------------------------|
|
||||
| id_num | 证件号码 | varchar(100) | 存储个人身份证号或其他证件号码 |
|
||||
| loan_loop | 循环功能 | varchar(10) | 贷款合同是否开通循环功能,true/false |
|
||||
|
||||
#### 企业客户缺失字段
|
||||
|
||||
| 字段名 | 中文名 | 类型 | 说明 |
|
||||
|-----------------------|------------|--------------|----------------------------------|
|
||||
| id_num | 证件号码 | varchar(100) | 存储企业统一社会信用代码或其他证件号码 |
|
||||
| is_trade_construction | 贸易和建筑业企业标识 | varchar(10) | 抵(质)押类:贸易和建筑业企业上调20BP,true/false |
|
||||
| is_green_loan | 绿色贷款 | varchar(10) | 绿色贷款标识,true/false |
|
||||
| is_tech_ent | 科技型企业 | varchar(10) | 科技型企业标识,true/false |
|
||||
| loan_term | 贷款期限 | varchar(50) | 贷款期限,单位:月/年 |
|
||||
|
||||
### 数据库迁移 SQL
|
||||
|
||||
```sql
|
||||
-- 添加缺失的字段到 loan_pricing_workflow 表
|
||||
|
||||
-- 个人和企业共同需要的字段
|
||||
ALTER TABLE `loan_pricing_workflow` ADD COLUMN `id_num` varchar(100) DEFAULT NULL COMMENT '证件号码' AFTER `id_type`;
|
||||
|
||||
-- 个人客户专用字段
|
||||
ALTER TABLE `loan_pricing_workflow` ADD COLUMN `loan_loop` varchar(10) DEFAULT NULL COMMENT '循环功能: true/false' AFTER `biz_proof`;
|
||||
|
||||
-- 企业客户专用字段
|
||||
ALTER TABLE `loan_pricing_workflow` ADD COLUMN `is_trade_construction` varchar(10) DEFAULT NULL COMMENT '贸易和建筑业企业标识: true/false(抵质押类上调20BP)' AFTER `is_agri_guar`;
|
||||
ALTER TABLE `loan_pricing_workflow` ADD COLUMN `is_green_loan` varchar(10) DEFAULT NULL COMMENT '绿色贷款: true/false' AFTER `is_agri_guar`;
|
||||
ALTER TABLE `loan_pricing_workflow` ADD COLUMN `is_tech_ent` varchar(10) DEFAULT NULL COMMENT '科技型企业: true/false' AFTER `is_agri_guar`;
|
||||
ALTER TABLE `loan_pricing_workflow` ADD COLUMN `loan_term` varchar(50) DEFAULT NULL COMMENT '贷款期限' AFTER `apply_amt`;
|
||||
```
|
||||
|
||||
### Entity 类更新
|
||||
|
||||
`LoanPricingWorkflow.java` 需要添加以下属性:
|
||||
|
||||
```java
|
||||
/** 证件号码 */
|
||||
private String idNum;
|
||||
|
||||
/** 循环功能: true/false */
|
||||
private String loanLoop;
|
||||
|
||||
/** 贸易和建筑业企业标识: true/false */
|
||||
private String isTradeConstruction;
|
||||
|
||||
/** 绿色贷款: true/false */
|
||||
private String isGreenLoan;
|
||||
|
||||
/** 科技型企业: true/false */
|
||||
private String isTechEnt;
|
||||
|
||||
/** 贷款期限 */
|
||||
private String loanTerm;
|
||||
```
|
||||
|
||||
## 架构设计
|
||||
|
||||
### 1. DTO 结构设计
|
||||
|
||||
#### PersonalLoanPricingCreateDTO(个人客户发起DTO)
|
||||
|
||||
```java
|
||||
@Data
|
||||
public class PersonalLoanPricingCreateDTO {
|
||||
@NotBlank(message = "客户内码不能为空")
|
||||
private String custIsn;
|
||||
|
||||
@NotBlank(message = "客户类型不能为空")
|
||||
private String custType; // 固定值 "个人"
|
||||
|
||||
@NotBlank(message = "担保方式不能为空")
|
||||
private String guarType; // 可选值:信用,保证,抵押,质押
|
||||
|
||||
private String custName;
|
||||
private String idType;
|
||||
private String idNum;
|
||||
|
||||
@NotBlank(message = "申请金额不能为空")
|
||||
private String applyAmt; // 单位:元
|
||||
|
||||
private String bizProof; // 是否有经营佐证
|
||||
private String loanLoop; // 循环功能
|
||||
|
||||
private String collType; // 抵质押类型
|
||||
private String collThirdParty; // 抵质押物是否三方所有
|
||||
}
|
||||
```
|
||||
|
||||
#### CorporateLoanPricingCreateDTO(企业客户发起DTO)
|
||||
|
||||
```java
|
||||
@Data
|
||||
public class CorporateLoanPricingCreateDTO {
|
||||
@NotBlank(message = "客户内码不能为空")
|
||||
private String custIsn;
|
||||
|
||||
@NotBlank(message = "客户类型不能为空")
|
||||
private String custType; // 固定值 "企业"
|
||||
|
||||
@NotBlank(message = "担保方式不能为空")
|
||||
private String guarType; // 可选值:信用,保证,抵押,质押
|
||||
|
||||
private String custName;
|
||||
private String idType;
|
||||
private String idNum;
|
||||
|
||||
@NotBlank(message = "申请金额不能为空")
|
||||
private String applyAmt; // 单位:元
|
||||
|
||||
private String isAgriGuar; // 省农担担保贷款
|
||||
private String isGreenLoan; // 绿色贷款
|
||||
private String isTechEnt; // 科技型企业
|
||||
private String loanTerm; // 贷款期限
|
||||
|
||||
private String collType; // 抵质押类型
|
||||
private String collThirdParty; // 抵质押物是否三方所有
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 接口设计
|
||||
|
||||
#### Controller 层
|
||||
|
||||
```java
|
||||
@RestController
|
||||
@RequestMapping("/loanPricing/workflow")
|
||||
public class LoanPricingWorkflowController extends BaseController {
|
||||
|
||||
// 原有接口(保留)
|
||||
@PostMapping("/create")
|
||||
public AjaxResult create(@Validated @RequestBody LoanPricingWorkflow loanPricingWorkflow)
|
||||
|
||||
// 新增:个人客户发起接口
|
||||
@PostMapping("/create/personal")
|
||||
public AjaxResult createPersonal(@Validated @RequestBody PersonalLoanPricingCreateDTO dto)
|
||||
|
||||
// 新增:企业客户发起接口
|
||||
@PostMapping("/create/corporate")
|
||||
public AjaxResult createCorporate(@Validated @RequestBody CorporateLoanPricingCreateDTO dto)
|
||||
}
|
||||
```
|
||||
|
||||
#### Service 层接口
|
||||
|
||||
```java
|
||||
public interface ILoanPricingWorkflowService {
|
||||
// 原有方法(保留兼容)
|
||||
LoanPricingWorkflow createLoanPricing(LoanPricingWorkflow loanPricingWorkflow);
|
||||
|
||||
// 新增:个人客户发起
|
||||
LoanPricingWorkflow createPersonalLoanPricing(PersonalLoanPricingCreateDTO dto);
|
||||
|
||||
// 新增:企业客户发起
|
||||
LoanPricingWorkflow createCorporateLoanPricing(CorporateLoanPricingCreateDTO dto);
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 字段映射关系
|
||||
|
||||
| 字段类别 | 个人字段 | 企业字段 |
|
||||
|------|------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
|
||||
| 共同字段 | custIsn, custType, guarType, custName, idType, idNum, applyAmt, collType, collThirdParty | |
|
||||
| 个人特有 | bizProof(是否有经营佐证), loanLoop(循环功能) | |
|
||||
| 企业特有 | | isAgriGuar(省农担担保贷款), isGreenLoan(绿色贷款), isTechEnt(科技型企业), isTradeConstruction(贸易和建筑业企业), loanTerm(贷款期限) |
|
||||
|
||||
### 4. 实现细节
|
||||
|
||||
#### DTO 转 Entity 转换器
|
||||
|
||||
创建一个转换工具类,将 DTO 转换为 `LoanPricingWorkflow` 实体:
|
||||
|
||||
```java
|
||||
public class LoanPricingConverter {
|
||||
public static LoanPricingWorkflow toEntity(PersonalLoanPricingCreateDTO dto) {
|
||||
LoanPricingWorkflow entity = new LoanPricingWorkflow();
|
||||
// 映射共同字段
|
||||
entity.setCustIsn(dto.getCustIsn());
|
||||
entity.setCustType("个人");
|
||||
entity.setCustName(dto.getCustName());
|
||||
entity.setIdType(dto.getIdType());
|
||||
entity.setIdNum(dto.getIdNum());
|
||||
entity.setGuarType(dto.getGuarType());
|
||||
entity.setApplyAmt(dto.getApplyAmt());
|
||||
entity.setCollType(dto.getCollType());
|
||||
entity.setCollThirdParty(dto.getCollThirdParty());
|
||||
// 映射个人特有字段
|
||||
entity.setBizProof(dto.getBizProof());
|
||||
entity.setLoanLoop(dto.getLoanLoop());
|
||||
return entity;
|
||||
}
|
||||
|
||||
public static LoanPricingWorkflow toEntity(CorporateLoanPricingCreateDTO dto) {
|
||||
LoanPricingWorkflow entity = new LoanPricingWorkflow();
|
||||
// 映射共同字段
|
||||
entity.setCustIsn(dto.getCustIsn());
|
||||
entity.setCustType("企业");
|
||||
entity.setCustName(dto.getCustName());
|
||||
entity.setIdType(dto.getIdType());
|
||||
entity.setIdNum(dto.getIdNum());
|
||||
entity.setGuarType(dto.getGuarType());
|
||||
entity.setApplyAmt(dto.getApplyAmt());
|
||||
entity.setCollType(dto.getCollType());
|
||||
entity.setCollThirdParty(dto.getCollThirdParty());
|
||||
// 映射企业特有字段
|
||||
entity.setIsAgriGuar(dto.getIsAgriGuar());
|
||||
entity.setIsGreenLoan(dto.getIsGreenLoan());
|
||||
entity.setIsTechEnt(dto.getIsTechEnt());
|
||||
entity.setIsTradeConstruction(dto.getIsTradeConstruction());
|
||||
entity.setLoanTerm(dto.getLoanTerm());
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 验证策略
|
||||
|
||||
#### 个人客户验证
|
||||
|
||||
- 必填字段:custIsn, custType, guarType, applyAmt
|
||||
- 枚举验证:guarType 必须是"信用/保证/抵押/质押"之一
|
||||
|
||||
#### 企业客户验证
|
||||
|
||||
- 必填字段:custIsn, custType, guarType, applyAmt
|
||||
- 枚举验证:guarType 必须是"信用/保证/抵押/质押"之一
|
||||
|
||||
### 6. 向后兼容性策略
|
||||
|
||||
1. 保留原有 `POST /loanPricing/workflow/create` 接口
|
||||
2. 新旧接口共存,前端可自由选择使用
|
||||
3. 不添加 @Deprecated 标记,保持接口的可用性
|
||||
|
||||
## 技术决策
|
||||
|
||||
### 为什么使用两个独立的 DTO 而不是一个带条件验证的 DTO?
|
||||
|
||||
1. **类型安全**:编译期就能发现字段错误
|
||||
2. **API 文档更清晰**:Swagger 只显示相关字段
|
||||
3. **验证更简单**:不需要在 DTO 内部根据类型做条件验证
|
||||
|
||||
### 为什么保留原有接口?
|
||||
|
||||
1. **多接口共存**:前端可以选择使用新接口或继续使用原有接口
|
||||
2. **降级方案**:如果新接口有问题,可以快速回退
|
||||
3. **兼容性**:可能有其他系统调用该接口
|
||||
|
||||
## 文件清单
|
||||
|
||||
### 数据库相关
|
||||
|
||||
- **新增**: `sql/add_missing_fields.sql` - 数据库迁移脚本
|
||||
|
||||
### 新增文件
|
||||
|
||||
- `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTO.java`
|
||||
- `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTO.java`
|
||||
- `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java`
|
||||
|
||||
### 测试文件
|
||||
|
||||
- `ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTOTest.java`
|
||||
- `ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTOTest.java`
|
||||
- `ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/util/LoanPricingConverterTest.java`
|
||||
- `test_api/test_personal_create.http` - 个人客户发起接口 HTTP 测试脚本
|
||||
- `test_api/test_corporate_create.http` - 企业客户发起接口 HTTP 测试脚本
|
||||
- `test_api/test_backward_compatibility.http` - 向后兼容性测试脚本
|
||||
|
||||
### 修改文件
|
||||
|
||||
- `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java` - 添加缺失字段的属性
|
||||
- `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/controller/LoanPricingWorkflowController.java`
|
||||
- `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/ILoanPricingWorkflowService.java`
|
||||
- `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java`
|
||||
|
||||
## 测试脚本示例
|
||||
|
||||
### HTTP 测试脚本格式
|
||||
|
||||
测试脚本使用 IntelliJ IDEA 的 .http 文件格式,示例如下:
|
||||
|
||||
```http
|
||||
### 获取测试 Token
|
||||
POST http://localhost:8080/login/test
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"username": "admin",
|
||||
"password": "admin123"
|
||||
}
|
||||
|
||||
> {%
|
||||
client.test("Request executed successfully", function() {
|
||||
client.assert(response.status === 200, "Response status is 200");
|
||||
client.assert(response.body.code === 200, "Response code is 200");
|
||||
client.global.set("token", response.body.data.token);
|
||||
});
|
||||
%}
|
||||
|
||||
### 个人客户发起 - 成功场景
|
||||
POST http://localhost:8080/loanPricing/workflow/create/personal
|
||||
Authorization: Bearer {{token}}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"custIsn": "TEST001",
|
||||
"custName": "张三",
|
||||
"idType": "身份证",
|
||||
"idNum": "110101199001011234",
|
||||
"guarType": "信用",
|
||||
"applyAmt": "500000",
|
||||
"bizProof": "true",
|
||||
"loanLoop": "false"
|
||||
}
|
||||
|
||||
> {%
|
||||
client.test("Personal loan creation successful", function() {
|
||||
client.assert(response.status === 200, "Response status is 200");
|
||||
client.assert(response.body.code === 200, "Response code is 200");
|
||||
client.assert(response.body.data.custType === "个人", "Customer type is 个人");
|
||||
});
|
||||
%}
|
||||
|
||||
### 企业客户发起 - 成功场景
|
||||
POST http://localhost:8080/loanPricing/workflow/create/corporate
|
||||
Authorization: Bearer {{token}}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"custIsn": "CORP001",
|
||||
"custName": "测试科技有限公司",
|
||||
"idType": "统一社会信用代码",
|
||||
"idNum": "91110000100000000X",
|
||||
"guarType": "抵押",
|
||||
"applyAmt": "1000000",
|
||||
"isAgriGuar": "false",
|
||||
"isGreenLoan": "true",
|
||||
"isTechEnt": "true",
|
||||
"loanTerm": "36"
|
||||
}
|
||||
|
||||
> {%
|
||||
client.test("Corporate loan creation successful", function() {
|
||||
client.assert(response.status === 200, "Response status is 200");
|
||||
client.assert(response.body.code === 200, "Response code is 200");
|
||||
client.assert(response.body.data.custType === "企业", "Customer type is 企业");
|
||||
});
|
||||
%}
|
||||
```
|
||||
@@ -0,0 +1,83 @@
|
||||
# Proposal: 拆分个人和企业利率定价发起接口
|
||||
|
||||
## 概述
|
||||
|
||||
将现有的统一利率定价发起接口 (`POST /loanPricing/workflow/create`) 拆分为两个独立的接口:
|
||||
|
||||
- 个人客户发起接口 (`POST /loanPricing/workflow/create/personal`)
|
||||
- 企业客户发起接口 (`POST /loanPricing/workflow/create/corporate`)
|
||||
|
||||
## 背景
|
||||
|
||||
当前系统中,`LoanPricingWorkflow` 实体包含了个人和企业客户的所有字段。当发起流程时,根据客户类型(custType)的不同,需要填写的字段存在差异:
|
||||
|
||||
- **个人客户**:需要填写个人特有字段(如是否有经营佐证、循环功能等)
|
||||
- **企业客户**:需要填写企业特有字段(如贸易和建筑业企业标识、省农担担保贷款、绿色贷款、科技型企业、贷款期限等)
|
||||
|
||||
将接口拆分可以带来以下好处:
|
||||
|
||||
1. **接口契约更清晰**:每个接口只包含对应客户类型的字段
|
||||
2. **验证更精确**:可以在 DTO 层面进行字段验证
|
||||
3. **文档更友好**:API 文档可以分别展示个人和企业的字段
|
||||
4. **维护性更好**:字段变更不会影响另一类型的客户
|
||||
|
||||
## 影响范围
|
||||
|
||||
### 后端变更
|
||||
|
||||
- 创建新的 DTO 类:`PersonalLoanPricingCreateDTO` 和 `CorporateLoanPricingCreateDTO`
|
||||
- 在 `LoanPricingWorkflowController` 中添加两个新接口
|
||||
- 修改 `ILoanPricingWorkflowService` 接口,添加两个新的创建方法
|
||||
- 实现 `LoanPricingWorkflowServiceImpl` 中的新方法
|
||||
- 保留原有接口以保持向后兼容(可选,建议标记为 Deprecated)
|
||||
|
||||
### 前端变更
|
||||
|
||||
> **注:本次变更仅涉及后端,前端暂不修改**
|
||||
|
||||
### 数据库变更
|
||||
|
||||
需要向 `loan_pricing_workflow` 表添加以下字段:
|
||||
|
||||
| 字段名 | 类型 | 说明 | 适用客户 |
|
||||
|-----------------------|--------------|------------------------|-------|
|
||||
| id_num | varchar(100) | 证件号码 | 个人、企业 |
|
||||
| loan_loop | varchar(10) | 循环功能 | 个人 |
|
||||
| is_trade_construction | varchar(10) | 贸易和建筑业企业标识(抵质押类上调20BP) | 企业 |
|
||||
| is_green_loan | varchar(10) | 绿色贷款(最多下降5BP) | 企业 |
|
||||
| is_tech_ent | varchar(10) | 科技型企业(最多下降5BP) | 企业 |
|
||||
| loan_term | varchar(50) | 贷款期限 | 企业 |
|
||||
|
||||
**迁移脚本位置**: `sql/add_missing_fields.sql`
|
||||
|
||||
同时需要更新 `LoanPricingWorkflow` Entity 类,添加对应的属性和字段映射注解。
|
||||
|
||||
## 设计方案
|
||||
|
||||
详见 `design.md`
|
||||
|
||||
## 风险和考虑
|
||||
|
||||
1. **向后兼容性**:原有接口 `POST /loanPricing/workflow/create` 继续保留
|
||||
- 原有接口不做标记为 Deprecated 的处理
|
||||
- 新旧接口共存,供前端自由选择使用
|
||||
|
||||
2. **数据迁移**:需要执行数据库迁移脚本添加新字段,但不涉及现有数据的迁移
|
||||
|
||||
3. **测试覆盖**:需要为新接口编写测试用例
|
||||
|
||||
## 依赖关系
|
||||
|
||||
- **数据库迁移必须最先执行**:所有后端开发依赖于新字段添加完成
|
||||
- 依赖现有的 `LoanPricingWorkflow` 实体
|
||||
- 依赖现有的 `ILoanPricingWorkflowService` 服务层
|
||||
|
||||
## 验收标准
|
||||
|
||||
1. **数据库变更**:所有新字段成功添加到数据库表,且可以正确存储和检索数据
|
||||
2. **Entity 类更新**:`LoanPricingWorkflow` 实体类包含所有新增字段的属性和映射
|
||||
3. **个人客户接口**:个人客户发起接口只接受个人相关的字段
|
||||
4. **企业客户接口**:企业客户发起接口只接受企业相关的字段
|
||||
5. **接口功能**:两个接口都能成功创建利率定价流程记录,包括新增字段的保存
|
||||
6. **字段验证**:字段验证正确生效
|
||||
7. **API 文档**:API 文档正确显示两个接口的差异
|
||||
@@ -0,0 +1,105 @@
|
||||
# 企业利率定价流程发起 Capability Spec
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 企业客户利率定价流程发起
|
||||
|
||||
系统 SHALL 提供企业客户专用的利率定价流程发起接口 (`POST /loanPricing/workflow/create/corporate`),该接口只接受企业客户相关的字段。
|
||||
|
||||
#### Scenario: 成功发起企业客户利率定价流程
|
||||
|
||||
- **WHEN** 业务人员通过企业客户发起接口提交包含必填字段(custIsn、guarType、applyAmt)的完整申请
|
||||
- **THEN** 系统自动生成业务方流水号(serialNum)并保存记录,custType 固定为"企业",返回成功响应
|
||||
|
||||
#### Scenario: 字段验证-必填字段
|
||||
|
||||
- **WHEN** 提交的企业客户申请缺少必填字段(custIsn、guarType、applyAmt)
|
||||
- **THEN** 系统返回参数验证失败的错误信息
|
||||
|
||||
#### Scenario: 字段验证-担保方式枚举值
|
||||
|
||||
- **WHEN** 提交的企业客户申请中 guarType 不是"信用"、"保证"、"抵押"、"质押"之一
|
||||
- **THEN** 系统返回参数验证失败的错误信息
|
||||
|
||||
#### Scenario: 记录企业特有字段
|
||||
|
||||
- **WHEN** 企业客户申请中包含 isAgriGuar(省农担担保贷款)、isGreenLoan(绿色贷款)、isTechEnt(科技型企业)或 loanTerm(贷款期限)字段
|
||||
- **THEN** 系统正确保存这些字段的值
|
||||
|
||||
#### Scenario: 自动设置客户类型
|
||||
|
||||
- **WHEN** 通过企业客户发起接口创建流程
|
||||
- **THEN** 系统自动将 custType 设置为"企业",无需客户端传入
|
||||
|
||||
#### Scenario: 自动生成业务方流水号
|
||||
|
||||
- **WHEN** 发起企业客户利率定价流程时
|
||||
- **THEN** 系统使用时间戳自动生成唯一的业务方流水号
|
||||
|
||||
#### Scenario: 记录创建和更新信息
|
||||
|
||||
- **WHEN** 企业客户利率定价流程创建成功
|
||||
- **THEN** 系统自动记录创建者、创建时间、更新者、更新时间
|
||||
|
||||
### Requirement: 企业客户发起接口字段定义
|
||||
|
||||
企业客户发起接口 SHALL 接受以下字段:
|
||||
|
||||
#### Scenario: 基本信息字段
|
||||
|
||||
- **WHEN** 客户端提交企业客户发起请求
|
||||
- **THEN** 系统接受以下基本信息字段:
|
||||
- `custIsn`(必填):客户内码
|
||||
- `custName`:客户名称
|
||||
- `idType`:证件类型
|
||||
- `idNum`:证件号码
|
||||
|
||||
#### Scenario: 贷款信息字段
|
||||
|
||||
- **WHEN** 客户端提交企业客户发起请求
|
||||
- **THEN** 系统接受以下贷款信息字段:
|
||||
- `guarType`(必填):担保方式,可选值"信用"、"保证"、"抵押"、"质押"
|
||||
- `applyAmt`(必填):申请金额,单位:元
|
||||
- `loanTerm`:贷款期限
|
||||
|
||||
#### Scenario: 企业特有字段-优惠条件
|
||||
|
||||
- **WHEN** 客户端提交企业客户发起请求
|
||||
- **THEN** 系统接受以下企业特有优惠条件字段:
|
||||
- `isAgriGuar`:省农担担保贷款(省农担担保贷款下调40个BP)
|
||||
- `isGreenLoan`:绿色贷款(绿色贷款或科技型企业最多下降5BP)
|
||||
- `isTechEnt`:科技型企业(绿色贷款或科技型企业最多下降5BP)
|
||||
|
||||
#### Scenario: 贸易和建筑业企业标识
|
||||
|
||||
- **WHEN** 企业客户申请中担保方式为抵(质)押类,且企业为贸易和建筑业企业
|
||||
- **THEN** 系统记录该标识,用于后续利率测算时上调20BP
|
||||
|
||||
#### Scenario: 抵质押信息字段
|
||||
|
||||
- **WHEN** 客户端提交企业客户发起请求
|
||||
- **THEN** 系统接受以下抵质押信息字段:
|
||||
- `collType`:抵质押类型
|
||||
- `collThirdParty`:抵质押物是否三方所有
|
||||
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: 利率定价流程发起接口弃用策略
|
||||
|
||||
原有的统一发起接口 (`POST /loanPricing/workflow/create`) SHALL 标记为 Deprecated,系统 SHALL
|
||||
继续支持该接口以保证向后兼容,同时引导使用新的个人或企业专用接口。
|
||||
|
||||
#### Scenario: 原有接口向后兼容
|
||||
|
||||
- **WHEN** 客户端继续使用原有发起接口
|
||||
- **THEN** 系统继续处理请求并返回正确结果,但建议迁移到新接口
|
||||
|
||||
#### Scenario: 原有接口标记为已弃用
|
||||
|
||||
- **WHEN** 开发人员查看 API 文档
|
||||
- **THEN** 原有接口标记为 Deprecated,引导使用新的个人或企业专用接口
|
||||
|
||||
## Cross-References
|
||||
|
||||
- 相关 Capability: `personal-loan-pricing-creation`(个人客户利率定价流程发起)
|
||||
- 修改自 Capability: `loan-pricing-workflow` 中的"利率定价流程发起"需求
|
||||
@@ -0,0 +1,98 @@
|
||||
# 个人利率定价流程发起 Capability Spec
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 个人客户利率定价流程发起
|
||||
|
||||
系统 SHALL 提供个人客户专用的利率定价流程发起接口 (`POST /loanPricing/workflow/create/personal`),该接口只接受个人客户相关的字段。
|
||||
|
||||
#### Scenario: 成功发起个人客户利率定价流程
|
||||
|
||||
- **WHEN** 业务人员通过个人客户发起接口提交包含必填字段(custIsn、guarType、applyAmt)的完整申请
|
||||
- **THEN** 系统自动生成业务方流水号(serialNum)并保存记录,custType 固定为"个人",返回成功响应
|
||||
|
||||
#### Scenario: 字段验证-必填字段
|
||||
|
||||
- **WHEN** 提交的个人客户申请缺少必填字段(custIsn、guarType、applyAmt)
|
||||
- **THEN** 系统返回参数验证失败的错误信息
|
||||
|
||||
#### Scenario: 字段验证-担保方式枚举值
|
||||
|
||||
- **WHEN** 提交的个人客户申请中 guarType 不是"信用"、"保证"、"抵押"、"质押"之一
|
||||
- **THEN** 系统返回参数验证失败的错误信息
|
||||
|
||||
#### Scenario: 记录个人特有字段
|
||||
|
||||
- **WHEN** 个人客户申请中包含 bizProof(是否有经营佐证)或 loanLoop(循环功能)字段
|
||||
- **THEN** 系统正确保存这些字段的值
|
||||
|
||||
#### Scenario: 自动设置客户类型
|
||||
|
||||
- **WHEN** 通过个人客户发起接口创建流程
|
||||
- **THEN** 系统自动将 custType 设置为"个人",无需客户端传入
|
||||
|
||||
#### Scenario: 自动生成业务方流水号
|
||||
|
||||
- **WHEN** 发起个人客户利率定价流程时
|
||||
- **THEN** 系统使用时间戳自动生成唯一的业务方流水号
|
||||
|
||||
#### Scenario: 记录创建和更新信息
|
||||
|
||||
- **WHEN** 个人客户利率定价流程创建成功
|
||||
- **THEN** 系统自动记录创建者、创建时间、更新者、更新时间
|
||||
|
||||
### Requirement: 个人客户发起接口字段定义
|
||||
|
||||
个人客户发起接口 SHALL 接受以下字段:
|
||||
|
||||
#### Scenario: 基本信息字段
|
||||
|
||||
- **WHEN** 客户端提交个人客户发起请求
|
||||
- **THEN** 系统接受以下基本信息字段:
|
||||
- `custIsn`(必填):客户内码
|
||||
- `custName`:客户名称
|
||||
- `idType`:证件类型
|
||||
- `idNum`:证件号码
|
||||
|
||||
#### Scenario: 贷款信息字段
|
||||
|
||||
- **WHEN** 客户端提交个人客户发起请求
|
||||
- **THEN** 系统接受以下贷款信息字段:
|
||||
- `guarType`(必填):担保方式,可选值"信用"、"保证"、"抵押"、"质押"
|
||||
- `applyAmt`(必填):申请金额,单位:元
|
||||
|
||||
#### Scenario: 个人特有字段
|
||||
|
||||
- **WHEN** 客户端提交个人客户发起请求
|
||||
- **THEN** 系统接受以下个人特有字段:
|
||||
- `bizProof`:是否有经营佐证(个人经营性贷款提供的经营佐证包括:借款人或其配偶为法定代表人、实际经营者、股东的企业(个体工商户)营业执照或企查查、企信宝查档资料)
|
||||
- `loanLoop`:贷款合同是否开通循环功能
|
||||
|
||||
#### Scenario: 抵质押信息字段
|
||||
|
||||
- **WHEN** 客户端提交个人客户发起请求
|
||||
- **THEN** 系统接受以下抵质押信息字段:
|
||||
- `collType`:抵质押类型
|
||||
- `collThirdParty`:抵质押物是否三方所有
|
||||
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: 利率定价流程发起接口弃用策略
|
||||
|
||||
原有的统一发起接口 (`POST /loanPricing/workflow/create`) SHALL 标记为 Deprecated,系统 SHALL
|
||||
继续支持该接口以保证向后兼容,同时引导使用新的个人或企业专用接口。
|
||||
|
||||
#### Scenario: 原有接口向后兼容
|
||||
|
||||
- **WHEN** 客户端继续使用原有发起接口
|
||||
- **THEN** 系统继续处理请求并返回正确结果,但建议迁移到新接口
|
||||
|
||||
#### Scenario: 原有接口标记为已弃用
|
||||
|
||||
- **WHEN** 开发人员查看 API 文档
|
||||
- **THEN** 原有接口标记为 Deprecated,引导使用新的个人或企业专用接口
|
||||
|
||||
## Cross-References
|
||||
|
||||
- 相关 Capability: `corporate-loan-pricing-creation`(企业客户利率定价流程发起)
|
||||
- 修改自 Capability: `loan-pricing-workflow` 中的"利率定价流程发起"需求
|
||||
149
openspec/changes/split-pricing-creation-interface/tasks.md
Normal file
149
openspec/changes/split-pricing-creation-interface/tasks.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# Tasks: 拆分个人和企业利率定价发起接口
|
||||
|
||||
## 数据库变更任务
|
||||
|
||||
### 0. 数据库表结构更新
|
||||
|
||||
- [x] 执行数据库迁移脚本,添加缺失字段:
|
||||
- `id_num` varchar(100) - 证件号码(个人和企业都需要)
|
||||
- `loan_loop` varchar(10) - 循环功能(个人客户专用)
|
||||
- `is_trade_construction` varchar(10) - 贸易和建筑业企业标识(企业客户专用)
|
||||
- `is_green_loan` varchar(10) - 绿色贷款(企业客户专用)
|
||||
- `is_tech_ent` varchar(10) - 科技型企业(企业客户专用)
|
||||
- `loan_term` varchar(50) - 贷款期限(企业客户专用)
|
||||
- [x] 更新 `LoanPricingWorkflow` Entity 类,添加对应的属性和字段映射注解
|
||||
- [ ] 验证数据库变更是否成功执行(需手动执行 SQL 脚本)
|
||||
|
||||
### 0.1 创建数据库迁移脚本
|
||||
|
||||
- [x] 在 `sql/` 目录下创建 `add_missing_fields.sql` 文件
|
||||
- [x] 包含所有 ALTER TABLE 语句
|
||||
- [x] 添加详细的注释说明每个字段的用途
|
||||
|
||||
## 后端实现任务
|
||||
|
||||
### 1. 创建 DTO 类
|
||||
|
||||
- [x] 创建 `PersonalLoanPricingCreateDTO.java`
|
||||
- 添加共同字段:custIsn、custName、idType、idNum、guarType、applyAmt、collType、collThirdParty
|
||||
- 添加个人客户特有字段:bizProof(是否有经营佐证)、loanLoop(循环功能)
|
||||
- 添加共同字段验证注解:custIsn、guarType、applyAmt 为必填
|
||||
- 添加担保方式枚举验证
|
||||
- [x] 创建 `CorporateLoanPricingCreateDTO.java`
|
||||
- 添加共同字段:custIsn、custName、idType、idNum、guarType、applyAmt、collType、collThirdParty
|
||||
- 添加企业客户特有字段:isAgriGuar(省农担担保贷款)、isGreenLoan(绿色贷款)、isTechEnt(科技型企业)、isTradeConstruction(贸易和建筑业企业)、loanTerm(贷款期限)
|
||||
- 添加共同字段验证注解:custIsn、guarType、applyAmt 为必填
|
||||
- 添加担保方式枚举验证
|
||||
|
||||
### 2. 更新 Entity 类
|
||||
|
||||
- [x] 在 `LoanPricingWorkflow.java` 中添加缺失的字段属性:
|
||||
- `idNum` - 证件号码
|
||||
- `loanLoop` - 循环功能
|
||||
- `isTradeConstruction` - 贸易和建筑业企业标识
|
||||
- `isGreenLoan` - 绿色贷款
|
||||
- `isTechEnt` - 科技型企业
|
||||
- `loanTerm` - 贷款期限
|
||||
- [x] 为新字段添加 MyBatis Plus 字段映射注解(如果需要)
|
||||
- [ ] 验证 Entity 类与数据库表字段映射正确(需执行 SQL 后验证)
|
||||
|
||||
### 3. 创建转换器工具类
|
||||
|
||||
- [x] 创建 `LoanPricingConverter.java`
|
||||
- 实现 `toEntity(PersonalLoanPricingCreateDTO)` 方法
|
||||
- 实现 `toEntity(CorporateLoanPricingCreateDTO)` 方法
|
||||
- 确保自动设置 custType 为"个人"或"企业"
|
||||
- 正确映射所有字段,包括新增的 idNum、loanLoop、isTradeConstruction、isGreenLoan、isTechEnt、loanTerm
|
||||
|
||||
### 4. 修改 Service 层
|
||||
|
||||
- [x] 在 `ILoanPricingWorkflowService` 接口中添加:
|
||||
- `createPersonalLoanPricing(PersonalLoanPricingCreateDTO dto)` 方法声明
|
||||
- `createCorporateLoanPricing(CorporateLoanPricingCreateDTO dto)` 方法声明
|
||||
- [x] 在 `LoanPricingWorkflowServiceImpl` 中实现新方法:
|
||||
- 实现 `createPersonalLoanPricing` 方法,调用转换器后复用现有逻辑
|
||||
- 实现 `createCorporateLoanPricing` 方法,调用转换器后复用现有逻辑
|
||||
|
||||
### 5. 修改 Controller 层
|
||||
|
||||
- [x] 在 `LoanPricingWorkflowController` 中添加:
|
||||
- `POST /loanPricing/workflow/create/personal` 接口
|
||||
- `POST /loanPricing/workflow/create/corporate` 接口
|
||||
- [x] 添加 Swagger 注解,明确标注接口用途和字段说明
|
||||
- [x] 保持原有接口不变,不做 @Deprecated 标记
|
||||
|
||||
### 6. 单元测试
|
||||
|
||||
- [ ] 创建 `PersonalLoanPricingCreateDTOTest.java` 测试类
|
||||
- 测试必填字段验证(custIsn、guarType、applyAmt)
|
||||
- 测试担保方式枚举验证(信用/保证/抵押/质押)
|
||||
- 测试个人特有字段(bizProof、loanLoop)
|
||||
- [ ] 创建 `CorporateLoanPricingCreateDTOTest.java` 测试类
|
||||
- 测试必填字段验证(custIsn、guarType、applyAmt)
|
||||
- 测试担保方式枚举验证(信用/保证/抵押/质押)
|
||||
- 测试企业特有字段(isAgriGuar、isGreenLoan、isTechEnt、isTradeConstruction、loanTerm)
|
||||
- [ ] 创建 `LoanPricingConverterTest.java` 测试类
|
||||
- 测试个人 DTO 转 Entity 映射完整性
|
||||
- 测试企业 DTO 转 Entity 映射完整性
|
||||
- 验证 custType 自动设置正确
|
||||
|
||||
### 7. 集成测试与测试脚本
|
||||
|
||||
- [x] 生成 HTTP 测试脚本 `test_personal_create.http`
|
||||
- 测试个人客户发起成功场景(完整必填字段)
|
||||
- 测试缺少必填字段的失败场景
|
||||
- 测试担保方式枚举验证失败场景
|
||||
- 使用 `/login/test` 接口获取测试 token
|
||||
- [x] 生成 HTTP 测试脚本 `test_corporate_create.http`
|
||||
- 测试企业客户发起成功场景(完整必填字段)
|
||||
- 测试缺少必填字段的失败场景
|
||||
- 测试担保方式枚举验证失败场景
|
||||
- 测试企业特有字段(isAgriGuar、isGreenLoan、isTechEnt、loanTerm)
|
||||
- [x] 生成 HTTP 测试脚本 `test_backward_compatibility.http`
|
||||
- 验证原有 `POST /loanPricing/workflow/create` 接口仍可正常工作
|
||||
- [x] 生成 Shell 测试脚本 `test_personal_create.sh`
|
||||
- 将 HTTP 测试脚本转换为 Shell 脚本格式
|
||||
- 使用 curl 命令进行接口调用
|
||||
- 包含颜色输出和测试结果统计
|
||||
- [x] 生成 Shell 测试脚本 `test_corporate_create.sh`
|
||||
- 将 HTTP 测试脚本转换为 Shell 脚本格式
|
||||
- 使用 curl 命令进行接口调用
|
||||
- 包含颜色输出和测试结果统计
|
||||
- [x] 生成 Shell 测试脚本 `test_backward_compatibility.sh`
|
||||
- 将 HTTP 测试脚本转换为 Shell 脚本格式
|
||||
- 使用 curl 命令进行接口调用
|
||||
- 包含颜色输出和测试结果统计
|
||||
- [ ] 执行所有测试脚本并验证结果
|
||||
- [ ] 生成测试报告到 `doc/` 目录
|
||||
|
||||
## 文档和部署
|
||||
|
||||
### 8. API 文档
|
||||
|
||||
- [ ] 更新 Swagger 文档,添加两个新接口的完整说明
|
||||
- [ ] 生成并导出 API 文档到项目 doc 目录
|
||||
|
||||
### 9. 代码审查和合并
|
||||
|
||||
- [ ] 提交 Pull Request
|
||||
- [ ] 通过代码审查
|
||||
- [ ] 合并到主分支
|
||||
|
||||
## 依赖关系
|
||||
|
||||
- **数据库变更(任务0)必须最先执行**:所有后端开发依赖于数据库字段完成
|
||||
- 任务 1-5 可以并行开发(依赖任务0完成)
|
||||
- 任务 6-7 依赖任务 1-5 完成
|
||||
- 任务 8-9 依赖所有前序任务完成
|
||||
|
||||
> **注:本次变更仅涉及后端,前端暂不修改**
|
||||
|
||||
## 验证检查点
|
||||
|
||||
1. **数据库字段完整性**:确保所有新增字段(idNum、loanLoop、isTradeConstruction、isGreenLoan、isTechEnt、loanTerm)已添加到数据库表
|
||||
2. **Entity 类映射正确性**:确保 Entity 类字段与数据库表字段一一对应
|
||||
3. **DTO 验证**:确保所有必填字段有 `@NotBlank` 注解,枚举字段有正确的验证
|
||||
4. **转换器正确性**:确保 DTO 到 Entity 的转换不丢失字段,包括新增字段
|
||||
5. **API 路由**:确保新接口路径正确且可访问
|
||||
6. **向后兼容**:确保原有接口继续工作
|
||||
7. **API 文档**:确保 Swagger 文档正确显示所有接口的参数说明
|
||||
Reference in New Issue
Block a user