Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,15 @@ pnpm validate # 每次改元数据后跑;其余检查见 AGENTS.md §6
| 版本 | 内容 | 累计对象 |
|---|---|---|
| v0.1(已合入,PR #5) | 内部工作台:主数据、两级准入审批、资质到期扫描 | 7 |
| v0.2 | 物料只读副本、银行账户、存量导入、信息变更单 | 10 |
| v0.2(已合入,PR #13–#18) | 物料只读副本、银行账户、存量导入、信息变更单 | 10 |
| v0.3 | 合同与协议、供应商处置 | 13 |
| v0.4 | 交付记录导入、质量问题 / SCAR、供应商审核 | 16 |
| v0.5 | 绩效、风险事件、管理报表 = 内部版 MVP,试运行 | 20 |
| v0.6 | 供应商门户(依赖 objectstack#25233) | 21 |
| v0.7 | 寻源与封标、价格库;核心对象冻结 | 27 |

已完成:核心设计、三个扩展包设计(保留)、ADR-0001~0009、参数文件首版、体系文件生成脚本
和 12 份模板、v0.1 内部工作台(PR #5)。文档目录见 [docs/README.md](./docs/README.md);
和 12 份模板、v0.1 内部工作台(PR #5)、v0.2 主数据补齐(PR #13–#18)。文档目录见 [docs/README.md](./docs/README.md);
参与开发前先读 [AGENTS.md](./AGENTS.md)。

下一步:v0.2 主数据补齐——物料只读副本、银行账户、存量导入、信息变更单([07 §1](./docs/design/07-delivery-plan.md#1-分期路线图))。
下一步:v0.3 合同与处置——合同与合同行、供应商处置单([07 §1](./docs/design/07-delivery-plan.md#1-分期路线图))。
38 changes: 32 additions & 6 deletions docs/design/02-domain-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ erDiagram
| `is_related_party` | boolean | 默认 false;存在关联关系申报时为 true(FR-904) |
| `quality_agreement_signed` / `integrity_agreement_signed` | boolean | 默认 false;协议生效时由合同 flow 置为 true |
| `erp_vendor_code` | text | ERP 供应商编码,唯一;预留,ERP 集成前空着或由采购员手工填写 |
| `last_change_request` | lookup → 信息变更单(只读) | 最近一次写回本档案的变更单,由 `srm_change_apply` 写入(v0.2) |
| `portal_position` | text | 门户岗位标识,如 `srm_vendor_sup0000128`;开通门户时写入,只读。校验规则:非空时必须以 `srm_vendor_` 开头(没开通门户的供应商为空)。v0.6 加 |
| `legacy_imported` | boolean | 默认 false;存量导入的供应商为 true(v0.2)。只能在新建时置为 true:`readonlyWhen: previous.legacy_imported != true`,已建档的供应商重复导入时该列被忽略;只有 `srm_admin` 可写 |
| `legacy_reviewed` | boolean | 默认 false;品类经理核对后经「确认复核」按钮置为 true。`legacy_imported && !legacy_reviewed` 的供应商列在「存量待复核」视图(v0.2) |
Expand All @@ -209,6 +210,12 @@ erDiagram
| `expired_certificate_count` | summary | `count` 资质证书,条件 `status == 'expired'` |
| `default_bank_account_count` | summary | `count` 银行账户,条件 `is_default == true`;「每家至多一个默认账户」的校验读它(v0.2) |

关键信息锁定(v0.2):`name`、`country`、`credit_code`、`registration_no`、`legal_representative`、
`registered_capital`、`address` 在 `potential` / `qualifying` 期间可以直接改;准入通过后(合格、冻结、
淘汰、黑名单)只能经信息变更单修改。实现为校验规则 `key_info_via_change_request`:这些字段有变化而
`last_change_request` 没变时拒绝写入;`last_change_request` 只读,只有写回 flow 能带着它一起写。
不用 `readonlyWhen`,因为它连系统身份的写入也挡,写回 flow 就写不进去。

**`srm_supplier_contact` 供应商联系人**(master_detail → 供应商;OWD `controlled_by_parent`)

| 字段 | 类型 | 说明 |
Expand All @@ -231,7 +238,7 @@ erDiagram
| `currency` | select | `cny` / `usd` / `eur` / `jpy` / `hkd`,默认 `cny` |
| `status` | select(stageField,只读) | `pending_verify` 待核验(新建默认)/ `active` 有效 / `inactive` 停用;只由 flow 写入,状态机 `pending_verify → active ⇄ inactive` |
| `verified_by` | user(只读) | 核验人(应付会计),由「核验银行账户」screen flow 写入 |
| `is_default` | boolean | 默认 false;只有 `active` 的账户可设为默认(校验规则);每家至多一个默认账户(校验规则读供应商的 `default_bank_account_count`) |
| `is_default` | boolean | 默认 false;只有 `active` 的账户可设为默认(校验规则,新建与修改都拦;不用 `readonlyWhen`,变更单停用原账户时要同时取消默认);每家至多一个默认账户(校验规则读供应商的 `default_bank_account_count`) |
| `erp_bank_id` | text(只读) | 预留,ERP 集成前空着 |

锁定:开户行、支行、户名、账号、SWIFT、币种在任何状态下都 `readonlyWhen` 只读(新建时可填)——
Expand Down Expand Up @@ -324,11 +331,30 @@ upsert 写入,结构不变。
`status`(`planned` / `done` / `cancelled`)。问题项可经「转整改单」screen flow 生成
`srm_quality_issue`(`source = audit`)。

**`srm_supplier_change_request` 信息变更单**(v0.2):`supplier`、`change_type`
(`basic` 基本信息 / `bank_account` 银行账户 / `address` 地址 / `contact` 联系人)、
`before_value` / `after_value`(json,变更前后快照)、`reason`、`status`、
`purchase_approver` / `finance_approver`(user)、`applied_at`(审批通过后写回档案
的时间)。门户上线前由采购员代供应商发起。
**`srm_supplier_change_request` 信息变更单**(OWD `private`;v0.2)。门户上线前由采购侧代供应商在
供应商档案下新建,新建即进入审批(03 §5)。

| 字段 | 类型 | 说明 |
|---|---|---|
| `change_no` | autonumber | `CHG{YYYY}{00000}` |
| `supplier` | lookup → 供应商 | 必填;新建后只读 |
| `change_type` | select | `basic` 基本信息 / `bank_account` 银行账户 / `address` 地址 / `contact` 联系人;新建后只读 |
| `reason` | textarea | 必填 |
| `new_name` / `new_credit_code` / `new_registration_no` / `new_legal_representative` / `new_registered_capital` | text / currency | 基本信息的新值,至少填一项,留空的保持原值 |
| `new_address` | address | 地址变更必填 |
| `bank_account` | lookup → 银行账户 | 被替换的原账户:必须属于本供应商、状态为 `active`;新建后只读 |
| `new_bank_name` / `new_branch_name` / `new_account_name` / `new_account_no` / `new_swift_code` / `new_currency` | text / select | 新账户。户名规则同银行账户;`new_account_no` 同样脱敏并要求 `srm_view_bank_account_no`,所以银行账户变更只能由持该能力的岗位(品类经理、采购主管)发起 |
| `contact` | lookup → 联系人 | 联系人变更必填,必须属于本供应商;新值 `new_contact_name` / `new_mobile` / `new_email` |
| `status` | select(stageField,只读) | `in_review` 审批中 / `applied` 已生效 / `rejected` 已驳回;只由 flow 写入 |
| `approval_status` | select(只读) | 审批节点镜像:`pending` / `approved` / `rejected` / `returned` 退回修改 / `recalled` |
| `purchase_approver` / `finance_approver` | user(只读) | 两级审批的实际审批人,flow 从审批记录写入 |
| `reject_reason` | textarea(只读) | 驳回时的审批意见 |
| `before_value` / `after_value` | json(只读) | 新建时快照的当前档案 / 写回后的档案;银行账号不进快照(BR-20) |
| `applied_at` | datetime(只读) | 写回时间 |
| `new_bank_account` | lookup → 银行账户(只读) | 银行账户变更写回时新建的账户 |

新值用分类型字段而不是直接编辑 json:表单能按类型显示、校验,退回后发起人能直接改。变更内容只在新建时和
`approval_status == 'returned'` 期间可改(`readonlyWhen`),审批中平台锁定记录。

**`srm_supplier_disposition` 供应商处置单**(v0.3):`supplier`、`action`
(`freeze` / `unfreeze` / `eliminate` / `blacklist` / `remove_blacklist`)、
Expand Down
29 changes: 20 additions & 9 deletions docs/design/03-processes-and-automation.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,13 +190,24 @@ flowchart TD
`verified_by`。flow 拒绝三种情况:启动人不是应付会计、账户不是待核验、启动人就是新建人
(双人原则)。已有账户的修改不直接编辑,走下面的信息变更单。

**信息变更**(v0.2,FR-207):供应商在门户经「提交变更申请」screen flow 提交变更单(v0.6 前由采购员代供应商发起)→
`before_value` 自动快照当前档案 → 审批 flow `srm_change_approval`:第 1 级
`position = srm_buyer_lead`(采购确认);`change_type == 'bank_account'` 时增加第 2 级
`position = srm_ap_accountant`(财务复核),
两级审批人由不同岗位担任(BR-11)→ 通过后 flow 把 `after_value` 写回供应商或银行
账户,新银行账户为 `active`,旧账户为 `inactive`。驳回时通知供应商并写明原因。ERP 侧的
银行账户由财务按 SRM 的审批记录维护(ERP 集成为预留集成点)。
**信息变更**(v0.2,FR-207):门户上线前由采购侧代供应商在供应商档案下新建变更单(v0.6 起供应商在门户经
「提交变更申请」screen flow 提交),填写变更后的值 → 审批 flow `srm_change_approval` 新建即触发,先把当前档案
快照到 `before_value` → 第 1 级 `position = srm_buyer_lead`(采购确认);`change_type == 'bank_account'` 时
增加第 2 级 `position = srm_ap_accountant`(财务复核,核实方式按 `params/core.yaml` 的 `bank_change_verification`)
→ 通过后子 flow `srm_change_apply` 以系统身份写回:基本信息、地址写回供应商(同时写 `last_change_request`,
见 02 §4.1 关键信息锁定),联系人写回联系人;银行账户变更停用原账户(是默认账户的同时取消默认)、按新值建一个
`active` 账户,核验人记为财务复核人,原账户是默认的新账户接着做默认 → 写回后的档案快照到 `after_value`,
变更单为 `applied`,通知发起人。

- **驳回**:不改主记录,审批意见写入 `reject_reason`,通知发起人。
- **退回修改**:第 1 级可以退回(`revise` → `approval_revise`,至多 3 次),记录解锁,发起人改完重新提交,
从第 1 级重新审批。**临时做法**:第 2 级只能通过或驳回、不能退回——平台 18.0.0 把第 2 个审批节点的提交人记成
第 1 级审批人,退回后发起人无法重新提交(objectstack#24817 已在主干修复、未发版);发版后加回退回。
- **职责分离(BR-11)**:发起人不能审批本人的变更单,两级审批人不能是同一人。平台没有「提交人不得审批」开关
(objectstack#25446),岗位又可能兼任,所以每级通过后 flow 读审批记录比对,撞人时这次通过不算数,通知审批人
并重新开一轮同级审批。审批人在节点开启时按岗位解析:只有一位采购主管且他就是发起人时,要再任命一位。

ERP 侧的银行账户由财务按 SRM 的审批记录维护(ERP 集成为预留集成点)。

**供应商处置**(v0.3,FR-208):品类经理发起处置单 → 审批:冻结 / 解冻为品类经理 →
采购总监;淘汰与黑名单再加 `position = srm_general_manager`;解除黑名单单独走同一条
Expand Down Expand Up @@ -377,7 +388,7 @@ flow 属于 ERP 集成后的门户镜像,现阶段不建。
| `srm_certificate_expiry_notice` | time_relative:`valid_to` −30 / −15 / −7 天 | 资质证书 | v0.1 |
| `srm_certificate_expire_sweep` | schedule:每日 01:00(追赶式) | 资质证书 | v0.1 |
| `srm_supplier_qualification_recalc` | record_change:证书、品类资格写入 | 资质证书 → 供应商 | v0.1 |
| `srm_change_approval` / `srm_change_apply` | record_change | 变更单、银行账户 | v0.2 |
| `srm_change_approval` / `srm_change_apply` | record_change:变更单新建 / 子 flow | 变更单 → 供应商、银行账户、联系人 | v0.2 |
| `srm_contract_approval` | record_change:状态→`in_review` | 合同 | v0.3 |
| `srm_contract_expiry_notice` / `srm_contract_expire_sweep` | time_relative / schedule | 合同 | v0.3 |
| `srm_disposition_approval` / `srm_disposition_apply` | record_change | 处置单 | v0.3 |
Expand Down Expand Up @@ -408,7 +419,7 @@ flow 属于 ERP 集成后的门户镜像,现阶段不建。
| `srm_certificate_verify` 核验证书 | 资质证书 | SQE | v0.1 |
| `srm_primary_contact_set` 设为主联系人 | 供应商联系人 | `srm_supplier_admin` | v0.1 |
| `srm_bank_verify` 核验银行账户 | 银行账户 | 应付会计 | v0.2 |
| `srm_change_submit` 提交变更申请 | 供应商档案(v0.6 起门户:公司资料) | 采购员;v0.6 起门户管理员 | v0.2 |
| `srm_change_submit` 提交变更申请 | 门户:公司资料(v0.6 前内部在供应商档案下直接新建变更单) | 门户管理员 | v0.6 |
| `srm_audit_finding_to_scar` 转整改单 | 供应商审核 | SQE | v0.4 |
| `srm_score_submit` 提交评分 | 考评单 | 评分人 | v0.5 |
| `srm_appeal_submit` 申诉 | 门户:绩效 | 门户管理员 | v0.6 |
Expand Down
4 changes: 2 additions & 2 deletions docs/design/04-security-and-portal.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ SRM 同时服务内部员工和互相竞争的供应商,权限设计的首要
| `srm_internal_base` | 内部员工的基础:读品类、物料、工厂、供应商主数据(不含银行账号)、价格库;**不是** `isDefault` |
| `srm_sourcing` | 寻源单、寻源明细的增改(状态只经 screen flow 推进);邀请、技术评分、定标只经 screen flow;读报价(受封标 RLS 约束);新建合同 |
| `srm_supplier_admin` | 供应商档案、联系人、证书、准入申请、审核、供货品类资格、处置单、合同的增改;开通门户 |
| `srm_buyer` | 供应商档案、合同、交付记录读;物料只改 `category` 关联(其余字段 FLS 只读,不新建、不删除);代供应商发起变更单(v0.6 前);ERP 集成后加订单、送货单的内部字段 |
| `srm_buyer` | 供应商档案、合同、交付记录读;物料只改 `category` 关联(其余字段 FLS 只读,不新建、不删除);代供应商发起变更单(v0.6 前;银行账户变更要填完整账号,由持完整账号能力的品类经理或采购主管发起);ERP 集成后加订单、送货单的内部字段 |
| `srm_quality` | 审核、交付记录(录入)、整改单的增改;证书只读,核验经 screen flow |
| `srm_iqc` | 交付记录的录入(没有质量系统的客户) |
| `srm_finance` | 银行账号可读,核验经 screen flow;银行账户变更的第 2 级审批;整改单索赔结论标记 |
Expand Down Expand Up @@ -85,7 +85,7 @@ R 读 · C 建 · E 改 · D 删 · F 仅经 flow / screen flow 写入 · —
| 银行账户 | — | — | R | — | — | R + F(核验) | R(本公司);门户管理员 C |
| 资质证书 | R | R | RCE | R | R + F(核验) | R | RCE(本公司;状态与核验字段只读) |
| 准入申请 | — | — | RCE | — | RE | — | R(本公司) |
| 变更单 | — | — | R | R | — | R | R(本公司)+ F(提交) |
| 变更单 | — | — | RCE(本人发起的) | RCE(本人发起的;不含银行账户变更) | — | R | R(本公司)+ F(提交) |
| 寻源单 / 明细 | R | RCE(状态只经 F) | R | R | R | — | — |
| 寻源邀请 | R | RF | R | — | — | — | RE(本公司:接受 / 拒绝) |
| 报价单 / 明细 | — | R(开标后)+ F(评分、定标) | — | — | — | — | RE(本公司,截止前且未开标) |
Expand Down
7 changes: 4 additions & 3 deletions docs/design/07-delivery-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
| 版本 | 范围 | 新增对象(累计) | 本版闭环 | 前置条件 |
|---|---|---|---|---|
| v0.1 内部工作台 | 供应商主数据、两级准入审批、证书到期提醒 | 7:品类、工厂、供应商、联系人、证书、供货品类资格、准入申请 | 供应商从登记到合格;证书到期前有提醒 | 已交付(PR #5) |
| v0.2 主数据补齐 | 银行账户、信息变更申请、法人(业务单元)、物料与存量供应商导入 | +3 = 10:物料、银行账户、信息变更单 | 存量供应商导入后能复核;关键信息变更走审批 | — |
| v0.2 主数据补齐 | 银行账户、信息变更申请、法人(业务单元)、物料与存量供应商导入 | +3 = 10:物料、银行账户、信息变更单 | 存量供应商导入后能复核;关键信息变更走审批 | 已交付(PR #13–#18) |
| v0.3 合同与处置 | 合同与合同行、处置单(暂停 / 冻结 / 解除)、供应商自助重新申请 | +3 = 13:合同、合同行、处置单 | 合同到期前提醒;冻结后不能被邀请 | — |
| v0.4 质量 | 交付记录导入、质量问题与整改单、供应商审核与年度审核计划 | +3 = 16:交付记录、质量问题、供应商审核 | 不合格交付能开整改单并闭环;OTD、合格率、PPM 出数 | 客户能按月导出交付数据 |
| v0.5 绩效与风险 | 指标库、按周期考评、风险事件与扫描、黑名单 | +4 = 20:绩效指标、考评单、考评明细、风险事件 | 第一次考评自动生成并发布;D 级进入处置 | 门槛 1:内部 MVP 验收(§2.1) |
Expand Down Expand Up @@ -232,16 +232,17 @@ test/ # 仓库根目录
| PF2 | objectstack#25443 运行时创建岗位 | 门户开通 | 管理员手工建岗位 |
| PF3 | objectstack#25444 通知组织外联系人 | 供应商邮件通知 | 门户内通知 + 人工邮件 |
| PF4 | objectstack#25445 公开表单附件 | 供应商自助注册 | 内部登记 + 邀请注册 |
| PF5 | objectstack#25446 禁止自审开关 | 职责分离 | `expression` 改派 |
| PF5 | objectstack#25446 禁止自审开关 | 职责分离 | `expression` 改派;信息变更单每级通过后读审批记录比对,撞人时重开同级审批(03 §5) |
| PF6 | objectstack#25233 门户用户可列出全组织用户 | 门户隔离 | v0.6 阻塞;见 D8 |
| PF7 | objectstack#25447 ADR-0138 D5(多组织环境下公开表单绑定到指定组织) | 多法人客户的自助注册 | 邀请注册;多法人按 ADR-0006 单组织时不受影响 |
| PF8 | objectstack#25475 导入时「只在新建时写入」的列 | 存量导入不回退状态 | `status` 默认值按 `legacy_imported` 计算、`legacy_imported` 用 `readonlyWhen` 锁定(02 §4.1) |
| PF9 | objectstack#25476 导入按多组匹配字段依次匹配 | 境内 / 境外供应商同表导入 | 同一张表导两遍,各自跳过匹配字段为空的行 |
| PF10 | objectstack#25477 条件唯一(每家至多一位主联系人)在批量写入中生效 | 联系人导入 | 汇总字段 + 校验规则守卫单条写入;「主联系人重复」视图兜底同批写入 |
| PF11 | objectstack#25491 导入映射的 `transform`(转大写 / 小写)被忽略 | 信用代码、邮箱归一 | 导入前清洗([导入说明 §6.2](../implementation/legacy-supplier-import.md#62-清洗清单)) |
| PF12 | objectstack#25493 导入接受 `YYYY.MM.DD` / `YYYYMMDD`、选项别名与大小写、每行报全部错误 | 存量台账导入 | 导入前清洗 |
| PF13 | objectstack#24817 多级审批的后续节点以原发起人为提交人(主干已修,18.0.0 未带上) | 信息变更单第 2 级退回修改 | 第 2 级只能通过或驳回(03 §5) |

---

*本设计的下一步:v0.2 主数据补齐 → … → v0.5 门槛 1 验收 → v0.6 门户 → v0.7 寻源与门槛 2。
*本设计的下一步:v0.3 合同与处置 → … → v0.5 门槛 1 验收 → v0.6 门户 → v0.7 寻源与门槛 2。
每个版本出口时更新 §1 的路线表。*
Loading
Loading