diff --git a/code/ERP动态配置多租户多公司多语言需求分析.md b/code/ERP动态配置多租户多公司多语言需求分析.md new file mode 100644 index 00000000..dc9d48d3 --- /dev/null +++ b/code/ERP动态配置多租户多公司多语言需求分析.md @@ -0,0 +1,1395 @@ +# ERP 动态配置、多租户、多公司与多语言需求分析 + +> 文档版本:V1.1 +> 编制日期:2026-09-30 +> 修订日期:2026-09-30 +> 适用范围:FMS/ERP 新系统规划、产品设计、数据库设计、接口设计和开发验收 +> 文档状态:需求基线草案(多语言与配置版本方案已修订) +> +> **V1.1 修订范围**:第 10 章(引入变更集、无状态/有状态配置、类型注册表)、第 11 章(三层存储模型、角色能力边界、双重循环回退链、可覆盖白名单)、以及 3.5 / 9.4 / 13.2 / 19.4 / 22 / 23 章的配套修订。其余章节保持 V1.0 原文。 + +## 1. 文档说明 + +本文档用于明确 ERP 系统在以下方面的总体需求和设计边界: + +- 一个租户一个数据库的物理隔离模式; +- 一个租户包含多个公司、子公司和组织; +- 动态字段、动态表单、动态流程和动态权限; +- 简体中文、繁体中文、英文等多语言能力; +- 公司级业务、集团级共享资料和集团汇总报表; +- 与现有 FMS SQL 驱动、模块配置和工作流设计保持一致。 + +本文档是系统级需求分析,不替代各业务模块的详细需求、接口协议、数据库字段设计和页面原型。后续销售、采购、库存、财务等模块应以本文档的边界和基础模型为前提继续细化。 + +## 2. 建设目标 + +### 2.1 总体目标 + +建设一个面向企业集团和内部业务团队的 ERP/FMS 系统,通过稳定的业务内核和可版本化的配置能力,支持不同租户在不复制代码的情况下适配不同的组织结构、字段、流程、权限和语言。 + +系统不是通用低代码平台,不要求所有页面、业务规则和复杂业务组件都由用户拖拽生成。系统采用以下原则: + +> 固定核心业务能力,配置变化部分,代码承载复杂业务逻辑,插件承载专业差异。 + +### 2.2 具体目标 + +1. 每个租户拥有独立数据库,方便备份、迁移、恢复和维护。 +2. 一个租户可以包含多个公司、子公司、分公司和组织机构。 +3. 公司之间可以共享基础资料,也可以保持独立的业务和财务数据。 +4. 支持字段、表单、查询、编号、流程、权限、打印模板等动态配置。 +5. 支持用户界面、配置项、基础资料和业务快照的多语言处理。 +6. 核心业务数据可通过 SQL 高效查询、统计、导出和扩展。 +7. 所有配置均支持草稿、校验、发布、生效、停用和回滚。 +8. 支持单租户备份、恢复、复制到测试环境和迁移到其他数据库。 +9. 支持公司级报表、集团汇总报表和后续合并分析能力。 + +## 3. 设计原则 + +### 3.1 租户隔离原则 + +一个租户对应一个业务数据库。租户业务表不再依赖 `tenant_id` 实现日常数据隔离,数据库边界本身就是租户隔离边界。 + +租户注册信息与数据库连接信息由租户注册表维护。首期可以使用配置文件,后续在租户数量、部署实例或平台运维需求增加时再切换为可选平台库;租户自己的用户、组织、配置和业务数据始终放在租户数据库。 + +### 3.2 公司隔离原则 + +租户数据库内部允许多个公司共存,但所有公司级业务和财务数据必须带有 `company_id`。公司是业务、库存、结算、账簿和报表的主要归属边界。 + +### 3.3 配置与代码边界 + +以下内容优先配置化: + +- 字段定义、字段标签和字段分组; +- 列表和表单布局; +- 查询条件、排序、显示格式和导出字段; +- 编号规则、字典和枚举; +- 审批节点、审批人和审批条件; +- 角色、字段权限和数据范围; +- 打印模板、通知模板和简单校验。 + +以下内容必须由代码保证: + +- 库存扣减、锁定、释放和成本计算; +- 财务过账、反过账和账簿一致性; +- 单据状态的关键流转约束; +- 并发控制、幂等处理和跨模块数据一致性; +- 复杂税务、结算、汇率和合并抵销逻辑。 + +### 3.4 数据模型原则 + +- 核心业务数据使用关系表,不使用全量 EAV 模型。 +- 高频查询和关键业务字段使用正式列。 +- 变化频繁的扩展字段可使用 JSON 或扩展值表。 +- 需要筛选、排序、统计的扩展字段应具备可索引方案。 +- 历史单据保存名称、规格、地址、税率、价格等业务快照。 +- 配置、元数据和业务数据分离存储。 + +### 3.5 现有 FMS 规范兼容 + +系统实现应延续现有 FMS 规范: + +- 使用 SQL 驱动的查询和数据处理方式; +- 系统配置、元数据和权限表使用 `s_` 前缀; +- 业务表沿用现有 `b_` 或业务域前缀; +- 字段采用小写 `snake_case`; +- JSON 仅承载布局、查询和用户偏好等适合 JSON 的结构; +- 多语言采用三层存储:系统默认层与租户覆盖层使用租户库关系表,硬编码兜底层使用代码资源文件,历史单据使用业务快照(详见 11.1); +- 权限过滤必须落实到后端查询或写入逻辑; +- 不使用触发器代替业务层规则。 + +## 4. 业务概念模型 + +```text +平台 +└── 租户 Tenant:一个客户集团或客户账号,对应一个数据库 + ├── 公司 Company:集团总部、子公司、分公司、法人实体 + │ ├── 组织 Organization:部门、岗位、成本中心 + │ ├── 仓库 Warehouse + │ └── 账簿 Ledger + ├── 集团共享基础资料 + └── 公司专属基础资料 +``` + +### 4.1 租户 + +租户是平台级概念,代表一个独立客户或集团客户。租户具备: + +- 独立数据库; +- 独立的配置和业务数据; +- 独立的备份和恢复周期; +- 独立的模块授权和版本状态; +- 独立的默认语言、时区和区域设置。 + +### 4.2 公司 + +公司是租户内部的法人实体、经营主体或业务主体。公司至少需要维护: + +- 公司编码和名称; +- 上级公司; +- 公司类型; +- 法人、税号和注册地址; +- 默认币种和默认语言; +- 时区和会计日历; +- 默认账簿和财务期间; +- 银行账户、开票主体和税务信息; +- 启停用状态。 + +### 4.3 组织 + +组织是公司的内部管理单元,包括部门、业务部、采购部、仓储部、财务部、成本中心等。组织支持树形层级,可用于审批、权限、负责人、费用归属和数据范围。 + +### 4.4 共享范围 + +基础资料应支持集团共享和公司专属两种范围: + +```text +GROUP 集团内公司均可使用 +COMPANY 仅指定公司可使用 +ORG 仅指定组织或组织范围可使用 +``` + +共享不代表可以跨公司直接交易。业务单据仍必须指定实际业务公司、结算公司和相关组织。 + +## 5. 系统总体架构 + +```text +前端应用层 +├── 平台管理 +├── 基础资料 +├── 销售管理 +├── 采购管理 +├── 库存管理 +├── 费用与结算 +├── 财务管理 +├── 报表中心 +└── 系统配置 + +通用能力层 +├── 业务对象与元数据 +├── 动态表单与列表 +├── 工作流与审批 +├── 权限与数据范围 +├── 多语言与区域化 +├── 编号与字典 +├── 附件与打印 +├── 审计日志 +└── 通知消息 + +租户运行层 +├── 租户识别 +├── 数据库路由 +├── 数据源连接池 +├── 配置版本管理 +├── 租户数据库迁移 +├── 备份恢复 +└── 租户健康检查 + +数据层 +├── 租户连接注册(文件/平台库) +├── 租户数据库 +├── 消息队列 +└── 分析库/数仓 +``` + +### 5.1 租户注册表与平台库(可选) + +系统必须能够根据租户标识找到对应数据库。租户注册信息不强制要求使用平台库,首期可以使用按租户维护的配置文件: + +```text +config/tenants/tenant-a.json +config/tenants/tenant-b.json +``` + +注册表至少维护: + +- 租户编码和状态; +- 数据库标识和部署模式; +- 当前数据库版本; +- 数据库健康状态; +- 域名或登录入口映射; +- 模块授权和启用功能; +- 迁移、备份和恢复任务状态。 + +当需要在线开通租户、多实例部署、统一运维或集中查看所有租户状态时,可将同一套注册信息迁移到平台库。平台库只负责控制平面,不保存租户业务明细。 + +### 5.2 租户数据库 + +每个租户数据库保存本租户的完整业务数据,包括: + +- 用户成员和组织架构; +- 公司、账簿、仓库和基础资料; +- 系统模块、字段、流程、权限和语言配置; +- 销售、采购、库存、费用和财务数据; +- 租户级审计日志和业务操作记录。 + +## 6. 功能需求总览 + +| 编号 | 功能域 | 主要内容 | 优先级 | +| ------ | ---------- | ---------------------------------------- | ------ | +| FR-001 | 平台与租户 | 租户开通、数据库登记、状态管理 | P0 | +| FR-002 | 公司与组织 | 多公司、子公司、组织树、仓库和账簿 | P0 | +| FR-003 | 用户与权限 | 用户、角色、公司范围、组织范围、字段权限 | P0 | +| FR-004 | 元数据配置 | 模块、字段、对象和关系配置 | P0 | +| FR-005 | 动态页面 | 列表、表单、详情、查询和导出配置 | P0 | +| FR-006 | 工作流 | 状态、节点、条件、审批人和动作 | P0 | +| FR-007 | 多语言 | 界面、配置、主数据和单据快照多语言 | P0 | +| FR-008 | 基础资料 | 客户、供应商、产品、分类、价格和税率 | P0 | +| FR-009 | 销售采购 | 订单、审批、收发货、结算和对账 | P1 | +| FR-010 | 库存 | 仓库、库存、批次、序列号、调拨和盘点 | P1 | +| FR-011 | 财务 | 账簿、期间、应收应付、凭证和报表 | P1 | +| FR-012 | 报表 | 公司报表、集团汇总、导出和分析 | P1 | +| FR-013 | 运维 | 迁移、备份、恢复、监控和审计 | P0 | +## 7. 平台与租户管理需求 + +### 7.1 租户开通 + +租户开通可以由部署工具、运维人员或平台管理员完成: + +1. 创建租户基本资料; +2. 创建或绑定租户数据库; +3. 执行数据库初始化脚本; +4. 写入基础语言、时区和默认参数; +5. 创建首个租户管理员; +6. 分配默认模块和权限; +7. 写入租户注册文件或平台库; +8. 记录初始化结果和数据库版本。 + +租户注册表应抽象为统一的 `TenantRegistry` 接口。首期使用文件实现,后续可以替换为平台库实现,不改变业务模块代码。 + +### 7.2 租户数据库模式 + +系统应支持以下数据库部署模式: + +- `shared_instance`:同一数据库实例中的独立数据库; +- `dedicated_instance`:独立数据库实例; +- `external_database`:外部托管或私有化数据库。 + +默认采用独立数据库,是否独立实例由租户规模、性能和部署要求决定。 + +### 7.3 租户状态 + +租户状态至少包括: + +```text +CREATING 初始化中 +ACTIVE 正常使用 +READ_ONLY 只读维护 +SUSPENDED 暂停访问 +MIGRATING 数据迁移中 +ARCHIVED 已归档 +``` + +不同状态下,登录、查询、保存、审批、导出和后台任务应有明确限制。 + +## 8. 公司、组织和账簿需求 + +### 8.1 公司管理 + +系统支持在一个租户数据库内维护多个公司,并支持公司树: + +```text +集团总部 +├── 上海子公司 +├── 苏州子公司 +└── 香港子公司 +``` + +公司管理功能包括: + +- 新增、编辑、停用公司; +- 设置上级公司和公司类型; +- 设置默认语言、时区和币种; +- 设置会计日历和财务期间; +- 维护税务、银行和开票资料; +- 配置公司级编号规则、审批规则和权限; +- 查看公司数据量、业务状态和启用模块。 + +### 8.2 组织管理 + +组织树使用父子关系维护,支持: + +- 部门、岗位、成本中心等组织类型; +- 组织移动和层级调整; +- 负责人和分管人员; +- 组织有效期; +- 用户多组织任职; +- 审批节点按组织、岗位或负责人取值。 + +### 8.3 仓库和账簿 + +仓库必须归属公司,可进一步归属组织。账簿必须归属公司,并明确: + +- 本位币; +- 会计年度; +- 会计期间; +- 科目体系; +- 是否允许过账; +- 结账状态。 + +## 9. 用户、角色和权限需求 + +### 9.1 权限层次 + +系统权限至少分为: + +```text +平台权限 +租户权限 +公司权限 +组织权限 +仓库权限 +模块权限 +按钮权限 +字段权限 +数据权限 +业务动作权限 +``` + +### 9.2 用户业务上下文 + +用户登录后形成统一的业务上下文: + +```text +tenant_id 当前租户标识 +company_id 当前公司 +organization_id 当前组织 +ledger_id 当前账簿 +language 当前语言 +timezone 当前时区 +currency 当前显示或业务币种 +user_id 当前用户 +``` + +用户可以切换的范围由权限决定。普通用户可能只能切换组织,集团财务可以切换公司和账簿。 + +### 9.3 数据权限 + +数据权限支持: + +- 仅本人创建的数据; +- 所属组织数据; +- 所属组织及下级组织数据; +- 指定公司数据; +- 指定仓库数据; +- 指定客户、供应商或业务负责人数据; +- 自定义条件数据。 + +数据权限必须在后端 SQL 或数据访问层执行,前端隐藏不能代替后端权限过滤。 + +### 9.4 超级管理员与租户用户 + +> V1.1 新增。本章是第 10 章配置版本与第 11 章多语言的能力边界前提。 + +系统区分两类角色,其能力差异是全局性的,不只作用于多语言: + +| 角色 | 持有方 | 是否交付客户 | 主要能力 | +| ---------- | -------------- | ------------------ | ------------------------------------------------------------ | +| 超级管理员 | 运维或开发团队 | **否**,不交付租户 | 新增/删除语言、配置语言默认值、修改任意配置与文案、对租户白名单做例外放行、平台级运维操作 | +| 租户用户 | 客户方 | 是 | 在授权范围内修改文案取值与配置,**不能新增语言、不能语言级配置、不能修改锁定文本** | + +租户用户对文案的修改结果**对整个租户生效**,不是每个登录账号各改各的。租户内所有用户看到同一份文案;个人语言偏好只决定"使用哪一门语言",不决定"某个词如何翻译"。 + +这条约束的实操价值在于:用户报障时会复述屏幕上的文案,若同一租户内不同人看到不同叫法,运维无法据此定位问题。 + +## 10. 动态配置需求 + +### 10.1 配置对象 + +系统至少支持以下配置对象: + +- 业务模块; +- 数据对象; +- 字段定义; +- 主子表关系; +- 列表布局; +- 表单布局; +- 查询方案; +- 编号规则; +- 字典和枚举; +- 工作流; +- 权限和数据范围; +- 打印模板; +- 通知模板; +- 公式和简单规则。 + +### 10.2 动态字段 + +支持以下字段类型: + +- 文本、多行文本; +- 整数、数值、金额; +- 日期、时间、日期时间; +- 单选、多选、下拉树; +- 用户、部门、公司、仓库、客户等关联字段; +- 附件、图片; +- 公式字段; +- 子表和明细字段。 + +字段配置包括: + +- 编码、名称和数据类型; +- 是否启用; +- 是否必填; +- 默认值; +- 可见、只读和禁用条件; +- 查询、排序和导出能力; +- 权限级别; +- 公司作用域; +- 多语言标签; +- 校验和格式化规则。 + +### 10.3 动态表单和列表 + +表单支持: + +- 分组、选项卡和折叠面板; +- 字段栅格和列宽; +- 条件显示、条件只读和条件必填; +- 主表与子表; +- 自定义组件; +- 用户个性化布局; +- 根据公司、角色或单据状态使用不同布局。 + +列表支持: + +- 动态列; +- 固定列和排序; +- 多条件查询; +- 条件组和逻辑组合; +- 汇总、分组和统计; +- 导出字段控制; +- 用户保存查询方案。 + +### 10.4 配置生命周期与元模型 + +配置发布必须经过: + +```text +草稿 → 校验 → 测试 → 发布 → 生效 → 停用/回滚 +``` + +发布前校验包括: + +- 字段和编码重复检查; +- 关联对象存在性检查; +- 流程节点可达性检查; +- 必填字段可填写检查; +- 公式字段引用检查; +- 权限是否造成无人审批检查; +- 删除或停用字段对历史数据的影响检查。 + +配置版本必须保留发布人、发布时间、变更说明和前一版本引用。 + +> V1.1 修订:上述生命周期是**完整链路**,适用于结构型与行为型配置。展示型、内容型(含翻译)按 10.7 的类型注册表跳过"测试"环节,直接发布。 + +**统一元模型。** 10.1 列举的全部配置对象共用一套版本机制,不为每类各造一套: + +```text +配置对象 config_object —— 一个可版本化的单元(字段定义、列表布局、工作流、打印模板……) + ├── 工作副本 —— 唯一一份,可反复编辑 + ├── 版本快照 —— 发布时整体冻结,发布后不可变 + └── 指针 —— 当前版本 + 上一版本 + +变更集 change_set —— 打包多个配置对象的工作单元,见 10.5 +``` + +参考表结构(沿用 `s_` 前缀与 `snake_case` 命名): + +```text +s_config_object (tenant_id, object_type, object_code) +s_config_version (object_id, version_no, status, content_json) +s_config_release (object_id, current_version_id, previous_version_id, released_by, released_at) +s_change_set (tenant_id, set_code, status, released_by, released_at) +s_change_set_item (change_set_id, object_id, before_version_id, after_version_id) +``` + +**整包快照,不做行级 diff。** 单个配置对象通常为几百行 JSON,整体冻结最简单、最不易出错,回滚即移动指针。版本比对通过两个版本的 JSON 并排展示实现,**不实现三方合并**。 + +**配置作用域:租户级默认 + 公司级稀疏覆盖。**(V1.1 补充) + +本节新增的公司级覆盖机制只作用于「表现与行为」类配置对象;结构性定义仍由租户统一,详见下方「配置对象的作用域划分」。三层结构与第 11 章多语言的「覆盖层 → 默认层 → 兜底层」一致,表述与之对齐: + +```text +多语言:租户覆盖层 → 系统默认层 → 硬编码兜底层 +配置: 公司级覆盖 → 租户级默认 → 系统内置 +``` + +原 `s_config_object` / `s_config_version` / `s_config_release` 定义保持不变;公司级覆盖通过新增两张表实现,不改变对象的租户级定义: + +```text +s_config_override (object_id, company_id, current_version_id, previous_version_id) +s_config_override_version (object_id, company_id, version_no, content_json, status, released_by, released_at) +``` + +解析规则: + +```text +最终生效配置 = + 公司级覆盖(company_id) 存在 → 取公司级已发布版本 + 否则 → 取租户级已发布版本 +``` + +**覆盖粒度为「对象级整包覆盖」,不做字段级合并。** 理由:字段级合并会产生"字段 A 来自公司版、字段 B 来自租户版"的组合,租户升级后可能出现公司版与租户版字段结构不一致的诡异状态,且无法预测。整包覆盖语义清晰、可预期。 + +**稀疏覆盖,不做全量复制。** 公司级覆盖必须是稀疏的: + +- 公司创建时,覆盖表为空,零初始化; +- 租户级默认值变更后,自动传播到所有未做覆盖的公司; +- 公司删除覆盖,即回退到租户级默认。 + +**为什么不做「创建公司时复制全量租户配置」。** 该做法下,租户后续优化无法传播到已有公司,N 个公司产生 N 份副本,改一次通用规则要改 N 次,与多语言全量复制的缺陷完全相同。 + +**配套要求:租户版与公司版差异比对。** 系统提供「查看租户版与本公司版差异」的比对功能(两个 JSON 并排展示即可),使公司管理员能判断是否需要同步租户级更新。 + +**配置对象的作用域划分。** + +| 配置对象 | 租户级 | 公司级覆盖 | 说明 | +| --- | --- | --- | --- | +| 业务模块、数据对象、主子表关系 | 定义 | ❌ | 结构型,租户统一 | +| 字段定义(编码、名称、数据类型) | 定义 | ❌ | 结构性定义租户统一 | +| 字段使用属性(必填、显隐、只读、默认值、标签) | 默认 | ✅ | 10.2 已有「公司作用域」 | +| 列表布局、表单布局、查询方案 | 默认 | ✅ | 10.3 已支持按公司 | +| 编号规则 | 默认 | ✅ | 8.1 明确要求 | +| 工作流、审批规则 | 默认 | ✅ | 8.1 明确要求 | +| 权限和数据范围 | 默认 | ✅ | 9.1 已有公司权限层 | +| 打印模板、通知模板 | 默认 | ✅ | 抬头、税号、logo 常为公司专属 | +| 字典和枚举 | 默认 | ✅ 有限 | 允许公司增改项文案,不允许改编码 | +| 公式和简单规则 | 默认 | ❌ | 逻辑一致性优先 | + +> 原则:**结构性定义租户统一,表现与行为规则允许公司覆盖。** +> +> 作用域止于公司:组织级、仓库级不设配置作用域(仅权限可下沉到组织/仓库)。配置继续下沉会导致配置量爆炸且无法维护。 + +**作用域边界规则。** + +1. **删除公司级覆盖 = 回退到租户级默认**,不等同于停用或删除该配置。 +2. **孤儿覆盖校验**:租户级对象被停用或删除后,其下的公司级覆盖应被标记为孤儿覆盖,纳入发布前校验清单与运维巡检,不得静默失效。 +3. **公司停用或归档时,其覆盖随之失效**,不进入解析链。 +4. **权限、编号规则、打印模板复用同一套覆盖机制**,不得各造一套。 + +**共享内核(建议)。**「租户级默认 + 公司级稀疏覆盖 + 优先级解析」是本文档中反复出现的结构,至少四处复用同一模式——多语言(11.4 公司级 overlay)、配置(本次新增)、权限(9.1 公司权限层)、编号规则(8.1 公司级编号规则)。建议抽象为共享内核统一实现,避免四处各造一套导致行为不一致。 + +### 10.5 变更集 + +> V1.1 新增。V1.1 补充:支持租户级与公司级混合作用域。 + +ERP 中最常见的操作是"加字段 → 改表单 → 改列表列 → 改打印模板"的组合修改。若只能单对象独立发布,会产生"字段已加但表单未放置"的中间态不一致。因此配置以**变更集**为发布单元: + +- 变更集包含 N 个配置对象的草稿变更; +- 提交时执行**跨对象一致性校验**; +- **原子发布**:全部成功或全部不生效,不得出现半发布状态(呼应 19.4); +- **回滚以变更集为最小单位**。 + +**跨对象校验**是相比单对象发布的最大增量价值:可校验"表单引用的字段是否存在""列表列引用的字段是否已停用""打印模板引用的字段是否仍可见"这类约束,而这些在分开发布时无法校验。 + +**变更集项的作用域。**(V1.1 补充)`s_change_set_item` 增加 `scope` 与 `company_id`: + +```text +s_change_set_item (change_set_id, object_id, before_version_id, after_version_id, scope, company_id) +``` + +- `scope` 取 `TENANT` 或 `COMPANY`; +- `scope = COMPANY` 时 `company_id` 必填,指向公司级覆盖(见 10.4); +- `scope = TENANT` 时 `company_id` 为空。 + +**允许同一变更集混合租户级与公司级项。** 典型场景:「加字段(租户级)+ 改 A 公司表单(公司级)」必须能一起发,否则又会退回"字段已加但公司表单未更新"的中间态。 + +**原子发布与原子回滚仍以变更集为单位,跨作用域一并回退**,不因作用域不同而拆分。 + +**跨对象校验需具备作用域意识**:例如校验"表单引用的字段在该公司是否可见/启用",而非仅校验租户级。校验清单增加「孤儿覆盖检查」(见 10.4 作用域边界规则)。 + +**占用锁**:配置对象进入某个变更集后,其他变更集不得再将其加入,系统应提示"该对象已在 XXX 变更集中"。占用锁的键扩展为 `(object, scope, company_id)` 组合,避免同一公司级对象被两个变更集同时占用。采用占用锁而非三方合并。 + +### 10.6 无状态配置与有状态配置 + +> V1.1 新增。本节决定配置变更对在途业务单据的影响方式。 + +配置按是否持有运行时状态分为两类: + +| 类型 | 典型例子 | 生效规则 | +| -------------- | ---------------------------------------------------- | ------------------------------------------------------------ | +| **无状态配置** | 必填、显隐、只读、校验规则、显示格式、打印模板、翻译、编号规则的格式定义(前缀、日期格式、位数、补位规则) | **实时求值,永远以最新为准**。发布后立刻对所有单据生效 | +| **有状态配置** | 工作流、审批节点、审批规则 | **实例创建时绑定 `config_version`**,按绑定版本执行完毕,不受后续发布影响 | + +**为什么有状态配置必须绑定版本。** 审批流原为 A→B→C 三级,改为 A→C 两级后回滚:若按"最新为准",已走完 C 的单据在回滚后缺失 B 级审批,已发生的业务动作无法处理;仍卡在 C 的单据则无法确定 B 级算通过还是未通过。审批流改版时,在途单据必然被此类问题撞上。 + +**编号规则不属于有状态配置。** 编号规则需拆为两部分理解: + +- 编号格式的规则部分(前缀、日期格式、位数、补位方式等)是**无状态配置**,修改后实时求值、立即生效,与必填、显隐等同类,无需版本绑定; +- **计数器本身不是配置,而是运行时数据**。它需要解决的是并发安全问题(数据库序列、独立计数表或乐观锁),与配置版本机制无关,不进入 `s_config_version` 版本体系。 + +因此,需要版本绑定的配置仅包括工作流与审批流实例。不应为编号计数器生成版本快照。 + +**影响面**:版本绑定仅作用于"改版那一刻正在审批中的少数单据",新单据照常走最新版本。 + +**配套硬约束:** + +1. **字段只能停用,不能物理删除**。10.4 校验清单中"删除或停用字段对历史数据的影响检查"升级为硬约束。 +2. **保存与提交的校验强度不同**。新规则将某字段设为必填后,审批中的历史单据该字段可能为空,若保存时强制校验,该单据将既无法编辑也无法提交,形成死单。规则:**保存时降级为警告,提交/审核时强制校验**,使老单据可补填后继续流转。 +3. **运行时与发布分离**。运行时永远读取已发布版本,草稿修改不影响线上。单据与流程实例记录其绑定的 `config_version`;打印模板同理,历史单据打印使用开单时的模板版本。 + +### 10.7 类型注册表与校验器 + +> V1.1 新增。 + +使用**声明式类型注册表**替代散落的 if-else 判断。新增一类配置对象时,只需增加一条注册记录与一个校验器,不改引擎。 + +| 类型 | 例子 | 变更频率 / 风险 | 是否审批 | 生命周期 | +| ------ | ---------------------------- | --------------- | ------------ | ---------------------- | +| 展示型 | 列表布局、查询方案、打印模板 | 高 / 低 | 否 | 跳过测试环节,直接发布 | +| 内容型 | 翻译、字典、枚举文案 | 高 / 低 | 否(轻量档) | 轻量发布,见 11.10 | +| 结构型 | 字段定义、对象关系 | 低 / 高 | 是 | 校验 + 审批 | +| 行为型 | 工作流、审批规则、编号规则 | 中 / 高 | 是 | 校验 + 审批 | + +### 10.8 回滚语义 + +> V1.1 新增。 + +回滚 = 指针拨回上一版本,**物理上不删除任何数据**。 + +- 无状态配置:回滚后立即按旧版本求值。 +- 有状态配置:新实例按旧版本执行,在途实例按绑定版本执行完毕。 +- 存在在途实例时给出**强提示,但不硬性禁止**。管理员在回滚时具备判断力,强行拦截导致卡单才是更严重的事故。 + +### 10.9 设计边界 + +> V1.1 新增。以下内容明确不在本期范围内,避免后续被误加: + +- **不新建通用审批流引擎承载"配置审批"**,复用第 15 章已有的工作流能力。 +- **不自动生成配置变更的数据迁移脚本或 DDL**。结构型变更走"影响评估 + 只停用不删除"。 +- **不做行级 diff,不做冲突三方合并**。 + +## 11. 多语言与区域化需求 + +### 11.1 多语言存储策略 + +> V1.1 整节重写。原"混合存储(代码资源 + 租户库)"改为三层模型,并明确角色能力边界。 + +多语言文本分三层存储。**注意:系统默认层(第 2 层)走数据库而非代码资源文件**,原因是"超级管理员新增语言、配置语言默认值"是运行时的、不发版的动作,代码资源文件无法承载。 + +| 层级 | 内容 | 存储位置 | 可修改方 | 生效方式 | +| -------------------------- | ------------------------------ | --------------------------------------------------- | ------------------------------------ | ----------------------- | +| 第 3 层 租户覆盖层 overlay | 该租户**改过的 key**,只存差异 | 租户数据库 `s_i18n_overlay` | 租户(白名单内)、超级管理员(全部) | 保存即生效 | +| 第 2 层 系统默认层 | 系统默认翻译值,全量 | 租户数据库 `s_i18n_resource` / `s_i18n_translation` | **仅超级管理员** | 保存即生效,不发版 | +| 第 1 层 硬编码兜底层 | 系统能跑起来的最小文案集 | 代码资源文件 | 开发(随版本发布) | 仅在第 2 层不可用时生效 | + +关键约束: + +- **第 1 层不是全量翻译**,只放错误提示、语言名称本身等最小集,其唯一职责是"数据库不可用时界面仍能渲染、不白屏"。 +- **租户 overlay 只存差异**,大部分租户该表是空的——空表即零初始化、租户秒级可用。 +- **动态字段标签、流程节点名、字典文案等天生没有代码默认值的内容直接归入第 2 层**,不属于 overlay 概念。overlay 仅指"第 2 层已有默认值、租户要覆盖"的部分。 +- 平台库不负责保存租户业务翻译。 + +按内容性质归类: + +| 内容类型 | 归属层级 | 示例 | +| -------------- | ---------------------------------- | ------------------------------------------ | +| 系统默认文案 | 第 2 层 | 菜单、按钮、系统提示、固定错误码 | +| 租户改写文案 | 第 3 层 | 菜单显示名、按钮文案、业务校验提示 | +| 租户动态配置 | 第 2 层 | 动态字段标题、表单分组、流程名称、字典翻译 | +| 租户业务主数据 | 主表 + 翻译表 | 产品、分类、客户类型、供应商类型 | +| 可编辑模板 | 第 2 层 / 租户数据库 | 打印模板、邮件模板、通知模板 | +| 用户语言偏好 | 租户数据库用户配置,可辅以本地缓存 | 当前语言、日期格式、数字格式 | +| 历史单据内容 | 业务单据快照字段 | 产品名称、客户名称、税率、单位名称 | + +### 11.2 角色能力边界 + +> V1.1 新增,承接 9.4。 + +本文档中的"租户"实质上是**受限的普通用户**,不是可以自由定制的独立租户。多语言能力边界如下: + +| 能力 | 超级管理员 | 租户用户 | +| ------------------------- | -------------------- | ---------------------- | +| 新增语言 | ✅ 运行时配置,不发版 | ❌ | +| 删除/停用语言 | ✅ | ❌ | +| 配置语言默认值(第 2 层) | ✅ | ❌ | +| 修改具体文案取值 | ✅ 全部 | ✅ 白名单内 | +| 修改结果的生效范围 | 全局 | **整个租户**,非账号级 | + +租户用户**不能新增语言、不能删除语言、不能配置语言包的默认值**,只能修改已有语言中某些文案的取值。修改结果对整个租户生效,租户内所有用户看到同一份文案;个人语言偏好只决定"使用哪一门语言",不决定"某个词如何翻译"。 + +### 11.3 支持范围 + +系统设计上支持: + +- 简体中文 `zh-CN`; +- 繁体中文 `zh-TW`; +- 英文 `en-US`; +- 日文 `ja-JP`; +- 后续扩展其他语言。 + +首期实际启用语言由项目范围确定,但数据模型和接口不得写死单一语言。新增语言由超级管理员在运行时配置,不需要发版。 + +### 11.4 读取与回退规则 + +> V1.1 修订:删除原 11.2 与 11.5 两处互相冲突的回退链,合并为唯一一条,并改为双重循环模型。 + +原 V1.0 的 11.2 与 11.5 对回退链描述不一致(一处写"系统代码资源"、一处写"系统基础语言"),且把"语言"和"来源"两个正交维度压成了一维。统一模型如下: + +```text +语言候选 L = [用户语言, 当前公司默认语言, 租户默认语言, 系统基础语言] (去重) +来源优先 S = [租户 overlay, 公司级 overlay, 系统默认层, 硬编码兜底层, 原始 key 末段] + +遍历顺序:先遍历语言,后遍历来源 + for l in L: + for s in S: + 命中即返回 +``` + +**为什么要先语言后来源。** 若先遍历来源,会出现同一页面上半部分日文、下半部分中文(overlay 只有中文则出中文、默认层有日文则出日文)。ERP 中语言混屏会被当作缺陷上报,比缺翻译更严重。先遍历语言可保证整屏语言一致,全部未命中才整体降级。 + +**语言候选受"系统已启用语言"约束**:候选列表 = 系统已启用语言 ∩ 用户语言偏好。系统未启用某语言时,即使用户浏览器语言匹配也不得采用,应回退到系统基础语言。 + +代码资源与数据库资源应使用统一的语言编码和资源键。系统文案使用资源键,例如 `common.save`;动态配置和业务主数据使用对象编码、字段编码或资源 ID 关联翻译表。 + +缺少翻译时不得导致页面报错,应显示回退语言,并允许超级管理员查看缺失翻译清单。 + +### 11.5 多语言内容类型与可覆盖白名单 + +> V1.1 修订:原 11.1 与 11.4 冲突(11.1 将菜单、按钮归入代码资源,隐含租户不可改;11.4 又写两者"共同覆盖")。此处统一拆分。 + +数据库与代码资源共同覆盖以下内容: + +1. 菜单、按钮、提示和系统消息; +2. 动态字段、表单分组和流程节点; +3. 字典、分类和枚举项; +4. 产品、物料、客户分类和供应商分类; +5. 打印模板标题和固定文本; +6. 通知、邮件和消息模板; +7. 单据打印时使用的历史名称快照。 + +其中**允许租户覆盖**与**锁死不给改**的划分如下: + +| 允许租户覆盖 | 不允许租户覆盖(锁死) | +| ---------------------- | ------------------------ | +| 菜单显示名 | 技术错误码、异常堆栈文案 | +| 按钮文案 | 日志关键字、审计术语 | +| 表单/字段标签、分组名 | 权限拒绝的标准文案 | +| 业务校验提示、业务消息 | 升级提示、系统状态提示 | +| 打印模板抬头 | | + +**锁死理由**:用户报障时会复述屏幕上的错误文案,若该文案可被租户改写,运维无法用它检索日志与工单,问题定位链路会断。 + +**白名单授予方式**:按**模块 + 类别**批量授予,不逐 key 配置;超级管理员可对单个 key 做例外放行。 + +### 11.6 业务主数据翻译 + +产品、分类等主数据采用主表加翻译表的方式: + +```text +product +product_translation +dictionary_item +dictionary_item_translation +``` + +不建议把所有翻译内容拼接在单个 JSON 字段中,以便后续查询、导入、导出、校验和维护。 + +### 11.7 单据快照 + +单据创建或审核时,需要根据业务要求保存以下快照: + +- 产品编码和名称; +- 规格型号; +- 客户或供应商名称; +- 公司名称、地址和税号; +- 银行信息; +- 币种和汇率; +- 税率和税额; +- 付款条件; +- 单位名称。 + +历史单据展示和打印优先使用快照,不能因主数据后续改名而改变历史事实。 + +> V1.1 补充:快照需区分两类,名称类快照的语言维度待业务方确认(见第 22 章待确认项 14)。 + +- **事实性快照**:金额、税率、数量、编码、税号、地址等与语言无关的信息,必须原样存储,不因主数据后续变更而改变。 +- **名称类快照**:产品名称、客户名称、单位名称等。原 11.7 只要求存快照,未说明存哪个语言。实际场景:去年以中文开单,今年客户要求补打英文版发票,快照中只有中文名。 + +名称类快照提供三个选项供业务方决策: + +| 选项 | 做法 | 评价 | +| ---- | ------------------------ | -------------------------------------------- | +| a | 仅存开单时的那一种语言 | 补打其他语言无法输出,财务与合规场景常不满足 | +| b | 带 `lang` 维度存多份 | 最稳妥,存储量翻倍 | +| c | 仅存主数据 ID + 当前翻译 | 违反"历史事实不可变"原则 | + +**建议折中**:按开单语言存一份,同时保留主数据 ID,允许按当前翻译补打,但单据上须标注"依据当前资料翻译"。 + +### 11.8 区域化 + +系统分别配置语言、时区、日期格式、数字格式和币种,不将这些概念混为一谈。配置优先级为: + +```text +用户设置 → 公司设置 → 租户设置 → 系统默认 +``` + +### 11.9 缓存与资源治理 + +> V1.1 新增。以下条目为原 V1.0 缺失项,缺失会导致上线后返工。 + +1. **缓存**:多语言是每次渲染都读取的高频数据,必须缓存。按 `lang` 整包加载进内存(通常几十 KB),超级管理员修改默认值或租户修改 overlay 时发送缓存失效事件。 +2. **单一数据源**:避免前端与后端各维护一份资源文件导致不同步。以 key 为中心单一维护,构建期分发,或由后端统一提供 i18n 接口。 +3. **key 命名规范**:使用语义化 key,如 `sales.order.status.pending`。**禁止使用英文原文作为 key**——以原文为 key 时,修改一次英文就要改动所有语言包。 +4. **Excel 导入导出**:超级管理员批量配置翻译、批量查找替换的刚需。缺失此能力,翻译运营最终会退化为直接改数据库。 +5. **zh-TW 独立维护**:不得依赖简体自动转繁体。打印/列印、软件/軟體、文件/檔案 等用词差异必须独立维护。 +6. **废弃 key 治理**:废弃 key 标记为 `deprecated` 后静默保留,版本升级时不得硬删除,由清理工具另行处理。 +7. **占位符与复数**:至少支持 ICU MessageFormat(如 `{count, plural, ...}`)。中文无复数变化,但英文、俄文有,后期补齐成本高。 + +### 11.10 翻译与配置版本体系的关系 + +> V1.1 新增。本节落定"翻译是否纳入配置版本体系"。 + +**结论:翻译纳入同一套版本模型(10.4 元模型、10.5 变更集),但发布门槛设为最低档(轻量档)。** + +排除理由: + +- ❌ **不走严格审批**(同结构型):修改错别字也要等审批,运营会绕过系统直接改数据库。 +- ❌ **不独立于版本体系之外**:否则没有发布/回滚、没有审计、没有批量导入导出;且翻译与配置存在联动(新增字段时,字段标签翻译需与字段定义一同发布),两套体系无法实现原子发布,与 10.5 的变更集机制直接冲突。 + +轻量档的具体形态: + +| 能力 | 翻译是否具备 | +| ----------------------------------- | ------------ | +| 版本快照、一键回滚 | ✅ | +| 变更审计(谁改的、什么时候改的) | ✅ | +| 可进入变更集、与配置原子发布 | ✅ | +| 走审批才能生效 | ❌ | +| 必须走「草稿→校验→测试→发布」全链路 | ❌ | + +**热修复通道**:翻译属于高频、低风险、改错字类的操作,必须支持"改完立刻生效"的快速通道,10.4 的完整生命周期对其过重。翻译与「展示型」配置同属轻量档。 +## 12. 核心业务需求 + +### 12.1 基础资料 + +基础资料包括: + +- 客户、供应商和其他往来单位; +- 产品、物料、服务和分类; +- 单位、仓库、库位和批次规则; +- 价格表、付款条件和结算方式; +- 税率、币种和汇率; +- 银行账户和开票信息; +- 业务员、部门和负责人。 + +每项资料需要明确: + +- 集团共享还是公司专属; +- 谁可以查看和使用; +- 是否允许停用; +- 是否允许被历史单据引用; +- 是否支持多语言; +- 是否需要版本或有效期。 + +### 12.2 销售管理 + +销售流程至少支持: + +```text +报价 → 销售订单 → 审批 → 发货/出库 → 开票 → 收款/结算 +``` + +销售单据必须记录销售公司、销售组织、客户、仓库、币种、价格和税务信息。 + +### 12.3 采购管理 + +采购流程至少支持: + +```text +采购申请 → 采购订单 → 审批 → 收货/入库 → 发票 → 付款/结算 +``` + +采购公司、采购组织、收货仓库、供应商和结算主体可以按业务规则分别指定。 + +### 12.4 库存管理 + +库存管理至少支持: + +- 入库、出库、调拨和退货; +- 库存锁定和释放; +- 盘点和库存调整; +- 批次、保质期和序列号; +- 公司间调拨; +- 委托、寄售和其他库存所有权; +- 库存成本和库存余额。 + +库存数据必须明确公司、仓库、货主、产品和计量单位。 + +### 12.5 财务和结算 + +财务能力至少包括: + +- 公司独立账簿; +- 会计年度和期间; +- 应收、应付和往来核销; +- 费用、收款、付款和预收预付; +- 汇率和币种处理; +- 单据结算状态; +- 记账和反记账; +- 公司级财务报表。 + +财务单据必须归属公司和账簿。已过账数据不得通过普通编辑直接修改。 + +### 12.6 公司间交易 + +系统预留公司间交易能力,支持: + +- 公司间销售和采购; +- 公司间调拨; +- 代收代付; +- 内部往来; +- 公司间应收应付; +- 集团内部抵销标识。 + +公司间交易应记录: + +```text +source_company_id +target_company_id +intercompany_transaction_id +``` + +## 13. 数据模型要求 + +### 13.1 租户注册信息 + +首期可以使用配置文件维护以下信息,后续也可以将其迁移到平台库: + +```text +tenant_registry +tenant_database +tenant_module_license +tenant_migration_task +tenant_backup_task +tenant_domain_mapping +``` + +平台管理员、授权和运维任务是否进入平台库,根据部署模式决定;不影响租户数据库内的用户、公司和业务数据。 + +### 13.2 租户数据库核心对象 + +```text +s_user +s_role +s_user_role +s_company +s_organization +s_warehouse +s_ledger +s_user_company +s_user_organization +s_module +s_field +s_module_schema +s_workflow +s_permission +s_i18n_resource +s_i18n_translation +s_i18n_overlay +s_audit_log +``` + +> V1.1 新增以下配置版本与多语言对象(对应 10.4、10.5、11.1): + +```text +s_config_object +s_config_version +s_config_release +s_change_set +s_change_set_item +s_i18n_release +``` + +其中 `s_i18n_overlay` 只保存租户改过的 key(11.1 第 3 层),`s_i18n_release` 保存翻译版本快照(11.10)。 + +### 13.3 业务表通用字段 + +公司级业务表原则上包括: + +```text +company_id +organization_id 可选 +created_by +created_at +updated_by +updated_at +status +``` + +库存业务根据场景增加: + +```text +warehouse_id +owner_type +owner_id +``` + +财务业务根据场景增加: + +```text +ledger_id +fiscal_year +fiscal_period +currency_code +exchange_rate +``` + +### 13.4 数据库设计边界 + +核心字段使用关系列;动态字段根据访问频率采用 JSON 或扩展值表。不得为了追求绝对动态而将所有字段转换为 `entity_id + field_name + field_value` 的全量 EAV 结构。 + +## 14. 数据库路由和运行时需求 + +### 14.1 请求路由 + +请求处理流程: + +```text +请求进入 +→ 解析域名、登录信息或令牌 +→ 识别租户 +→ 读取租户注册表(配置文件或平台库) +→ 获取租户数据库标识 +→ 选择数据源和连接池 +→ 设置公司和组织上下文 +→ 执行业务查询或写入 +→ 清理上下文 +``` + +### 14.2 数据源管理 + +系统应支持: + +- 按租户动态创建数据源; +- 连接池复用和空闲释放; +- 租户数据库健康检查; +- 连接失败重试和熔断; +- 数据库只读状态; +- 租户迁移期间禁止普通写入; +- 日志记录租户、数据库和请求编号。 + +### 14.3 注册表实现和跨租户限制 + +`TenantRegistry` 至少支持文件实现和平台库实现两种方式。文件更新应具备格式校验、版本号和原子替换能力;平台库更新应具备事务和审计能力。 + +日常业务接口禁止跨租户查询和跨租户事务。平台级统计通过事件、CDC 或分析库实现,不在业务请求中遍历全部租户数据库。 + +## 15. 工作流与审批需求 + +### 15.1 流程模型 + +工作流采用状态机模型,包括: + +- 草稿; +- 提交; +- 审批中; +- 已通过; +- 已驳回; +- 已取消; +- 已完成; +- 已关闭。 + +### 15.2 审批节点 + +审批人来源支持: + +- 指定用户; +- 指定角色; +- 部门负责人; +- 公司负责人; +- 业务负责人; +- 发起人上级; +- 按金额、公司、组织或字段条件计算。 + +### 15.3 业务动作 + +流程节点可以触发: + +- 状态变更; +- 发送通知; +- 写入审计记录; +- 生成下一张业务单据; +- 锁定或释放库存; +- 触发打印或导出; +- 调用受控的业务处理器。 + +库存、财务和结算等关键动作必须经过业务处理器,不允许只依赖通用配置执行任意写入。 + +## 16. 审计、日志和可追溯性 + +系统应记录: + +- 登录、退出和租户切换; +- 公司和组织切换; +- 配置创建、发布和回滚; +- 权限授予、撤销和变更; +- 单据创建、修改、提交、审批和作废; +- 库存和财务关键动作; +- 导出、打印、备份和恢复; +- 平台管理员跨租户操作。 + +审计记录至少包含: + +```text +operator_id +tenant_code +company_id +operation_type +object_type +object_id +request_id +before_value +after_value +created_at +``` +## 17. 备份、恢复和迁移需求 + +### 17.1 租户级备份 + +系统支持单个租户执行: + +- 全量备份; +- 增量备份; +- 指定时间点恢复; +- 备份文件校验; +- 备份保留策略; +- 备份下载或转移; +- 恢复到临时数据库。 + +### 17.2 租户迁移 + +迁移流程: + +```text +申请迁移 +→ 检查租户状态 +→ 创建迁移前备份 +→ 切换只读 +→ 导出或复制数据库 +→ 校验数据和版本 +→ 更新租户连接文件或注册表记录 +→ 健康检查 +→ 恢复正常访问 +``` + +### 17.3 数据库版本 + +每个租户数据库必须维护当前结构版本。升级任务支持: + +- 版本扫描; +- 分批升级; +- 失败重试; +- 单租户暂停升级; +- 升级前备份; +- 执行记录和耗时; +- 失败原因和人工处理标记。 + +## 18. 报表和分析需求 + +### 18.1 公司级报表 + +首期支持: + +- 销售明细和汇总; +- 采购明细和汇总; +- 库存余额和收发存; +- 应收应付; +- 费用和结算; +- 公司利润和经营分析。 + +### 18.2 集团级报表 + +支持按公司、公司树、组织、区域、币种和期间汇总。集团报表需要考虑: + +- 不同公司的本位币; +- 汇率折算; +- 公司间交易识别; +- 内部往来抵销; +- 集团科目映射; +- 合并范围和有效期。 + +### 18.3 分析数据来源 + +日常交易查询使用租户数据库。跨公司和大数据量分析可通过事件或 CDC 同步到分析库,避免报表查询影响交易库。 + +## 19. 非功能需求 + +### 19.1 性能 + +- 常用列表查询应支持分页、排序和条件下推; +- 查询和数据权限尽量在 SQL 层完成; +- 不能在应用层加载全量数据后再过滤; +- 大型报表支持异步生成; +- 导入导出支持分批处理和进度反馈; +- 租户数据源应具备连接池上限和空闲回收机制。 + +### 19.2 可维护性 + +- 配置和业务逻辑分离; +- 租户数据库支持独立升级和恢复; +- 数据库迁移脚本可重复执行或具备明确版本记录; +- 核心业务规则集中实现; +- 动态模块不复制大量相同接口和页面代码。 + +### 19.3 可扩展性 + +- 支持新增公司和子公司; +- 支持新增语言(由超级管理员运行时配置,不需要发版); +- 支持新增模块、字段和流程; +- 支持独立数据库实例和外部数据库; +- 支持后续拆分库存、财务和分析服务; +- 支持公司级数据导出和迁移。 + +### 19.4 一致性 + +- 关键业务操作必须幂等; +- 库存和财务更新必须有明确事务边界; +- 已审核、已过账和已结算单据不能普通修改; +- 失败操作必须可重试或进入人工处理队列; +- 配置发布不能产生半发布状态(由 10.5 变更集的原子发布保证)。 + +## 20. 实施阶段建议 + +### 阶段一:平台基础和租户底座 + +- 租户连接配置或注册表; +- 租户开通和数据库路由; +- 数据库初始化和版本迁移; +- 用户、角色、公司和组织; +- 多语言基础资源; +- 审计日志; +- 备份和健康检查。 + +### 阶段二:动态配置底座 + +- 模块和字段元数据; +- 动态列表和查询; +- 动态表单; +- 字典和编号规则; +- 配置版本、发布和回滚; +- 基础权限和数据范围。 + +### 阶段三:核心业务 + +- 客户、供应商和产品; +- 销售和采购; +- 仓库、库存和调拨; +- 基础结算; +- 工作流和审批。 + +### 阶段四:财务和集团能力 + +- 账簿和期间; +- 应收应付; +- 费用和付款; +- 公司间交易; +- 集团汇总报表; +- 汇率和合并分析。 + +### 阶段五:增强能力 + +- 分析库和数据同步; +- 高级打印模板; +- 规则引擎; +- 外部系统接口; +- 独立数据库实例; +- 私有化部署和租户迁移工具。 + +## 21. 验收标准 + +### 21.1 租户隔离 + +- 新建两个租户并分别初始化数据库; +- 租户 A 的业务查询不能读取租户 B 的数据; +- 平台管理员切换租户有审计记录; +- 单个租户可以独立备份和恢复; +- 单个租户数据库可以迁移而不影响其他租户。 + +### 21.2 多公司 + +- 同一租户可以创建总部、子公司和分公司; +- 用户可被授权一个或多个公司; +- 公司级单据必须带 `company_id`; +- 基础资料可设置集团共享或公司专属; +- 公司级库存、账簿和报表相互隔离; +- 集团管理员可查看授权范围内的汇总数据。 + +### 21.3 动态配置 + +- 可新增自定义字段并在列表、表单和详情中使用; +- 可配置字段显隐、只读、必填和权限; +- 可配置流程并完成提交、审批、驳回和完成; +- 配置发布后可回滚到上一版本; +- 配置变更不会破坏历史单据展示。 + +### 21.4 多语言 + +- 用户可切换界面语言; +- 动态字段、字典和流程名称可翻译; +- 产品和基础资料支持多语言名称; +- 缺少翻译时按规则回退; +- 历史单据使用名称和税率快照; +- 打印模板可按语言输出。 + +### 21.5 运行维护 + +- 可查看每个租户数据库版本; +- 可执行租户级升级和失败重试; +- 可查看迁移、备份和恢复任务状态; +- 连接异常和数据库不可用时有明确错误提示; +- 大型跨公司报表不会阻塞日常单据操作。 + +## 22. 待确认事项 + +以下内容在进入详细设计前需要由业务方确认: + +1. 首期实际支持哪些语言; +2. 公司是否需要独立财务账簿和独立税务主体; +3. 是否首期实现公司间销售、采购和内部结算; +4. 首期支持哪些库存所有权类型; +5. 是否需要批次、序列号和保质期管理; +6. 租户数据库使用同一实例还是按规模分级部署; +7. 数据库备份保留周期和恢复时间目标; +8. 集团报表是否需要汇率折算和内部抵销; +9. 是否需要外部财务、税务、OA、CRM 或电商接口; +10. 哪些动态字段需要进入正式列或统计索引; +11. 业务配置是否需要测试环境和审批发布(V1.1 已按 10.7 类型注册表给出分类门槛,仍需业务方确认接受度); +12. 私有化部署是否作为首期交付范围; +13. 租户可覆盖的系统文本白名单范围是否完整(见 11.5,需确认锁死清单); +14. 历史单据名称快照是否需要支持多语言补打(见 11.7,选项 a/b/c 需业务方拍板); +15. 有状态配置(审批流、工作流)在途单据采用"实例绑定版本"的接受度(见 10.6); +16. 翻译变更纳入配置发布流程后,运营流程是否可配合(见 11.10); +17. 硬编码兜底层(11.1 第 1 层)最小文案集的具体范围。 + +## 23. 结论 + +平台库不是业务运行的硬性前提。对于租户数量较少、每个客户独立部署或由运维维护配置文件的场景,使用租户注册文件即可;当需要在线租户管理、集中运维、多实例同步或统一平台权限时,再启用平台库。无论采用哪种注册方式,业务代码保持一套,租户业务数据库保持独立。 + +系统采用以下总体方案: + +```text +代码 = 一套,租户差异通过配置、元数据和受控插件实现 +一个租户 = 一个独立数据库 +一个租户 = 多个公司、子公司和组织 +公司 = 业务、库存和财务归属边界 +组织 = 权限、审批和经营管理边界 +基础资料 = 支持集团共享或公司独立 +配置能力 = 动态字段、表单、流程、权限和打印 +多语言 = 界面、配置、主数据和历史单据快照(三层存储:租户覆盖 / 系统默认 / 硬编码兜底) +租户 = 受限用户,可改文案取值,不可新增语言 +超级管理员 = 运维持有,不交付客户,负责语言新增与默认值配置 +配置发布 = 以变更集为单元,跨对象校验,原子发布与原子回滚 +配置变更 = 无状态实时生效,有状态绑定版本跑完 +集团分析 = 公司维度汇总,必要时同步到分析库 +核心业务 = 由代码保证,不完全交给低代码配置 +``` + +最终目标不是把 ERP 做成一个万能低代码工具,而是建设一个具有稳定业务内核、清晰数据边界、可配置扩展能力和可独立运维能力的企业业务平台。 + +| | | +| ---- | ---- | +| | | +| | | +| | | +| | | +| | | \ No newline at end of file diff --git a/code/account1.json b/code/account1.json deleted file mode 100644 index 13f332d8..00000000 --- a/code/account1.json +++ /dev/null @@ -1,13 +0,0 @@ -[ - { - "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJteWZFenA3ODNLaV9KQ3g4Vm5jM1hfaXg2alpyYjZDZjVPTWtHWk1QSTNzIn0.eyJleHAiOjE3OTQ3MjUzMzksImlhdCI6MTc4OTU0MTMzOSwianRpIjoiODljMWFjZjYtMzcxNS00ZjEyLThhZWItMzljMGQ1MTNiNGRjIiwiaXNzIjoiaHR0cHM6Ly9jb3BpbG90LnRlbmNlbnQuY29tL2F1dGgvcmVhbG1zL2NvcGlsb3QiLCJhdWQiOiJhY2NvdW50Iiwic3ViIjoiNmJiZDQxMTUtNWJjOS00YmE3LTg1NDQtMzdlODcyMTUxZTBmIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiY29uc29sZSIsInNpZCI6IjhiNGY0NjlmLTc5NDMtNGYyMC1hMjVjLTE3YTQzY2U3NWM0OCIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiKiJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGVmYXVsdC1yb2xlcyIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6InByb2ZpbGUgb2ZmbGluZV9hY2Nlc3MgZW1haWwiLCJhcHBfdHlwZSI6ImNvZGVidWRkeSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicHJlZmVycmVkX3VzZXJuYW1lIjoiNjUxNjcxMDAiLCJlbnRlcnByaXNlX2lkIjoiIiwidG9rZW5fc291cmNlIjoiZW50ZXJwcmlzZV9zd2l0Y2gifQ.bbQJOKLg9CFON7HzkXLElnZDMjf1l0vRdeRdViC7KL7D-1OKaTcTL5M0QHJoGbOgtZERlVGmPoj7nviJ1QdXcbMVXuR0g9xL8_zz1KqzgMAAs1fmTnwFy--vPV7k_LlqK6kjGz5gbTnFNEXUIETmczSvi4NWoDQ2W33NgQVxmQaikvmhz8Snq0f3Ke-gYpJrW2MLytuG4f2hC6TLgbcpgGlxzZh-RiBE6zUT_UazCZm35Pq63yJVIjn7mLNvS8zTvU3HlXP_pxJlQXiDwEwFqKaWTNnD_h4pYIuWe81f5TizM_KxSudcmHRA1Kv-mOQlDGWLKyqLv-9zUyPnM8-ybA", - "domain": "www.codebuddy.cn", - "email": "65167100", - "expires_at": 1794725339, - "nickname": "65167100", - "phone": "65167100", - "refresh_token": "eyJhbGciOiJIUzUxMiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI2M2I4YzRkNS1jMTJjLTRhMGQtYjk5NC01ZTBjMDY0N2QwMDIifQ.eyJleHAiOjE3OTU1ODkzMzksImlhdCI6MTc4OTU0MTMzOSwianRpIjoiZDE3Y2ZiNDgtNmMxOC00MzBlLTk5NzMtZDQzNzZhZGE3N2U1IiwiaXNzIjoiaHR0cHM6Ly9jb3BpbG90LnRlbmNlbnQuY29tL2F1dGgvcmVhbG1zL2NvcGlsb3QiLCJhdWQiOiJodHRwczovL2NvcGlsb3QudGVuY2VudC5jb20vYXV0aC9yZWFsbXMvY29waWxvdCIsInN1YiI6IjZiYmQ0MTE1LTViYzktNGJhNy04NTQ0LTM3ZTg3MjE1MWUwZiIsInR5cCI6Ik9mZmxpbmUiLCJhenAiOiJjb25zb2xlIiwic2lkIjoiOGI0ZjQ2OWYtNzk0My00ZjIwLWEyNWMtMTdhNDNjZTc1YzQ4Iiwic2NvcGUiOiJhY3IgcHJvZmlsZSBiYXNpYyB3ZWItb3JpZ2lucyByb2xlcyBvZmZsaW5lX2FjY2VzcyBlbWFpbCJ9.ir-XJ4kurVBXnfImAzXJBF40ZeSWvuiOKRR8bPgH0kX5ePtR4qodPfwWcLrET6qhrY2MXx-XdBHgJFc1LiIk4w", - "token_type": "Bearer", - "uid": "6bbd4115-5bc9-4ba7-8544-37e872151e0f" - } -] \ No newline at end of file