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
1 change: 1 addition & 0 deletions docs/design/02-domain-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ upsert 写入,结构不变。
|---|---|---|
| `application_no` | autonumber | `APP{YYYY}{00000}`,按年重置 |
| `source` | select(只读) | `internal` 内部登记(默认)/ `invited` 邀请(v0.6,由「提交准入申请」写入)/ `self_registered` 自助注册(待平台,随公开表单加入) |
| `contact` | lookup → `srm_supplier_contact`(只读) | 申请联系人(v0.6 U6):门户提交时由「提交准入申请」写入提交人在名册上的联系人,受理、退回补充、通过、未通过的通知发给它在名册上的门户账号;内部登记的申请为空 |
| `company_name` | text | 必填 |
| `country` | select | 必填,默认 `cn`,选项同供应商的 `srm_country` |
| `credit_code` / `registration_no` | text | 规则同供应商:中国供应商填统一社会信用代码,境外供应商填当地注册号或税号 |
Expand Down
44 changes: 29 additions & 15 deletions docs/design/03-processes-and-automation.md

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions docs/design/04-security-and-portal.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ flowchart LR
- 经子 flow `srm_portal_roster_write`(`runAs: 'system'`,autolaunched)在联系人上写 `portal_user`,邀请置为「已开通」。
`portal_user` 字段级只读,`runAs: 'user'` 的写入会被数据层剔除(07 §6.3 PF19),所以名册由系统身份写;平台拒绝任何调用者
直接启动系统身份的 autolaunched flow,子 flow 只能经开通 flow 进入,写入前再查一遍一人一号。写入后下一个请求起该用户
只能看到本公司数据;
只能看到本公司数据;邀请置为「已开通」后 `srm_portal_opened_notice` 给受邀联系人发「门户已开通」(05 §5);
3. 准入邀请:供应商补齐资料、证书和银行账户后,在门户的公司资料上点「提交准入申请」(`srm_application_submit`,系统身份):
供应商取自调用者自己的名册行(不取页面传入的记录),品类取自门户邀请,`source = invited`,申请回填到邀请(03 §3);
4. 同一供应商以后再开通账号,同样走第 0–2 步。
Expand All @@ -243,9 +243,9 @@ flowchart LR
| 场景 | 动作 |
|---|---|
| 联系人离职 / 停用 | 联系人 `active = false`(名册过滤条件),下一个请求起看不到数据;`srm_portal_contact_revoke` 同时清掉 `portal_user`、撤销该联系人的门户邀请并通知组织管理员——日后把联系人改回在职也不会静默恢复门户访问,重新开通走门户邀请。组织管理员随后撤销门户岗位任命并移出组织 |
| 供应商冻结 | 账号与门户功能保持不变:整改单仍要回复,资料仍要维护;冻结只阻止新的询价邀请(BR-03),新订单由 ERP 侧冻结标志拦截 |
| 供应商淘汰 / 黑名单 | `srm_disposition_apply` 执行时清掉该供应商全部联系人上的 `portal_user`、撤销门户邀请,门户访问即刻失效,不靠人工停用联系人;有门户账号时通知组织管理员,岗位任命与组织成员身份由组织管理员随后移除(处置 flow 写不了任命,07 §6 V2)。重新准入时重新邀请、开通 |
| 准入未通过 | 申请驳回、供应商退回 `potential`(重新准入的旧档回 `eliminated`)时 `srm_admission_rejection` 清掉该供应商全部联系人上的 `portal_user`、撤销门户邀请,有门户账号时通知组织管理员(03 §3 第 8 步);已合格供应商增加品类的申请被驳回不动门户(只有潜在、淘汰的供应商能申请,`supplier_admissible`)。岗位任命与组织成员身份由组织管理员随后移除 |
| 供应商冻结 | 账号与门户功能保持不变,冻结与解冻都通知主账号联系人(05 §5):整改单仍要回复,资料仍要维护;冻结只阻止新的询价邀请(BR-03),新订单由 ERP 侧冻结标志拦截 |
| 供应商淘汰 / 黑名单 | `srm_disposition_apply` 执行时清掉该供应商全部联系人上的 `portal_user`、撤销门户邀请,门户访问即刻失效,不靠人工停用联系人;清名册之前先给主账号联系人发淘汰 / 列入黑名单通知(05 §5,清掉后名册上就没人可发了);有门户账号时通知组织管理员,岗位任命与组织成员身份由组织管理员随后移除(处置 flow 写不了任命,07 §6 V2)。重新准入时重新邀请、开通 |
| 准入未通过 | 申请驳回、供应商退回 `potential`(重新准入的旧档回 `eliminated`)时 `srm_admission_rejection` 先通知申请联系人「未通过」(05 §5),再清掉该供应商全部联系人上的 `portal_user`、撤销门户邀请,有门户账号时通知组织管理员(03 §3 第 8 步);已合格供应商增加品类的申请被驳回不动门户(只有潜在、淘汰的供应商能申请,`supplier_admissible`)。岗位任命与组织成员身份由组织管理员随后移除 |
| 季度复核 | 工作台「供应商 › 门户账号」视图(联系人的 `portal_accounts` 视图)按供应商列出登记了门户账号的联系人;停用、处置、驳回收回的已清掉 `portal_user`,不在此列。组织管理员对照组织成员页的外部成员,差异由采购主管确认(GL-10 6.6.3) |

