docs: add design for contract no date following sign date
Capture agreed rules: keep sequence when sign date changes, frontend preview plus backend authoritative align on save, and sync name parentheses. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
40fc54942b
commit
1c38d82079
1 file changed
+96
@@ -0,0 +1,96 @@
|
||||
# CRM 合同编号日期段跟随签订日期 — 设计
|
||||
|
||||
**日期**:2026-08-03
|
||||
**范围**:`web-admin` 合同管理新增/编辑;`backend` 合同 create/update(草稿)
|
||||
**状态**:已评审,待实现
|
||||
|
||||
## 背景
|
||||
|
||||
合同编号格式为 `{供方编码}/X-JT{yyyyMMdd}{3位序号}`(例:`SX/X-JT20250803001`)。
|
||||
日期段来自签订日期,但当前改签订日期时编号不更新;选报价单带入 `quoteDate` 会改签订日,编号仍可能与日期不一致。
|
||||
|
||||
## 目标
|
||||
|
||||
1. 签订日期变更后,标准格式合同编号中的 **日期段** 跟随更新。
|
||||
2. **前端即时预览** + **后端保存时校验/校正**;撞号时由后端定最终号。
|
||||
3. 合同名称末尾括号内编号与合同编号同步。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不新增合同编号预览 API。
|
||||
- 不改合同编号租户内唯一索引 / 既有迁移脚本。
|
||||
- 不改续签命名规则。
|
||||
- 不做历史数据批量重刷。
|
||||
- 非草稿合同仍不可编辑(沿用现有约束)。
|
||||
|
||||
## 行为规则
|
||||
|
||||
### 标准格式
|
||||
|
||||
```
|
||||
^([A-Z]+)/X-JT(\d{8})(\d{3})$
|
||||
```
|
||||
|
||||
仅当当前编号匹配该格式时才联动;手改成非标准格式则 **不联动**。
|
||||
|
||||
### 改号策略(方案 A + 权威后端)
|
||||
|
||||
1. 用签订日的 `yyyyMMdd` 替换日期段,**保留原 3 位序号**。
|
||||
2. 后端若候选号已被占用(租户内,**含软删**;编辑时排除本条),则序号 +1 直至可用(重试上限与现有 `generate_contract_no` 一致,约 50 次)。
|
||||
3. 编号为空:仍走现有「保存时按签订日全新生成」。
|
||||
4. 编号日期段已与签订日一致:前后端均 no-op。
|
||||
|
||||
### 名称同步
|
||||
|
||||
编号变更后,合同名称末尾 `(…)` / `(…)` 替换为新编号;与现有 `generate_contract_name`、前端名称重建习惯一致。
|
||||
|
||||
### 触发点
|
||||
|
||||
| 场景 | 行为 |
|
||||
|------|------|
|
||||
| 表单改签订日期 | 前端即时替换日期段 + 同步名称 |
|
||||
| 选报价单带入 `quoteDate` | 经同一签订日变更路径,自然联动 |
|
||||
| 换交易主体 | 仍只换供方编码前缀(现有逻辑),不因本需求改策略 |
|
||||
| create / update(草稿)保存 | 后端 align;撞号顺延;再生成/校正合同名称 |
|
||||
|
||||
## 实现要点
|
||||
|
||||
### 前端
|
||||
|
||||
主路径:`web-admin/src/views/crm/contract/components/ContractFormDialog.vue`
|
||||
必要时对齐遗留页:`form.vue`。
|
||||
|
||||
- 在 `handleSignDateChange` 中,更新合同期限后调用 `syncContractNoDateFromSignDate`。
|
||||
- 匹配标准正则则替换 8 位日期,保留序号;再同步名称括号内编号。
|
||||
- 前端 **不** 做撞号查询;预览号可能与保存结果不同,以接口返回为准。
|
||||
|
||||
### 后端
|
||||
|
||||
文件:`backend/app/crud/crm/contract.py`
|
||||
|
||||
- 新增 `align_contract_no_to_sign_date(...)`:标准格式换日期段;再按 `contract_no_exists` 撞号顺延。
|
||||
- **create**:有编号则先 align 再查重/落库;无编号则 `generate_contract_no(..., sign_date=…)`。
|
||||
- **update**:对提交编号(或原号)align,写回 `contract_no`,再用 `generate_contract_name` 校正名称。
|
||||
- 唯一性口径不变:租户内含软删、删除后不复用。
|
||||
|
||||
## 边界与错误
|
||||
|
||||
- 签订日清空:不改编号;合同期限按现有逻辑清空。
|
||||
- 同时改签订日 + 手改编号:后端按 **最终提交的编号** + **最终签订日** align;已非标准则不 align。
|
||||
- 序号顺延耗尽:抛错「生成合同编号失败,请稍后重试」,不静默写脏数据。
|
||||
- 非草稿 update:仍拒绝修改。
|
||||
|
||||
## 验收用例
|
||||
|
||||
1. 改签订日 → 编号日期段变、序号不变;名称括号同步。
|
||||
2. 目标号已占用 → 保存后序号顺延为可用号。
|
||||
3. 手改非标准编号 → 改签订日编号不变。
|
||||
4. 选报价单改签订日 → 编号日期段跟随(标准格式时)。
|
||||
5. 换交易主体 → 仅供方前缀变化,日期/序号策略与现网一致。
|
||||
6. 编号为空新增保存 → 仍按签订日生成完整新号。
|
||||
|
||||
## 决策记录
|
||||
|
||||
- 序号:保留原序号,撞号再顺延(A)。
|
||||
- 职责:前端预览 + 后端权威校正(两边都做)。
|
||||
- 名称:编号变更时名称内编号同步更新。
|
||||
Reference in new issue
Block a user