# 采集协议单 · 缴费默认定价与明细规则设计 **日期**:2026-07-06 **范围**:`web-admin` 采集协议单新增/编辑(`ProtocolFormDialog.vue`)、标准信息导入、后端缴费保存校验 **前置 spec**:[2026-06-04-protocol-pay-mode-switch-design.md](./2026-06-04-protocol-pay-mode-switch-design.md)、[2026-06-10-protocol-installment-config-design.md](./2026-06-10-protocol-installment-config-design.md) **状态**:已实现 --- ## 1. 背景与目标 业务方给出「样本数 × 缴费模式」下的**默认合同金额、默认期数、默认各期金额**。这些数值仅作录入辅助;用户可自由修改合同金额、分期期数、各期金额;趸交也可拆成多条缴费明细(如预付款 + 尾款)。 当前实现与目标的主要差距: | 维度 | 现状 | 目标 | |------|------|------| | 合同金额来源 | 非作废样本 `price` 之和 | 按定价表填**默认**,用户可改;样本数变化**不**自动改金额 | | 分期默认金额 | 均分或历史 50/10/10… | 固定模板(6,480 / 3,880…) | | 分期默认期数 | 一律 6 期 | 1 样本 6 期;2 样本分期/混合 5 期 | | 缴费模式 | `dj` / `fq` | 增加双样本 **趸交+分期** `djfq` | | 趸交明细条数 | 后端禁止多条 `dfj` | 允许多条,合计 = 合同金额 | | 默认填充时机 | 切分期、改样本价等会联动 | **方案 B**:仅新建或**首次**选缴费模式时填默认 | --- ## 2. 决策记录 | 议题 | 决定 | |------|------| | 默认值性质 | 仅初始填充,**不锁定**;用户可改合同金额、期数、各期金额 | | 样本数变化 | **不**自动改合同金额、期数、明细(方案 B) | | 缴费模式变化 | **首次**从空/未选切到某模式时填该模式默认;已选过且用户已编辑后,再次切换仍走既有「模式切换」确认流(见 §6) | | 单样本分期默认合同额 | **25,880**(6,480 + 3,880×5) | | 趸交默认合同额 | 优惠价:1 样本 **22,880**;2 样本 **37,880** | | 双样本「趸交+分期」 | 新模式 `djfq`,默认 **41,000**,5 期:22,880、6,480、3,880、3,880、3,880 | | 双样本纯分期 | 默认 **44,000**,5 期:12,960、7,760、7,760、7,760、7,760 | | 趸交多条明细 | 允许;`Σ dueAmount(全部明细)= contractAmount`;保存时不再限制「仅 1 条 dfj」 | | 样本 `price` 字段 | 仍维护样本单价;与合同默认**解耦**;导入/保存时可提示样本价合计与合同额不一致,**不阻断** | | 定价表存放 | 前端 `protocol-payment-presets.ts`(常量);后端镜像校验逻辑不依赖默认表,只校验合计与条数 | --- ## 3. 默认定价表 有效样本数 = 当前协议单内 `sampleStatus !== 'yzf'` 的样本条数,取值 **1** 或 **2**(与现网一致,不支持 0 样本保存缴费)。 | 样本数 | `pay_mode` | 默认合同金额 | 默认期数 | 默认各期金额(元) | |--------|------------|-------------|----------|-------------------| | 1 | `dj` | 22,880 | — | 单条明细 `dueAmount = 22,880`(用户可拆多条) | | 1 | `fq` | 25,880 | 6 | 6,480、3,880、3,880、3,880、3,880、3,880 | | 2 | `dj` | 37,880 | — | 单条明细 `dueAmount = 37,880`(用户可拆多条) | | 2 | `djfq` | 41,000 | 5 | 22,880、6,480、3,880、3,880、3,880 | | 2 | `fq` | 44,000 | 5 | 12,960、7,760、7,760、7,760、7,760 | **标签**:`djfq` 展示为「趸交+分期」;字典 `status-tag-registry` / 后端摘要增加 `djfq` → `趸交+分期`。 **双样本时缴费模式选项**:`dj`、`djfq`、`fq`(隐藏或禁用 `djfq` 当样本数 ≠ 2)。 --- ## 4. 默认填充时机(方案 B) ### 4.1 会填充默认的场景 1. **新建协议单**,用户**第一次**选择缴费模式(`pay_mode` 从初始 `dj` 切到 `fq` / `djfq`,或新建后首次进入缴费 Tab 且明细为空时的初始化,与产品确认以「首次 `onPayModeChange` 且该模式从未应用过」为准)。 2. **新建协议单**,打开时若默认 `pay_mode=dj` 且 `paymentDetails` 为空:按 **当前样本数** 填趸交默认(合同额 + 1 条明细)。若此时样本数仍为 0,待用户添加第 1 个样本后**不**自动重填(方案 B);用户选模式或手动点「套用默认」时再填。 > **实现建议**:维护 `paymentDefaultsApplied: Record`(或 `lastAppliedPresetKey: string | null`)。某 `pay_mode` 第一次生效时调用 `applyPaymentPreset(sampleCount, payMode)`,并标记已应用。 ### 4.2 不会自动改金额的场景 - 增删样本、样本作废/恢复 - 修改样本 `price` - 修改合同金额后回头改样本 用户自行改合同额、期数、明细;仅触发**合计校验**与既有「分期参数变更 / 模式切换」确认流。 ### 4.3 可选辅助(P1,非本期必须) 缴费主表旁「恢复默认」按钮:按当前样本数 + 当前 `pay_mode` 重新套用 §3 定价表,**需二次确认**。 --- ## 5. 缴费明细与校验 ### 5.1 趸交 `dj` - 明细 **≥ 1** 条;用户可通过「添加明细」增加(含预付款场景)。 - `canAddPaymentDetail`:改为在 `dj` 下**始终允许**添加(或:待缴条数无硬上限,仅校验合计)。 - 保存校验: - `Σ dueAmount(全部明细)` 与 `contractAmount` 差额 ≤ 0.01; - 允许多条 `dfj`; - 若存在 `yjf`:`Σ yjf.dueAmount + Σ dfj.dueAmount` 仍须等于 `contractAmount`(与现 `remaining` 逻辑一致,但允许多条 `dfj` 分摊剩余)。 ### 5.2 分期 `fq` 与混合 `djfq` - 明细条数 **=** `installment_count`(与现 `fq` 一致)。 - `installment_ratios` 存**各期金额(元)**,非百分比(与现网一致)。 - `Σ 各期 dueAmount = contractAmount`。 - `djfq` 在数据层按分期处理:每期有 `installmentNo`、应缴日;第 1 期金额语义为「趸交部分」,不做单独子表。 ### 5.3 与标准信息导入 - 导入解析到的 `contractAmount`、多笔 `transfer` **覆盖**默认填充(与 [2026-07-02-protocol-standard-import-design.md](./2026-07-02-protocol-standard-import-design.md) 一致)。 - 导入后标记 `paymentDefaultsApplied` 全部为已应用,避免再自动覆盖。 --- ## 6. 缴费模式切换(在 2026-06-04 上的修订) 既有切换规则(已缴锁定、确认流)**保留**。下列条目**修订**原 spec: | 原规则 | 新规则 | |--------|--------| | 趸交仅 1 条有效明细 | 趸交可多条;切换生成时仍可合并为 1 条**默认**,用户随后可拆 | | `pay_mode` 仅 `dj`/`fq` | 增加 `djfq`;`djfq` ↔ `fq` 按分期规则;`djfq` → `dj` 同 `fq` → `dj` | | 切换后分期金额均分 | 切换后若走「重建明细」,使用 §3 对应默认各期金额(非均分) | **双样本 → 单样本**(或反向):不自动改合同/明细(方案 B);若当前 `pay_mode=djfq` 且样本数变为 1,**阻断保存**并提示「请切换缴费模式」,或自动要求用户改模式(推荐:**保存前校验**样本数与 `djfq` 一致)。 --- ## 7. 数据模型 ### 7.1 `biz_protocol_payment.pay_mode` | 值 | 含义 | |----|------| | `dj` | 趸交 | | `fq` | 分期 | | `djfq` | 趸交+分期(仅双样本) | 字段长度 `varchar(8)` 足够。无需新列;`installment_count` / `installment_ratios` 在 `djfq` 与 `fq` 用法相同。 ### 7.2 迁移 - 字典项(若缴费模式走 dict):增加 `djfq`。 - 历史数据无 `djfq`,只读展示兼容即可。 --- ## 8. UI ### 8.1 缴费模式 ```text [ 趸交 ] [ 分期 ] // 1 样本 [ 趸交 ] [ 趸交+分期 ] [ 分期 ] // 2 样本 ``` ### 8.2 分期金额区 - `fq` / `djfq`:展示期数、间隔、开始时间、各期金额输入格;默认期数/金额来自 §3。 - 合计行:`合计 xxx / 合同 xxx`(已有)。 ### 8.3 样本价格 - 样本 Tab 的「价格」保留;**移除** `syncContractAmount()` 在样本价变更时对 `contractAmount` 的自动写入(方案 B)。 - 可选弱提示:样本价合计 ≠ 合同金额时展示 `form-tip`(不阻断保存)。 --- ## 9. 后端改动摘要 | 文件 | 改动 | |------|------| | `protocol_pay_mode_switch.py` | `dj`:删除「仅 1 条 dfj」;改为明细总额校验;支持 `djfq` 走 `fq` 分支 | | `collection_protocol.py` | 读写 `pay_mode=djfq`;列表/详情标签 | | `qc_work_order_fee_summary.py` 等 | `djfq` 标签与分期展示 | --- ## 10. 前端改动摘要 | 文件 | 改动 | |------|------| | `protocol-payment-presets.ts` | **新建**,§3 定价表 + `applyPaymentPreset()` | | `protocol-payment-installment.ts` | 默认金额生成改为调用 preset(均分仅作无 preset 时的兜底) | | `protocol-pay-mode-switch.ts` | `dj` 多明细;`PayMode` 含 `djfq` | | `ProtocolFormDialog.vue` | 模式 UI、首次填充、去掉样本价→合同额联动 | | `ProtocolViewDialog.vue` | `djfq` 展示 | | `status-tag-registry.ts` | `djfq` | | `protocol-standard-import-parse.ts` | 识别「趸交+分期」文案 → `djfq`(P1) | --- ## 11. 测试要点 - [ ] 新建 1 样本,首次选 `fq` → 合同 25,880,6 期金额正确 - [ ] 新建 2 样本,首次选 `djfq` → 41,000,5 期正确 - [ ] 改样本数 1→2,合同/明细**不变** - [ ] 趸交添加 2 条明细,合计 = 合同额,保存成功 - [ ] 趸交 2 条 `dfj` 预付款场景,保存成功 - [ ] 修改各期金额后合计 ≠ 合同额,前后端均拦截 - [ ] 模式切换 + 已缴锁定,仍符合 2026-06-04 - [ ] 2 样本 `djfq` 删至 1 样本,保存提示改模式 - [ ] 标准导入多笔转账 + 趸交,保存成功 --- ## 12. 范围外 - 定价表后台可配置化(本期写死常量) - 3 个及以上样本 - 按样本绑定不同缴费模式(每样本独立主表) --- ## 13. 修订记录 | 日期 | 说明 | |------|------| | 2026-07-06 | 初稿:默认定价表、方案 B、djfq、趸交多明细 |