# 供应商结算管理 — 技术方案 > **依据**:`供应商结算管理功能需求.md`(v1.1) > **关联**:`../交易订单管理/交易订单管理技术方案.md`(v1.4)、`交易订单管理功能需求.md`(v1.3) > **表与生成逻辑**:`sql/biz_supplier_settlement.sql` 已存在;结算单**仅**在订单 `completePay` 时由 `SettlementOnPayService` 插入 --- ## 1. 技术架构 | 项 | 说明 | | --- | --- | | **整体** | RuoYi **v3.9.2**(**springboot2** 分支)单体后端 + 若依 **Vue2** 前端 | | **运行时** | JDK 8、Spring Boot 2.x、Spring MVC、MyBatis、Druid | | **数据库** | MySQL **5.7.39**,InnoDB,`utf8mb4` | | **代码包** | `com.ruoyi.web.modules.trading`(与交易订单同包) | **本模块职责** | 能力 | 实现方 | 说明 | | --- | --- | --- | | 生成结算单 | 交易订单 `completePay` | `SettlementOnPayService` + `SettlementFeeCalculator` + `SettlementNoGenerator`(**已实现**) | | 列表 / 详情 / 完成结算 | 本模块 Controller/Service | **待实现** | | 打印结算凭证 | 前端 | 调详情接口渲染,无独立打印 API | | 跳转订单详情 | — | **不提供**(需求 v1.1) | **后端分层** | 组件 | 职责 | | --- | --- | | `BizSupplierSettlementController` | `GET /list`、`GET /{id}`、`PUT /completeSettle` | | `IBizSupplierSettlementService` / `BizSupplierSettlementServiceImpl` | 查询、完成结算事务 | | `SettlementValidation`(建议) | 结算凭证校验;完成结算前置条件 | | `SettlementRules`(建议) | 状态常量、提示语 | | `BizSupplierSettlementMapper` | 扩充分页列表、`selectById`、`updateCompleteSettle` | | 复用 | `SettlementOnPayService`、`SettlementFeeCalculator`、`SupplierRules.feeMethodName` | **业务摘要** | 场景 | 行为 | | --- | --- | | 列表 | `del_flag=0`;`settlementNo`、`orderNo` 模糊 **AND**;`create_time DESC`;JOIN `biz_supplier` 取 `supplierName` | | 详情 | 主表全字段 + 收费快照 + 凭证 + 状态中文;**无**订单跳转字段/接口 | | 完成结算 | `@Transactional`:`settlement_status=0` → `1`,写凭证与 `settle_finish_time`;**不回写**订单 | | 新增/改/删 | **不提供** | **初始化脚本**:`sql/biz_supplier_settlement.sql`(与订单脚本独立执行即可) --- ## 2. 源码位置 | 类型 | 路径 | | --- | --- | | Controller | `.../controller/BizSupplierSettlementController.java` | | Service | `.../service/IBizSupplierSettlementService.java`、`.../impl/BizSupplierSettlementServiceImpl.java` | | 校验 | `.../support/SettlementValidation.java`、`SettlementRules.java` | | 订单侧生成(已有) | `.../support/SettlementOnPayService.java`、`SettlementNoGenerator.java`、`SettlementFeeCalculator.java` | | Mapper | `.../mapper/BizSupplierSettlementMapper.java` | | XML | `mapper/trading/BizSupplierSettlementMapper.xml` | | 实体 | `.../domain/BizSupplierSettlement.java`(需补凭证字段 getter/setter) | | 测试 | `.../test/.../BizSupplierSettlementServiceImplTest.java`、`BizSupplierSettlementControllerApiTest.java` | --- ## 3. 数据库设计 ### 3.1 主表 `biz_supplier_settlement`(已建表) > 一笔订单一条记录;`uk_order_id` 保证 1:1。金额与费率在**订单完成支付**时写入,本模块**只读**展示,完成结算仅更新状态与凭证。 | 字段名 | 类型 | 非空 | 默认值 | 说明 | | --- | --- | --- | --- | --- | | `id` | `bigint(20)` | Y | 自增 | 主键 | | `settlement_no` | `varchar(14)` | Y | — | `JSD`+`YYYYMMDD`+3 位序号,**唯一** | | `order_id` | `bigint(20)` | Y | — | `biz_trade_order.id`,**唯一** | | `order_no` | `varchar(11)` | Y | — | 冗余,列表按关联订单号模糊 | | `supplier_id` | `bigint(20)` | Y | — | 冗余 | | `total_heads` | `int(11)` | Y | — | 来自订单 | | `total_amount` | `decimal(12,2)` | Y | — | 来自订单(元) | | `fee_method` | `tinyint(4)` | Y | — | 快照:`1` 按户 `2` 按头 `3` 按额 | | `fee_standard` | `decimal(12,2)` | N | NULL | 快照:元/头 | | `transaction_fee_rate` | `decimal(5,2)` | N | NULL | 快照:交易费率 % | | `management_fee_rate` | `decimal(5,2)` | N | NULL | 快照:管理费率 % | | `service_fee_amount` | `decimal(12,2)` | Y | — | 服务费(生成时计算固化) | | `payable_amount` | `decimal(12,2)` | Y | — | 实际应付 = 总金额 − 服务费 | | `settlement_status` | `char(1)` | Y | `'0'` | `0` 待结算 `1` 已完成 | | `settle_voucher_url` | `varchar(512)` | N | NULL | 完成结算时写入 | | `settle_voucher_path` | `varchar(512)` | N | NULL | 完成结算时写入 | | `settle_finish_time` | `datetime` | N | NULL | 结算完成时间 | | `del_flag` | `char(1)` | Y | `'0'` | `0` 存在 `2` 逻辑删除 | | `create_by` / `create_time` / `update_by` / `update_time` | 若依惯例 | — | — | **结算创建时间** = `create_time` | | `remark` | `varchar(500)` | N | NULL | 备注 | **索引**:`PRIMARY KEY (id)`;`UNIQUE uk_settlement_no`;`UNIQUE uk_order_id`;`KEY idx_order_no`;`KEY idx_supplier`;`KEY idx_settlement_status`;`KEY idx_create_time`;`KEY idx_del_flag`。 **DDL**:`sql/biz_supplier_settlement.sql`(无需新增表)。 ### 3.2 关联表(只读) | 表 | 用途 | | --- | --- | | `biz_trade_order` | 完成结算前校验:订单 `order_status=1`、`del_flag=0` | | `biz_supplier` | 列表/详情 `supplier_name` | ### 3.3 枚举 | 字段 | 值 | 含义 | | --- | --- | --- | | `settlement_status` | `0` / `1` | 待结算 / 已完成 | | `del_flag` | `0` / `2` | 正常 / 已删 | | `fee_method` | `1` / `2` / `3` | 按户 / 按头 / 按额(与 `biz_supplier` 一致) | ### 3.4 与订单表关系 ```text biz_trade_order (1) ──uk_order_id──► biz_supplier_settlement (1) ``` - 订单 `order_status=0`:无结算行。 - 订单 `completePay` 成功:插入一行 `settlement_status=0`。 - 本模块 `completeSettle` 成功:`settlement_status=1`;订单仍为 `order_status=1`。 --- ## 4. 字段命名(JSON 小驼峰) | JSON | 库表 | 说明 | | --- | --- | --- | | `id` | `id` | 主键 | | `settlementNo` | `settlement_no` | 结算单编号 | | `orderId` | `order_id` | 关联订单 ID(详情展示,**不用于跳转**) | | `orderNo` | `order_no` | 关联订单编号;列表筛选项 | | `supplierId` | `supplier_id` | | | `supplierName` | — | JOIN `biz_supplier` | | `totalHeads` | `total_heads` | | | `totalAmount` | `total_amount` | | | `feeMethod` | `fee_method` | `1`/`2`/`3` | | `feeMethodName` | — | `SupplierRules.feeMethodName` | | `feeStandard` | `fee_standard` | 按头快照 | | `transactionFeeRate` | `transaction_fee_rate` | 按额快照 % | | `managementFeeRate` | `management_fee_rate` | 按额快照 % | | `serviceFeeAmount` | `service_fee_amount` | | | `payableAmount` | `payable_amount` | | | `settlementStatus` | `settlement_status` | `0`/`1` | | `settlementStatusName` | — | 待结算 / 已完成 | | `settleVoucherUrl` / `settleVoucherPath` | 结算凭证 | 完成结算入参;已完成可预览 | | `createTime` | `create_time` | 结算创建时间 | | `settleFinishTime` | `settle_finish_time` | 结算完成时间 | | `settlementNo`(筛) | `settlement_no` | 列表模糊 `LIKE` | | `orderNo`(筛) | `order_no` | 列表模糊 `LIKE` | --- ## 5. 核心业务实现 ### 5.1 结算单生成(订单模块,已实现) 触发:`PUT /tradeMarket/tradeOrder/completePay` 事务内调用 `SettlementOnPayService.createFromOrder`。 | 步骤 | 说明 | | --- | --- | | 幂等 | `selectByOrderId` 已存在 → 抛错,订单保持待支付 | | 编号 | `SettlementNoGenerator`:`JSD`+日期+3 位;当日超 999 与订单编号策略一致抛错 | | 费用 | `SettlementFeeCalculator`:`HALF_UP` 2 位小数;快照 `fee_*` 与 `service_fee_amount`、`payable_amount` | | 初始状态 | `settlement_status=0`;凭证、完成时间为空 | 公式(与功能需求 §3.5 一致): ```text fee_method=1 → serviceFee = 0 fee_method=2 → serviceFee = totalHeads × feeStandard fee_method=3 → serviceFee = totalAmount × (transactionFeeRate + managementFeeRate) / 100 payableAmount = totalAmount − serviceFee ``` ### 5.2 完成结算 `completeSettle`(本模块) **接口**:`PUT /tradeMarket/supplierSettlement/completeSettle` **事务步骤**(全部成功或回滚): 1. `SettlementValidation.validateSettleVoucher`:`id`、`settleVoucherUrl`、`settleVoucherPath` 非空;后缀 `jpg|jpeg|png`(与 `TradeOrderValidation.validatePayVoucher` 规则一致;大小 ≤10MB 由 `/common/upload` 保证)。 2. `selectBizSupplierSettlementById`:`del_flag=0`;`settlement_status=0`;否则「仅待结算状态可完成结算」。 3. `biz_trade_order`:`order_id` 对应订单 `order_status=1` 且 `del_flag=0`;否则业务异常。 4. `UPDATE biz_supplier_settlement SET settlement_status='1', settle_voucher_url=?, settle_voucher_path=?, settle_finish_time=now(), update_by=?, update_time=now() WHERE id=? AND settlement_status='0' AND del_flag='0'`;`updated=0` → 已完成或并发冲突提示。 5. **不** `UPDATE` 订单表。 **幂等**:已完成不展示「完成结算」;接口层对 `settlement_status=1` 直接拒绝。 ### 5.3 列表 / 详情 - 列表 SQL:`FROM biz_supplier_settlement s LEFT JOIN biz_supplier sup ON s.supplier_id = sup.id AND sup.del_flag='0' WHERE s.del_flag='0'`。 - 详情:在列表字段基础上返回收费快照明细(`feeMethod` + 对应费率字段);**不**组装订单 `lineList`、支付凭证。 - 排序:`s.create_time DESC, s.id DESC`。 - 默认分页:`pageSize=20`。 ### 5.4 实体与 Mapper 补齐(实现时注意) 当前 `BizSupplierSettlement` / `BizSupplierSettlementMapper.xml` 仅支持 `insert`、`selectByOrderId`、编号序号查询。实现本模块前需: - 实体增加 `settleVoucherUrl`、`settleVoucherPath`;`resultMap` 映射 `settle_finish_time` 及凭证列。 - 新增 `selectBizSupplierSettlementList`、`selectBizSupplierSettlementById`、`updateCompleteSettle`。 --- ## 6. 接口设计 **Base Path**:`/tradeMarket/supplierSettlement` **权限**:`tradeMarket:supplierSettlement:list|query|settle` **响应**:`AjaxResult` / `TableDataInfo`(`code`、`msg`、`rows`/`data`) | 说明 | HTTP | URI | 权限 | | --- | --- | --- | --- | | 分页列表 | GET | `/list` | `list` | | 详情 | GET | `/{id}` | `query` | | 完成结算 | PUT | `/completeSettle` | `settle` | > 本期**无** `POST`/`DELETE`/`PUT /` 全量修改。打印凭证由前端根据详情数据生成,**无** `/print` 接口。 ### 6.1 列表 `GET /list` | 参数 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `pageNum` | int | N | 默认 `1` | | `pageSize` | int | N | 默认 `20` | | `settlementNo` | string | N | 结算单编号模糊 | | `orderNo` | string | N | 关联订单编号模糊 | - 条件:`del_flag=0`;两筛选项同时传则 **AND**。 - 行字段:功能需求 §5.2 所列(小驼峰见 §4)。 - `settlementStatus=0`:操作区「完成结算」「查看」;`1`:「打印凭证」「查看」(前端按权限显隐)。 ### 6.2 详情 `GET /{id}` - `data`:`BizSupplierSettlement` 全量展示字段 + `supplierName` + `feeMethodName` + `settlementStatusName`。 - **不返回**订单跳转 URL;**不嵌套**订单明细 `lineList`。 ### 6.3 完成结算 `PUT /completeSettle` | Body | 必填 | 说明 | | --- | --- | --- | | `id` | Y | 结算单主键 | | `settleVoucherUrl` | Y | 先 `POST /common/upload` | | `settleVoucherPath` | Y | 上传返回路径 | - 成功:`code=200`;`settlementStatus=1`;`settleFinishTime` 有值。 - 失败:保持 `settlement_status=0`;`msg` 示例见功能需求 §12。 ### 6.4 前端联调(共享) | 用途 | 接口 | | --- | --- | | 结算凭证上传 | `POST /common/upload` | | 查订单(用户自行) | `GET /tradeMarket/tradeOrder/list?orderNo=…`(**非**本模块跳转) | --- ## 7. 关联方案:交易订单管理 ### 7.1 职责边界 | 能力 | 交易订单 | 供应商结算(本模块) | | --- | --- | --- | | 写 `biz_supplier_settlement` | `completePay` 插入 | — | | 读 / 完成结算 | — | `list` / `{id}` / `completeSettle` | | 支付凭证 | 订单表 | — | | 结算凭证 | — | 结算表 | | 平台业务终点 | 订单已完成 | **结算已完成**(需求 v1.1) | | 跨模块跳转 | — | **禁止**跳转订单详情 | ### 7.2 端到端时序 ```mermaid sequenceDiagram participant O as tradeOrder participant S as supplierSettlement O->>O: completePay(支付凭证) O->>S: insert 待结算+费用快照 S->>S: completeSettle(结算凭证) Note over S: 不回写订单;流程结束 ``` ### 7.3 状态对照 ```text 订单 order_status: 0 待支付 ──completePay──► 1 已完成 结算 settlement_status: (无) ──生成──► 0 待结算 ──completeSettle──► 1 已完成 [平台终点] ``` ### 7.4 异常协同(实现校验要点) | 场景 | 处理 | | --- | --- | | 订单支付失败 | 无结算行 | | 订单支付成功 | 必有 1 条 `settlement_status=0` | | 结算完成失败 | 保持待结算,可重试 | | 结算已完成 | 拒绝 `completeSettle`;订单仍已完成 | | 订单已逻辑删除 | 不应存在结算;若存在则完成结算校验失败 | ### 7.5 与订单技术方案交叉引用 | 订单方案章节 | 本模块对应 | | --- | --- | | §3.3 `biz_supplier_settlement` | §3.1 同表 | | §5.4 `completePay` | §5.1 生成逻辑 | | §7.2 结算接口建议 | §6 定稿接口 | | §7.3 状态一致性 | §7.3 | --- ## 8. 菜单与权限(示例) | 类型 | 名称 | 权限标识 | | --- | --- | --- | | 菜单 | 供应商结算管理 | `tradeMarket:supplierSettlement:list` | | 按钮 | 查询 | `tradeMarket:supplierSettlement:query` | | 按钮 | 完成结算 | `tradeMarket:supplierSettlement:settle` | 组件路径建议:`tradeMarket/supplierSettlement/index`(与 `tradeOrder/index` 并列,**无**路由参数跳转订单)。 --- ## 9. 交付清单 - [x] `sql/biz_supplier_settlement.sql` - [x] `SettlementOnPayService`、`SettlementFeeCalculator`、`SettlementNoGenerator` - [x] `BizSupplierSettlement` 凭证字段 + Mapper 列表/详情/完成结算 - [x] `BizSupplierSettlementController`、`IBizSupplierSettlementService` 实现 - [x] `SettlementValidation` / `SettlementRules` - [ ] 菜单 SQL / 权限配置 - [x] 单元测试 + MockMvc(`SettlementValidationTest`、`BizSupplierSettlementServiceImplTest`、`BizSupplierSettlementControllerApiTest`) --- ## 10. 修订记录 | 版本 | 说明 | | --- | --- | | 1.0 | 初稿:对齐功能需求 v1.1;复用已有表与订单侧生成逻辑;列表/详情/完成结算接口;与交易订单关联方案 |