### 3.4 RLS 示例
Expand Down
28 changes: 23 additions & 5 deletions docs/design/05-experience-and-analytics.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,25 +160,43 @@
## 5. 通知

平台的 `notify` 节点只能发给组织内用户(objectstack#25444):v0.6 前供应商侧的通知发给
内部经办人(品类经理 / SQE),由其转告;v0.6 起发给供应商的门户用户。
内部经办人(品类经理 / SQE),由其转告;v0.6 起门户用户是组织成员(组织角色 external),供应商侧的通知直接发给
他们(U6)。收件人规则:

- **只取本条记录所属供应商的名册**(ADR-0010 红线 2):在职、登记了门户账号(`portal_user`)的联系人,与成员键
同一条件;供应商取触发记录自己的 `supplier`。按职能挑人:标「质量」的发 `quality` 联系人,该供应商没有质量门户
联系人时发主账号(`admin`)联系人;标「门户管理员」的发名册上任命了 `srm_portal_admin` 的门户账号;准入申请发
申请联系人(门户提交时写入申请的 `contact`)。
- 没开通门户的供应商名册为空,不发;内部经办人的通知照旧,由其转告(v0.5 行为不变)。内部通知本来发给门户用户
本人的(门户提交的变更单的发起人、门户提交的申诉人),改由供应商侧通知代替,不重复发。
- 门户回收(准入未通过、淘汰、拉入黑名单)要清空名册,相应的「未通过」「已淘汰」「已列入禁入名单」在回收之前发。

| 事件 | 接收人 | 通道 | 版本 |
|---|---|---|---|
| 待你审核的准入申请 | 审批人 | 站内 + 邮件 | v0.1 |
| 证书即将到期 / 已过期 | SQE(v0.6 起加供应商联系人) | 邮件 + 站内 | v0.1 |
| 证书即将到期(前 30 / 15 / 7 天)/ 已过期 | SQE(品类都没有 SQE 时质量经理);v0.6 U6 起加供应商主账号与质量联系人 | 邮件 + 站内 | v0.6(U6,v0.1 只对齐状态未提醒) |
| 银行账户变更待复核、变更已生效 | 应付会计 / 采购员 | 站内 | v0.2 |
| 合同待审批、合同即将到期 | 审批人、合同所有者、品类经理 | 站内 + 邮件 | v0.3 |
| 新整改单、整改退回、整改重开、整改逾期 | 负责 SQE(新整改单没有 SQE 时发质量经理);逾期加质量经理(SQE 主管);v0.6 起加供应商 `quality` 联系人 | 邮件 + 站内 / 门户待办 | v0.4 |
| 新整改单、整改退回、整改重开、整改逾期 | 负责 SQE(新整改单没有 SQE 时发质量经理);逾期加质量经理(SQE 主管);v0.6 U6 起加供应商 `quality` 联系人(任何来源的新整改单都发) | 邮件 + 站内 | v0.4(供应商侧 v0.6 U6) |
| 供应商在门户提交临时措施;供应商接受索赔 / 对索赔有异议 | 负责 SQE(提交临时措施时没有 SQE 发质量经理;SQE 本人代填的不发);接受索赔加应付会计 | 站内 | v0.6 |
| 待你评分、评分截止前 3 天仍未评、退回重评、绩效结果发布;绩效申诉待处理、申诉处理结果 | 评分人;采购总监;申诉提交人(门户管理员或内部代录人;v0.6 U6 起加供应商 `admin` 联系人) | 站内 + 邮件 | v0.5 |
| 待你评分、评分截止前 3 天仍未评、退回重评、绩效结果发布;绩效申诉待处理、申诉处理结果 | 评分人;采购总监;内部代录的申诉人;v0.6 U6 起绩效发布和申诉结果加供应商 `admin` 联系人(门户提交的申诉人只收这一条) | 站内 + 邮件 | v0.5(供应商侧 v0.6 U6) |
| 门户开通待办(新门户邀请);门户访问已收回(联系人停用、处置、准入未通过) | 组织管理员 | 站内 | v0.6(U3) |
| 门户邀请、准入申请已受理 / 已驳回 / 已通过 | 受邀联系人、申请联系人(受邀申请发给开通了门户的联系人 `portal_user`,不发 `created_by`) | 邮件 | v0.6(U6) |
| 银行账户核验生效;信息变更单已生效 / 已驳回 / 退回修改 | 供应商门户管理员(内部发起的变更单另发发起人) | 邮件 + 站内 | v0.6(U6) |
| 供货资格冻结 / 解冻、淘汰、列入黑名单 | 供应商 `admin` 联系人(只写范围,不写处置原因) | 邮件 + 站内 | v0.6(U6) |
| 门户已开通(门户邀请)、准入申请已受理 / 退回补充 / 已通过 / 未通过 | 受邀联系人;申请联系人(申请上的 `contact`,不发 `created_by`;内部登记的申请没有,不发) | 邮件 + 站内 | v0.6(U6) |
| 新的询价邀请、报价截止前 24 小时仍未提交、中标 / 未中标、待你审批的定标 | 受邀供应商 `sales` 联系人;审批人 | 邮件 + 门户待办 | v0.7 |
| 新订单待确认、订单变更、交期风险、订单 24 / 48 小时未确认、付款完成 | 供应商 / 采购员 / 采购主管 | 邮件 / 站内 | ERP 集成后 |

通知模板统一放在应用包里,按中文 / 英文两套维护;邮件只给出摘要和门户链接,**不在
邮件正文里放报价金额、银行账号等敏感内容**。

供应商侧通知的模板在 `src/core/notifications/`(平台 `emailTemplates`,每个模板写 `zh-CN`、`en-US` 两份):notify 节点
按模板名引用,平台按收件人自己的语言(`sys_user.locale`,未设时取部署默认语言 zh-CN;选英文的落到 en-US)渲染,
同一份内容既发邮件也进站内信,站内信点开跳到单据。正文只写单号、供应商名称、事件和期限,不写问题描述、金额、账号、
分数、等级和处置原因,详情登录门户查看。邮件里的完整链接要拼部署地址,平台模板上下文里没有(07 §6.3 PF20),
模板数据里给出相对路径 `path`,客户可以在模板覆盖层里写上自己的门户域名;时间按服务器时区显示。
内部经办人的通知仍是 flow 里写的中文标题和正文。

## 6. 多语言与移动端

- **多语言**:对象、字段、选项、视图标签和通知模板按中文维护;英文翻译覆盖全部元数据,
Expand Down
5 changes: 3 additions & 2 deletions docs/design/07-delivery-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ test/ # 仓库根目录
| 仪表盘 | ✅ ⚠️ | 各类看板 | 求和 / 平均只能落在存储数值字段;多值字段不能做维度 | 2026-10-23 确认 |
| 平台导入(表格) | ✅ ⚠️ | 物料、存量供应商、交付记录 | 按外部编号匹配,可重复执行;只在新建时写入的列(如供应商初始状态)用字段默认值和 `readonlyWhen` 表达(PF8);一次导入只能一组匹配字段,境内 / 境外供应商分两遍(PF9);同一批里的跨行规则拦不住(PF10) | 2026-10-23 样例表格在 CI 跑两遍通过;模拟「脏」台账试导结论见[导入说明 §6](../implementation/legacy-supplier-import.md#6-试导结果与清洗清单)(PF11、PF12);2026-10-24 交付记录月度表格两遍通过,「脏」表格试导见[交付记录导入说明 §5](../implementation/delivery-import.md#5-试导结果与清洗清单) |
| 批量 API `upsert`、`http` 节点、webhook | ✅ ⚠️ | ERP 集成(预留) | 业务字段记同步状态 + 追赶式重推(06 §1.1) | ERP 立项时验证 |
| 通知(`notify`) | ⚠️ | 全部通知 | 只能发给组织内用户,外部联系人的邮件待平台(PF3,主干已修、18.1.0 未带上) | 2026-10-23 |
| 通知(`notify`) | ✅ ⚠️ | 全部通知 | 只能发给组织内用户;门户用户是组织成员(external),供应商侧通知经门户账号发站内信和邮件,用中英文邮件模板按收件人语言渲染(v0.6 U6);没开通门户的联系人仍由经办人转告(PF3);邮件里拼不出带部署地址的完整链接(PF20) | 2026-10-23;2026-11-02 U6 实测 |
| 字段历史、审批历史 | ✅ | 审计 | — | 2026-10-23 确认 |
| AI 治理(工具调用审计、回答级权限) | ✅(企业版) | AI 用例的审计 | 需企业版许可 | — |
| 应用包代码(钩子、插件、函数) | ⚠️ | 不依赖 | 平台支持 QuickJS 沙箱内的事务型钩子(ADR-0034/0102/0119),可被 `OS_DISABLE_AUTHORED_HOOKS` 关闭;本设计按 ADR-0001 不依赖 | 2026-10-23 更正(原文「托管云不执行代码」有误) |
Expand Down Expand Up @@ -258,7 +258,7 @@ test/ # 仓库根目录
|---|---|---|---|---|
| PF1 | objectstack#25570(原 #25442)定时 flow 的延迟与漏跑保证 | 提醒、考评、扫描 | 追赶式扫描 | 平台不纳入计划;追赶式扫描为长期做法 |
| PF2 | objectstack#25234(原 #25443)运行时创建岗位 → 平台改以声明式成员键回应 | 门户开通 | 管理员手工建岗位 | 18.1.0 已发布 `ObjectSchema.membershipKeys`;U2 实测通过,2026-11-02 改用(ADR-0010) |
| PF3 | objectstack#25571(原 #25444)通知组织外联系人 | 供应商邮件通知 | 门户内通知 + 人工邮件 | 主干已修,18.1.0 未带上 |
| PF3 | objectstack#25571(原 #25444)通知组织外联系人 | 没开通门户的供应商联系人的邮件通知 | 开通门户的联系人是组织成员,直接发(v0.6 U6);没开通的由内部经办人转告 | 主干已修,18.1.0 未带上;门户上线后影响只剩没开通门户的联系人 |
| PF4 | objectstack#25572(原 #25445)公开表单附件 | 不再依赖(2026-10-24 决定公开表单不收附件) | 附件在供应商注册账户、登录后上传 | 主干已修;决定不变 |
| PF5 | objectstack#25573(原 #25446)禁止自审开关 | 职责分离 | `expression` 改派;信息变更单每级通过后读审批记录比对,撞人时重开同级审批(03 §5) | 主干已修,18.1.0 未带上 |
| PF6 | objectstack#25233 门户用户可列出全组织用户 | 门户隔离 | v0.6 阻塞;见 D8 | 18.1.0 已修:组织角色 `external`(04 §3.3);V1 已通过(2026-11-02) |
Expand All @@ -275,6 +275,7 @@ test/ # 仓库根目录
| PF17 | objectstack#25251 自动化不得以系统身份写岗位任命、权限集授予、邀请和成员(裁定 B);邀请只经组织接口(V2、V3) | 门户开通、回收 | 组织管理员在成员页邀请、移出组织;任命与门户管理员授权由 `runAs: 'user'` 的「开通门户」flow 在组织管理员操作时写;处置 flow 不撤任命,改为通知组织管理员(04 §3.3) | 平台裁定,长期做法(2026-11-02 实测登记,不另提 issue) |
| PF18 | objectstack#29050 直接触发 flow(REST trigger)不按启动人的权限读 `recordId`,按钮入口(#16370)会答「不存在」 | 门户能启动的系统身份 screen flow(确认索赔、申诉、提交变更申请、准入补充后重新提交) | 每条 flow 进门自己查名册(`portal_user` = 本人、`active == true`,与成员键同条件),元数据测试守住(04 §3.7) | 2026-11-02 新提 |
| PF19 | 平台既定行为(objectstack#3407 起):数据层剔除对只读字段的写入,flow 节点只在步骤结果里给警告(`droppedFields`),写入照样算成功;`runAs: 'user'` 的 flow 因此写不进字段级只读的 `portal_user` | 门户开通(名册写入) | 「开通门户」以 `runAs: 'user'` 任命门户岗位,名册由系统身份的子 flow `srm_portal_roster_write` 写;平台拒绝直接启动系统身份的 autolaunched flow,子 flow 只经开通 flow 进入(04 §3.3);`test/portal-invitation.test.ts` 的探针盯着平台行为 | 平台既定行为,长期做法(2026-11-02 U3 实测,总监裁定不另提 issue) |
| PF20 | objectstack#29095 邮件模板的渲染上下文只有 `appName`,没有部署地址(`OS_BASE_URL`),flow 发出的邮件拼不出能点开的完整链接 | 供应商侧通知邮件(05 §5) | 邮件正文写「登录门户查看」和单号,站内信带单据链接;模板数据给出相对路径 `path`,客户可在模板覆盖层写上自己的门户域名 | 2026-11-02 U6 新提 |

其他代码和文档里指向平台的临时做法,2026-10-26 核对结果:

Expand Down
Loading
Loading