# 流程列表测算利率展示设计文档

## 1. 背景

当前流程列表页已经展示“执行利率(%)”，但还没有展示“测算利率(%)”。现有测算利率并不存放在流程表 `loan_pricing_workflow` 中，而是存放在模型输出表中：

- 个人客户：`model_retail_output_fields.calculate_rate`
- 企业客户：`model_corp_output_fields.calculate_rate`

本次需求是在流程列表页新增“测算利率(%)”列，并与“执行利率(%)”同时展示。

## 2. 已确认约束

- 仅为流程列表页新增“测算利率(%)”展示
- 测算利率直接取模型输出表中的 `calculate_rate`
- 不新增冗余字段回写到 `loan_pricing_workflow`
- 正式方案采用联表 SQL，一次查出流程表和两张模型输出表所需字段
- 文档和计划统一保存在 `doc` 目录

## 3. 现状分析

当前流程列表页数据来源为 `/loanPricing/workflow/list`，后端列表接口直接基于 `LoanPricingWorkflow` 分页返回流程表字段。现状存在两个限制：

1. 流程表本身只有 `loanRate` 和 `executeRate`
2. 测算利率 `calculateRate` 分散在个人、企业两张模型输出表中

因此，如果不改列表查询链路，前端无法直接在列表页拿到统一的测算利率字段。

## 4. 方案对比

### 方案一：后端分页后按记录补查测算利率

做法：

- 先查流程表分页结果
- 再根据每条记录的 `custType` 和 `modelOutputId` 到对应模型输出表查询 `calculateRate`

优点：

- 改动可控

缺点：

- 查询次数随列表记录数增加
- 服务层补查逻辑分散
- 不符合本次已选定的联表方案

### 方案二：联表 SQL 一次查询流程列表和测算利率

做法：

- 以 `loan_pricing_workflow` 为主表
- 基于 `model_output_id` 左连接 `model_retail_output_fields` 和 `model_corp_output_fields`
- 统一返回一个列表专用字段 `calculateRate`

优点：

- 一次查询返回列表展示所需数据
- 前端消费简单
- 不需要额外补查或详情接口拼装

缺点：

- Mapper 查询层需要新增列表专用 SQL
- 返回对象需要从实体扩展为列表专用对象

### 方案三：前端逐条拉详情拼装测算利率

做法：

- 列表先只返回流程数据
- 前端逐条再请求详情，取详情中的测算利率

优点：

- 后端改动相对少

缺点：

- 请求次数多
- 列表渲染复杂
- 属于补丁式方案，不符合本次约束

## 5. 设计结论

采用方案二：联表 SQL 一次查询流程表和两张模型输出表，统一返回流程列表展示对象。

最终效果：

- 流程列表页新增“测算利率(%)”列
- 默认放在“执行利率(%)”前面
- “测算利率(%)”展示统一返回字段 `calculateRate`
- “执行利率(%)”继续展示 `executeRate`

## 6. 后端设计

### 6.1 返回对象

为流程列表新增列表专用返回对象，至少包含：

- 业务方流水号
- 客户名称
- 客户类型
- 担保方式
- 申请金额
- 测算利率 `calculateRate`
- 执行利率 `executeRate`
- 创建时间
- 创建者

不再让列表接口直接返回裸 `LoanPricingWorkflow` 实体。

### 6.2 SQL 设计

以 `loan_pricing_workflow` 为主表，联表查询：

- `LEFT JOIN model_retail_output_fields mr ON lpw.model_output_id = mr.id`
- `LEFT JOIN model_corp_output_fields mc ON lpw.model_output_id = mc.id`

测算利率统一按客户类型取值，返回别名 `calculateRate`。可采用 `CASE WHEN` 或等价写法：

- 当客户类型为“个人”时取 `mr.calculate_rate`
- 当客户类型为“企业”时取 `mc.calculate_rate`

### 6.3 分页与筛选

保留当前列表分页和筛选能力：

- 按创建者模糊查询
- 按客户名称模糊查询
- 按机构号模糊查询
- 按更新时间倒序

分页能力仍由当前列表接口承担，不改变接口入口路径。

## 7. 前端设计

流程列表页 `ruoyi-ui/src/views/loanPricing/workflow/index.vue` 新增一列：

- 列名：`测算利率(%)`
- 位置：放在 `执行利率(%)` 前面
- 绑定字段：`calculateRate`

现有 `执行利率(%)` 列不改，继续绑定 `executeRate`。

## 8. 边界与非目标

本次不包含以下内容：

- 不修改详情页测算利率展示逻辑
- 不修改执行利率设置逻辑
- 不修改流程创建逻辑
- 不修改数据库表结构
- 不新增流程表冗余字段存放测算利率
- 不让前端按客户类型自行拼装测算利率来源

## 9. 风险与控制

风险点主要有两个：

1. 联表后返回结构变化，可能影响前端列表字段读取
2. 个人/企业客户测算利率来源不同，若统一字段取值逻辑写错，会出现空值或串值

控制方式：

- 使用列表专用返回对象，避免污染实体语义
- 在 SQL 中用统一别名 `calculateRate` 输出
- 保持 `executeRate` 字段逻辑不变
- 通过源码和接口结果核对个人、企业两类记录的展示值

## 10. 验证方案

实施后需要完成以下验证：

1. 后端列表查询结果中包含 `calculateRate`
2. 个人客户记录的 `calculateRate` 来自 `model_retail_output_fields.calculate_rate`
3. 企业客户记录的 `calculateRate` 来自 `model_corp_output_fields.calculate_rate`
4. 前端流程列表页新增“测算利率(%)”列，且位于“执行利率(%)”前面
5. 流程列表页同时正常展示“测算利率(%)”和“执行利率(%)”
6. 列表查询、查看详情、设置执行利率功能不受影响

## 11. 实施范围

- 前端：流程列表页 1 个页面文件
- 后端：Controller / Service / Mapper / 列表返回对象
- 数据库：无表结构改动

本次属于列表查询结构增强与前端展示补充，不涉及数据模型持久化变更。
