3.3 KiB
3.3 KiB
数据库层(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)。
表结构(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 标记)。