aps-agent/docs/architecture/database.md

63 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 数据库层(SQLite 主数据 + world 投影)
> M-A 落地:主数据不再写死在代码里,康尼只是数据库里的一个「项目」。
> 代码:`server/db/`(models / database / sync)、`server/state/packs.py`、`server/importers/`。
## 定位
- **SQLite(`server/data/master.db`,`APS_DB_PATH` 可覆盖)**:主数据的持久源——项目、
主数据宽表(资源/物料/BOM/工序/路线/订单/柔性表)、行业工艺路线模板。
- **world.json**:排产运行态(版本/工单/冲突/检查点/审计)仍留在 `WorldStore`;
引擎零改动,读的还是 world dict。
- **knowledge.json + embeddings.json**:RAG 知识库(见 [rag.md](./rag.md))。
## 表结构(`server/db/models.py`,SQLAlchemy 2.0)
| 表 | 作用 |
| --- | --- |
| `projects` | 项目/租户(demo、kangni…),`is_active` 标记当前投影项目 |
| `master_records` | 通用宽表:`(project_id, table_key, seq)` + `code/name` 索引列 + `payload` JSON 全量;`table_key` 覆盖 `factories/materials/flexOrders/routingSteps/...`(清单见 `sync.MASTER_LIST_KEYS`) |
| `project_settings` | dict 型主数据(`factoryCalendar/changeoverMatrix/...`,见 `MASTER_DICT_KEYS`) |
| `routing_templates` / `routing_template_steps` | 行业工艺路线模板库(M-E,含推荐工时区间/设备类型/知识资产关联) |
宽表设计的取舍:world 的主数据形态仍在快速演进,`payload` 存整行 JSON、
`code/name/seq` 提列做索引,避免每加一个字段就迁 schema;引擎兼容性优先。
## 投影与同步(`server/db/sync.py` + `state/store.py`)
```
启动: WorldStore.__init__ → _sync_with_db()
DB 有主数据 → db_to_world() 覆盖 world 主数据键(DB 为准)
DB 空 world 有 → world_to_db() 一次性迁移(保留现场已导入数据)
写入: store.save() → _sync_master_to_db()(master_fingerprint 脏检查,变了才写)
```
- `set_active_project(code)` 切换活跃项目;`db_to_world` 只投影该项目数据。
- `APS_DB_DISABLED=1` 完全绕过 DB(测试/降级);DB 异常不阻断 world 主流程。
## 数据包(`server/state/packs.py`)
- `export_pack(world, name)` → `server/data/packs/<name>.json`(记录 `baseDate`)。
- `load_pack(name)` 重放时把所有日期按 `baseDate→今天` 平移(演示数据永不过期)。
- `seed_world()`:`APS_SEED_PACK` 指定则重放数据包,否则 `build_demo_world()` 程序化种子。
- `scripts/generate_demo_pack.py` 重新生成 `demo.json`。
## 导入器配置化(`server/importers/`)
- `excel_importer.import_site_excel(profile_name, path)`:按 profile 解析现场 Excel → 入库 → 投影。
- `profiles/kangni.json`:工厂名、区域、工时推断规则(部装 45/装配 30…)、换型/接刀默认、
班组、日历——原 `kangni_intake.py` 的硬编码全部搬进配置;解析函数吃 profile 参数。
- 新客户 = 新增一个 profile JSON,不改代码。
## API
| 端点 | 用途 |
| --- | --- |
| `GET /api/projects` | 项目清单 + 活跃项目(P0) |
| `GET /api/packs` | 可重放数据包清单(P0) |
## 测试
`tests/golden/test_db_projection.py`(入库→投影→PoolEngine 可排、多项目隔离、数据包日期平移)、
`test_excel_importer.py`(profile 等价性 + 覆写生效 + stdTimeSource 标记)。