init: 项目初始提交 - NeoZQYY Monorepo 完整代码

This commit is contained in:
Neo
2026-02-15 14:58:14 +08:00
commit ded6dfb9d8
769 changed files with 182616 additions and 0 deletions

View File

@@ -0,0 +1 @@
{"generationMode": "requirements-first"}

View File

@@ -0,0 +1,553 @@
# 设计文档Monorepo 迁移
## 概述
本设计将现有单一 ETL 仓库(`FQ-ETL`)迁移为 Monorepo 单体仓库(`NeoZQYY`),采用一次性搬迁策略。核心设计原则:
1. **最小破坏性**ETL 整体平移,保持内部结构不变,仅调整外部引用
2. **分层隔离**:通过 uv workspace 实现 Python 包依赖隔离,通过 `.env` 分层实现配置隔离
3. **数据库重组**:从现有 4 个 schemabilliards_ods/billiards_dwd/billiards_dws/etl_admin重组为 6 层 schemameta/ods/dwd/core/dws/app
4. **渐进式扩展**:第一阶段只建必要骨架,未来扩展点记录在 Roadmap 中
## 架构
### 整体架构
```mermaid
graph TB
subgraph "NeoZQYY Monorepo"
subgraph "apps/"
ETL["apps/etl/pipelines/feiqiu/"]
Backend["apps/backend/ (FastAPI)"]
Mini["apps/miniprogram/ (Donut+TDesign)"]
Admin["apps/admin-web/ (未来)"]
end
subgraph "packages/"
Shared["packages/shared/"]
end
subgraph "gui/"
GUI["gui/ (PySide6过渡期)"]
end
subgraph "db/"
ETLDB["db/etl_feiqiu/"]
AppDB["db/zqyy_app/"]
FDW["db/fdw/"]
end
end
ETL --> Shared
Backend --> Shared
GUI --> Shared
Backend --> AppDB
ETL --> ETLDB
AppDB -.->|postgres_fdw 只读| ETLDB
```
### 数据流架构
```mermaid
graph LR
API["上游 SaaS API"] --> ODS["ods (原始数据)"]
ODS --> DWD["dwd (main+EX 明细)"]
DWD --> Core["core (统一最小字段集)"]
DWD --> DWS["dws (汇总/工资)"]
Core --> DWS
DWS --> App["app (视图+RLS)"]
App -.->|FDW 只读映射| ZqyyApp["zqyy_app DB"]
ZqyyApp --> FastAPI["FastAPI 后端"]
FastAPI --> MiniApp["微信小程序"]
subgraph "etl_feiqiu DB"
Meta["meta (调度/游标)"]
ODS
DWD
Core
DWS
App
end
```
## 组件与接口
### 1. 目录结构生成器Scaffold
负责创建 Monorepo 完整目录结构和基础配置文件。
**输入**:目标路径 `C:\NeoZQYY\`
**输出**:完整目录树 + README.md + 配置文件
**关键行为**
- 创建所有一级和二级目录
- 为每个一级目录生成 README.md作用 + 结构 + Roadmap
- 生成 `.gitignore``.kiroignore``.env.template`
- 初始化 Git 仓库
### 2. uv Workspace 配置
**根 `pyproject.toml`**
```toml
[project]
name = "neozqyy"
version = "0.1.0"
requires-python = ">=3.10"
[tool.uv.workspace]
members = [
"apps/etl/pipelines/feiqiu",
"apps/backend",
"packages/shared",
"gui",
]
```
**子项目 `pyproject.toml` 模式**(以 ETL 为例):
```toml
[project]
name = "etl-feiqiu"
version = "0.1.0"
requires-python = ">=3.10"
dependencies = [
"psycopg2-binary>=2.9.0",
"requests>=2.28.0",
"python-dateutil>=2.8.0",
"tzdata>=2023.0",
"python-dotenv",
"openpyxl>=3.1.0",
"neozqyy-shared",
]
[tool.uv.sources]
neozqyy-shared = { workspace = true }
```
### 3. 配置隔离机制
**分层加载顺序**
```
根 .env公共配置→ 应用 .env.local私有覆盖→ 环境变量 → CLI 参数
```
**实现方式**
- 现有 `AppConfig``DEFAULTS < ENV < CLI` 模式保持不变
- 新增:在 `load_env_overrides()` 中先加载根 `.env`,再加载应用级 `.env.local`
- 冲突策略:应用级优先(后加载覆盖先加载)
- 缺失检测:在 `_validate()` 中检查必需项,报告缺失项名称
### 4. ETL 平移策略
**平移范围**
| 源路径 | 目标路径 | 说明 |
|--------|----------|------|
| `api/` | `apps/etl/pipelines/feiqiu/api/` | API 客户端 |
| `cli/` | `apps/etl/pipelines/feiqiu/cli/` | CLI 入口 |
| `config/` | `apps/etl/pipelines/feiqiu/config/` | 配置 |
| `loaders/` | `apps/etl/pipelines/feiqiu/loaders/` | 加载器 |
| `models/` | `apps/etl/pipelines/feiqiu/models/` | 模型 |
| `orchestration/` | `apps/etl/pipelines/feiqiu/orchestration/` | 调度 |
| `scd/` | `apps/etl/pipelines/feiqiu/scd/` | SCD2 |
| `tasks/` | `apps/etl/pipelines/feiqiu/tasks/` | 任务 |
| `utils/` | `apps/etl/pipelines/feiqiu/utils/` | 工具 |
| `quality/` | `apps/etl/pipelines/feiqiu/quality/` | 质量检查 |
| `tests/` | `apps/etl/pipelines/feiqiu/tests/` | 测试 |
| `database/*.sql` | `db/etl_feiqiu/schemas/` | DDL |
| `database/migrations/` | `db/etl_feiqiu/migrations/` | 迁移脚本 |
| `database/seed_*.sql` | `db/etl_feiqiu/seeds/` | 种子数据 |
| `gui/` | `gui/` | GUI顶层 |
**import 路径策略**
- ETL 内部使用相对 import`from .config.settings import AppConfig`)或保持现有绝对 import
- `pyproject.toml` 中设置 `pythonpath`,使 `apps/etl/pipelines/feiqiu/` 为 Python 路径根
- `pytest.ini` 同步更新 `pythonpath = .`
- 目标ETL 内部代码零修改或最小修改
### 5. 小程序平移策略
**平移范围**
| 源路径 | 目标路径 |
|--------|----------|
| `C:\ZQYY\XCX\`(除 Prototype | `apps/miniprogram/` |
| `C:\ZQYY\XCX\Prototype\` | `docs/h5_ui/` |
小程序为独立前端项目Donut + TDesign不涉及 Python 依赖管理,直接复制即可。
### 6. 数据库 Schema 重组etl_feiqiu
**现有 → 新 schema 映射**
| 现有 Schema | 新 Schema | 说明 |
|-------------|-----------|------|
| `etl_admin` | `meta` | 调度、游标、运行记录 |
| `billiards_ods` | `ods` | ODS 原始数据,结构不变 |
| `billiards_dwd` | `dwd` | DWD 明细,保留 main+EX 拆分 |
| (新增) | `core` | 统一维度/事实最小字段集 |
| `billiards_dws` | `dws` | DWS 汇总,结构不变 |
| (新增) | `app` | 面向外部的视图/函数 + RLS |
**core schema 设计原则**
- 仅包含跨系统共享的最小字段集(如会员 ID、姓名、手机号、状态
- 维度表从 DWD 维度表提取核心字段
- 事实表从 DWD 事实表提取核心度量
- 第一版保持精简,后续按需扩展
**app schema 设计原则**
- 以视图VIEW封装 DWS/Core 层数据
- 所有视图启用 RLS`site_id` 过滤
- 提供函数接口供 FDW 映射使用
- 不存储实际数据,仅做访问层
**RLS 实现方案**
```sql
-- 创建应用角色
CREATE ROLE app_reader;
-- 在 app schema 的视图上启用 RLS
ALTER TABLE app.v_member_summary ENABLE ROW LEVEL SECURITY;
-- 创建策略:根据会话变量 app.current_site_id 过滤
CREATE POLICY site_isolation ON app.v_member_summary
FOR SELECT TO app_reader
USING (site_id = current_setting('app.current_site_id')::bigint);
```
### 7. 业务数据库设计zqyy_app
**核心表**
- `users`:用户账户(微信 OpenID、手机号、角色
- `roles` / `permissions`RBAC 权限模型
- `user_roles`:用户-角色关联
- `tasks`:任务管理(审批流)
- `approvals`:审批记录
**FDW 映射**
```sql
-- 在 zqyy_app 中创建外部服务器
CREATE SERVER etl_feiqiu_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'localhost', dbname 'etl_feiqiu', port '5432');
-- 创建用户映射
CREATE USER MAPPING FOR app_user
SERVER etl_feiqiu_server
OPTIONS (user 'app_reader', password '***');
-- 导入 app schema 的外部表
IMPORT FOREIGN SCHEMA app
FROM SERVER etl_feiqiu_server
INTO fdw_etl;
```
**约束**FDW 映射为只读,`zqyy_app` 不存储 ETL 数据副本。
### 8. FastAPI 后端骨架
**项目结构**
```
apps/backend/
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI 入口
│ ├── config.py # 配置加载
│ ├── database.py # 数据库连接
│ ├── routers/ # 路由模块
│ │ └── __init__.py
│ ├── middleware/ # 中间件
│ │ └── __init__.py
│ └── schemas/ # Pydantic 模型
│ └── __init__.py
├── tests/
│ └── __init__.py
├── pyproject.toml
└── README.md
```
**关键配置**
- 连接 `zqyy_app` 数据库(通过 FDW 访问 ETL 数据)
- OpenAPI 文档自动生成FastAPI 内置)
- 依赖 `packages/shared` 获取通用工具
### 9. 共享包packages/shared
**模块划分**
```
packages/shared/
├── src/
│ └── neozqyy_shared/
│ ├── __init__.py
│ ├── enums.py # 字段枚举定义
│ ├── money.py # 金额精度工具CNY, numeric(2)
│ └── datetime_utils.py # 时间处理工具
├── tests/
│ └── __init__.py
├── pyproject.toml
└── README.md
```
**提取来源**
- `enums.py`:从 ETL 的 `models/` 中提取通用枚举
- `money.py`:金额四舍五入、格式化(`Decimal` + `ROUND_HALF_UP`scale=2
- `datetime_utils.py`:时区转换、日期范围计算(从 `utils/` 提取)
### 10. .kiro 迁移
**迁移内容**
- 复制 `.kiro/steering/` 到 Monorepo
- 更新 `product.md`:从单一 ETL 视角扩展为 Monorepo 全局视角
- 更新 `tech.md`:新增 FastAPI、uv workspace、Donut+TDesign 等技术栈
- 更新 `structure-lite.md`:反映 Monorepo 目录结构和模块边界
- 更新路径引用:所有 steering 文件中的路径适配新结构
## 数据模型
### etl_feiqiu 数据库(六层 Schema
```mermaid
erDiagram
META {
bigint run_id PK
text task_code
timestamptz started_at
timestamptz ended_at
text status
jsonb result_summary
}
META ||--o{ ODS : "调度触发"
ODS {
bigint id PK
text content_hash PK
jsonb payload
text source_endpoint
timestamptz fetched_at
}
ODS ||--o{ DWD : "清洗装载"
DWD {
bigint id PK
timestamptz scd2_start_time
timestamptz scd2_end_time
int scd2_is_current
int scd2_version
}
DWD ||--o{ CORE : "提取最小字段集"
CORE {
bigint id PK
text name
bigint site_id
}
DWD ||--o{ DWS : "汇总聚合"
CORE ||--o{ DWS : "汇总聚合"
DWS {
bigint id PK
date stat_date
numeric amount
bigint site_id
}
DWS ||--o{ APP : "视图封装"
APP {
text view_name
text rls_policy
}
```
### zqyy_app 数据库
```mermaid
erDiagram
USERS {
bigint id PK
text wx_openid UK
text mobile
text nickname
int status
timestamptz created_at
}
ROLES {
int id PK
text name UK
text description
}
USER_ROLES {
bigint user_id FK
int role_id FK
}
PERMISSIONS {
int id PK
text resource
text action
}
ROLE_PERMISSIONS {
int role_id FK
int permission_id FK
}
USERS ||--o{ USER_ROLES : "拥有"
ROLES ||--o{ USER_ROLES : "分配给"
ROLES ||--o{ ROLE_PERMISSIONS : "包含"
PERMISSIONS ||--o{ ROLE_PERMISSIONS : "授予"
FDW_ETL_VIEWS {
text foreign_table_name
text source_schema
text mapping_type
}
```
### 配置分层模型
```
优先级(低 → 高):
┌─────────────────────────────┐
│ 根 .env公共配置模板 │ DB_HOST, DB_PORT, TIMEZONE
├─────────────────────────────┤
│ 应用 .env.local私有覆盖 │ DB_NAME, DB_PASSWORD, API_TOKEN
├─────────────────────────────┤
│ 环境变量 │ 运行时覆盖
├─────────────────────────────┤
│ CLI 参数 │ 最高优先级
└─────────────────────────────┘
```
## 正确性属性
*属性是系统在所有有效执行中都应保持为真的特征或行为——本质上是关于系统应该做什么的形式化陈述。属性是人类可读规格与机器可验证正确性保证之间的桥梁。*
### Property 1: README.md 结构完整性
*对于任意* Monorepo 一级目录,其 README.md 文件应存在且包含"作用说明"、"结构描述"和"Roadmap"三个段落。
**Validates: Requirements 1.5**
### Property 2: Python 子项目配置完整性
*对于任意* uv workspace 声明的 Python 子项目成员,该子项目目录下应存在独立的 `pyproject.toml` 文件,且文件中包含 `[project]` 段落。
**Validates: Requirements 3.2**
### Property 3: 配置优先级 - .env.local 覆盖
*对于任意*配置项名称和两个不同的值,当根 `.env` 和应用 `.env.local` 都定义了该配置项时,配置加载器返回的值应等于 `.env.local` 中的值。
**Validates: Requirements 4.3**
### Property 4: 必需配置缺失检测
*对于任意*必需配置项,当所有配置层级(.env、.env.local、环境变量、CLI均未提供该项时配置加载器应抛出错误且错误信息中包含该缺失配置项的名称。
**Validates: Requirements 4.4**
### Property 5: 文件迁移完整性
*对于任意*源-目标目录映射关系ETL 业务代码、database 文件、tests 目录),源目录中的每个文件在目标目录的对应位置都应存在且内容一致。
**Validates: Requirements 5.1, 5.2, 5.3**
### Property 6: Schema 表定义迁移完整性
*对于任意*现有数据库 schemabilliards_ods、billiards_dws中的表新 schemaods、dws的 DDL 文件中应包含该表的 CREATE TABLE 定义。
**Validates: Requirements 7.3, 7.6**
### Property 7: Core schema 最小字段集
*对于任意* core schema 中的表,其字段数量应严格少于对应 dwd schema 中同名(或对应)表的字段数量。
**Validates: Requirements 7.5**
### Property 8: 测试数据库结构一致性
*对于任意*生产数据库etl_feiqiu、zqyy_app中的 schema 和表定义对应的测试数据库test_etl_feiqiu、test_zqyy_app中应存在相同的 schema 和表结构。
**Validates: Requirements 9.1, 9.2**
### Property 9: Steering 文件路径更新
*对于任意* `.kiro/steering/` 目录下的文件,文件内容中不应包含旧仓库路径引用(如 `FQ-ETL``C:\ZQYY\FQ-ETL`)。
**Validates: Requirements 10.2**
### Property 10: 业务表 site_id 字段存在性
*对于任意* app schema 中的业务视图和 dws/core schema 中的业务表,其定义中应包含 `site_id` 字段。
**Validates: Requirements 13.1**
### Property 11: RLS 按 site_id 隔离
*对于任意* app schema 中启用了 RLS 的视图,当会话变量 `app.current_site_id` 设置为某个门店 ID 时,查询结果应仅包含该 `site_id` 的数据行。
**Validates: Requirements 13.2**
## 错误处理
### 配置错误
- **缺失必需配置**:启动时立即报错,列出所有缺失项名称,不启动服务
- **配置值格式错误**:报告具体的配置项路径和期望格式
- **.env 文件不存在**:使用默认值继续,不报错(.env.template 仅为模板)
### 迁移错误
- **源文件不存在**:记录警告日志,继续迁移其他文件,最终汇总报告缺失文件列表
- **目标目录已存在**:提示用户确认是否覆盖,默认不覆盖
- **import 路径修复失败**:记录错误日志,标记需要手动修复的文件
### 数据库错误
- **Schema 创建失败**:回滚当前 schema 的所有 DDL报告失败原因
- **FDW 连接失败**:记录错误日志,不影响本地表的正常使用
- **RLS 策略创建失败**:回滚策略创建,报告受影响的表
### 测试数据库错误
- **结构不一致**:提供 diff 工具比较生产与测试库结构差异
- **数据迁移失败**:回滚到迁移前状态,报告失败的表和原因
## 测试策略
### 测试框架
- **单元测试**`pytest`Python 子项目)
- **属性测试**`hypothesis`Python 属性测试库)
- 每个属性测试配置最少 100 次迭代
### 单元测试覆盖
1. **Scaffold 测试**:验证目录创建、文件生成的具体示例
2. **配置加载器测试**:验证分层加载、冲突处理、缺失检测的边界情况
3. **迁移脚本测试**:验证文件复制、路径映射的具体场景
4. **DDL 语法测试**:验证生成的 SQL 语法正确性
### 属性测试覆盖
每个属性测试必须引用设计文档中的属性编号:
- **Feature: monorepo-migration, Property 1: README.md 结构完整性** — 验证所有一级目录 README 包含必需段落
- **Feature: monorepo-migration, Property 2: Python 子项目配置完整性** — 验证所有 workspace 成员有 pyproject.toml
- **Feature: monorepo-migration, Property 3: 配置优先级** — 生成随机配置项,验证 .env.local 覆盖行为
- **Feature: monorepo-migration, Property 4: 必需配置缺失检测** — 生成随机必需项组合,验证缺失报错
- **Feature: monorepo-migration, Property 5: 文件迁移完整性** — 验证源-目标文件映射的完整性
- **Feature: monorepo-migration, Property 6: Schema 表定义迁移完整性** — 验证现有表在新 DDL 中存在
- **Feature: monorepo-migration, Property 7: Core schema 最小字段集** — 验证 core 表字段数少于 dwd
- **Feature: monorepo-migration, Property 8: 测试数据库结构一致性** — 验证测试库与生产库结构相同
- **Feature: monorepo-migration, Property 9: Steering 文件路径更新** — 验证无旧路径残留
- **Feature: monorepo-migration, Property 10: 业务表 site_id 存在性** — 验证业务表包含 site_id
- **Feature: monorepo-migration, Property 11: RLS 隔离** — 验证 RLS 按 site_id 过滤(集成测试)
### 集成测试
- **ETL 运行验证**:在新目录结构下运行 `pytest tests/unit`,确保所有现有测试通过
- **数据库 Schema 验证**:在测试数据库上执行 DDL验证 schema 创建成功
- **FDW 连接验证**:验证 zqyy_app 通过 FDW 可读取 etl_feiqiu 的 app schema 数据
- **uv workspace 验证**:运行 `uv sync`,验证所有子项目依赖正确解析

View File

@@ -0,0 +1,186 @@
# 需求文档Monorepo 迁移
## 简介
将现有台球厅运营助手项目从单一 ETL 仓库(`FQ-ETL`)扩展为 Monorepo 单体仓库(`NeoZQYY`),整合 ETL 管线、微信小程序后端、小程序前端、管理后台等多个子项目。迁移采用一次性搬迁策略,不保留 Git 历史,所有架构决策已在前期讨论中确认。
## 术语表
- **Monorepo**:单体仓库,多个子项目共存于同一 Git 仓库中
- **ETL_Pipeline**:数据抽取-转换-加载管线,负责从上游 SaaS API 抓取数据并逐层处理
- **ODS**操作数据存储层Operational Data Store保留源 payload
- **DWD**明细数据层Data Warehouse Detail清洗后的明细数据
- **DWS**数据服务层Data Warehouse Service汇总与聚合数据
- **Core**:统一维度/事实最小字段集层,位于 DWD 与 DWS 之间
- **App_Schema**:应用层 schema提供视图/函数 + RLS 供外部访问
- **Meta_Schema**:元数据层 schema存储 ETL 调度、游标、运行记录
- **FDW**PostgreSQL 外部数据包装器Foreign Data Wrapper用于跨库只读映射
- **uv_Workspace**Python 包管理工具 uv 的 workspace 模式,管理多包依赖
- **RLS**行级安全策略Row Level Security用于多门店数据隔离
- **SCD2**:缓慢变化维度类型 2Slowly Changing Dimension Type 2维度历史追踪
- **etl_feiqiu**:飞球平台 ETL 数据库实例名
- **zqyy_app**:业务应用数据库实例名(用户/权限/任务/审批)
- **site_id**:门店标识字段,用于多门店数据隔离
- **Scaffold**项目骨架包含目录结构、配置文件、README 等基础设施
## 需求
### 需求 1Monorepo 骨架搭建
**用户故事:** 作为开发者,我希望在 `C:\NeoZQYY\` 创建完整的 Monorepo 目录结构和基础配置,以便所有子项目有统一的组织方式和开发规范。
#### 验收标准
1. WHEN Scaffold 初始化执行时THE Scaffold SHALL 在 `C:\NeoZQYY\` 下创建以下一级目录:`apps/``gui/``packages/``db/``docs/``infra/``scripts/``samples/``tests/``tmp/``.kiro/`
2. WHEN Scaffold 初始化执行时THE Scaffold SHALL 在 `apps/` 下创建子目录:`etl/`(含 `pipelines/feiqiu/`)、`backend/``miniprogram/``admin-web/`
3. WHEN Scaffold 初始化执行时THE Scaffold SHALL 在 `db/` 下创建子目录:`etl_feiqiu/`(含 `schemas/``migrations/``seeds/`)、`zqyy_app/`(含 `schemas/``migrations/``seeds/`)、`fdw/`
4. WHEN Scaffold 初始化执行时THE Scaffold SHALL 在 `docs/` 下创建子目录:`prd/``contracts/`(含 `openapi/``schemas/``data_dictionary/`)、`permission_matrix/``architecture/``database/``h5_ui/``ops/``audit/``roadmap/`
5. THE Scaffold SHALL 为每个一级目录生成 `README.md` 文件,包含该目录的作用说明、内部结构描述和 Roadmap 段落
6. WHEN 某个功能"暂不实施但未来必须做"时THE Scaffold SHALL 将该内容记录在对应目录 `README.md` 的 Roadmap 段落中
### 需求 2Git 仓库与版本控制配置
**用户故事:** 作为开发者,我希望新 Monorepo 有正确的 Git 配置,以便代码版本管理规范且安全。
#### 验收标准
1. WHEN Git 仓库初始化时THE Scaffold SHALL 创建新的 Git 仓库,不迁移旧仓库历史
2. THE Scaffold SHALL 生成 `.gitignore` 文件,排除 `tmp/``__pycache__/``.env`(非模板)、`*.pyc``.hypothesis/``.pytest_cache/``logs/``node_modules/`、虚拟环境目录等
3. THE Scaffold SHALL 生成 `.kiroignore` 文件,排除不需要 Kiro 索引的目录
### 需求 3Python 包管理与 uv Workspace 配置
**用户故事:** 作为开发者,我希望使用 `pyproject.toml` + `uv` workspace 管理多包依赖,以便各子项目的依赖隔离且可统一管理。
#### 验收标准
1. THE Scaffold SHALL 在 Monorepo 根目录生成 `pyproject.toml`,配置 uv workspace 并声明所有 Python 子项目成员
2. THE Scaffold SHALL 为每个 Python 子项目(`apps/etl/pipelines/feiqiu/``apps/backend/``packages/shared/``gui/`)生成独立的 `pyproject.toml`
3. WHEN 子项目声明对 `packages/shared` 的依赖时THE uv_Workspace SHALL 通过 workspace 路径引用解析该依赖
### 需求 4环境配置隔离
**用户故事:** 作为开发者,我希望公共配置和各应用私有配置分层管理,以便敏感信息不泄露且配置不冲突。
#### 验收标准
1. THE Scaffold SHALL 在 Monorepo 根目录生成 `.env.template` 文件,包含公共配置项(数据库主机、端口等非敏感信息)的模板
2. WHEN 各应用需要私有配置时THE Scaffold SHALL 支持在应用目录下放置 `.env.local` 文件覆盖公共配置
3. IF 公共 `.env` 与应用 `.env.local` 存在同名配置项且值冲突THEN THE 配置加载器 SHALL 以应用级 `.env.local` 的值为准
4. IF 必需的配置项在所有层级均缺失THEN THE 配置加载器 SHALL 在启动时报告明确的错误信息,指出缺失的配置项名称
### 需求 5ETL 项目平移
**用户故事:** 作为开发者,我希望将现有 ETL 项目整体平移到 Monorepo 中,以便 ETL 功能在新仓库中正常运行。
#### 验收标准
1. WHEN ETL 平移执行时THE 迁移脚本 SHALL 将 `C:\ZQYY\FQ-ETL` 的业务代码(`api/``cli/``config/``loaders/``models/``orchestration/``scd/``tasks/``utils/``quality/`)复制到 `apps/etl/pipelines/feiqiu/`
2. WHEN ETL 平移执行时THE 迁移脚本 SHALL 将 `database/` 目录的 DDL、seed、migration 文件迁移到 `db/etl_feiqiu/` 对应子目录
3. WHEN ETL 平移执行时THE 迁移脚本 SHALL 将 `tests/` 目录复制到 `apps/etl/pipelines/feiqiu/tests/`
4. WHEN ETL 平移完成后THE ETL_Pipeline SHALL 通过 `pytest tests/unit` 验证所有单元测试通过
5. IF ETL 内部存在需要调整的 import 路径THEN THE 迁移脚本 SHALL 更新这些路径以适配新目录结构
6. WHEN ETL 平移执行时THE 迁移脚本 SHALL 将现有 `gui/` 目录迁移到 Monorepo 顶层 `gui/`
### 需求 6小程序前端平移
**用户故事:** 作为开发者,我希望将微信小程序项目迁移到 Monorepo 中,以便前端代码与后端统一管理。
#### 验收标准
1. WHEN 小程序平移执行时THE 迁移脚本 SHALL 将 `C:\ZQYY\XCX` 的项目文件复制到 `apps/miniprogram/`
2. WHEN 小程序平移执行时THE 迁移脚本 SHALL 将 `C:\ZQYY\XCX\Prototype` 目录复制到 `docs/h5_ui/`
3. WHEN 小程序平移完成后THE 小程序项目 SHALL 保持原有的 Donut + TDesign 技术栈配置不变
### 需求 7数据库 Schema 重组etl_feiqiu
**用户故事:** 作为数据工程师,我希望将 ETL 数据库重组为六层 schema 架构,以便数据分层清晰、职责明确。
#### 验收标准
1. THE 数据库迁移 SHALL 为 `etl_feiqiu` 数据库创建六个 schema`meta``ods``dwd``core``dws``app`
2. WHEN `meta` schema 创建时THE DDL SHALL 包含 ETL 调度、游标、运行记录相关表(从现有 `etl_admin` schema 迁移)
3. WHEN `ods` schema 创建时THE DDL SHALL 包含现有 `billiards_ods` 的所有表定义
4. WHEN `dwd` schema 创建时THE DDL SHALL 保留现有 main + EX 拆分模式(因字段量大)
5. WHEN `core` schema 创建时THE DDL SHALL 仅包含统一维度表和事实表的最小字段集
6. WHEN `dws` schema 创建时THE DDL SHALL 包含现有 `billiards_dws` 的汇总表定义(助教业绩、财务日报、工资计算等)
7. WHEN `app` schema 创建时THE DDL SHALL 创建面向外部访问的视图和函数,并配置 RLS 策略以 `site_id` 隔离多门店数据
8. THE 数据库迁移 SHALL 将所有 DDL 文件存放在 `db/etl_feiqiu/schemas/` 目录下,每个 schema 一个独立文件
### 需求 8业务数据库设计zqyy_app
**用户故事:** 作为后端开发者,我希望有独立的业务数据库存储用户、权限、任务、审批等应用数据,以便业务逻辑与 ETL 数据解耦。
#### 验收标准
1. THE 数据库迁移 SHALL 为 `zqyy_app` 数据库创建用户管理、权限控制、任务管理、审批流程相关的表结构
2. THE 数据库迁移 SHALL 将 `zqyy_app` 的 DDL 文件存放在 `db/zqyy_app/schemas/` 目录下
3. WHEN `zqyy_app` 需要访问 ETL 数据时THE FDW 配置 SHALL 通过 `postgres_fdw``etl_feiqiu``app` schema 映射为 `zqyy_app` 中的外部表
4. THE FDW 配置 SHALL 以只读方式映射,`zqyy_app` 不存储 ETL 数据的副本
5. THE FDW 配置文件 SHALL 存放在 `db/fdw/` 目录下
### 需求 9测试数据库镜像
**用户故事:** 作为开发者,我希望有与生产结构完全一致的测试数据库,以便在不影响生产数据的情况下进行开发和测试。
#### 验收标准
1. THE 数据库迁移 SHALL 创建 `test_etl_feiqiu` 数据库,其 schema 结构与 `etl_feiqiu` 完全一致
2. THE 数据库迁移 SHALL 创建 `test_zqyy_app` 数据库,其 schema 结构与 `zqyy_app` 完全一致
3. WHEN 测试数据库创建完成后THE 迁移脚本 SHALL 提供从现有 `LLZQ-test` 数据库迁移测试数据到新结构的脚本
4. WHEN 生产数据库 schema 发生变更时THE 测试数据库 SHALL 同步应用相同的迁移脚本以保持结构一致
### 需求 10.kiro 配置迁移与 Steering 更新
**用户故事:** 作为开发者,我希望 Kiro IDE 的配置和 steering 文件适配 Monorepo 结构,以便 AI 辅助开发在新仓库中正常工作。
#### 验收标准
1. WHEN .kiro 迁移执行时THE 迁移脚本 SHALL 将现有 `.kiro/steering/` 文件复制到 Monorepo 的 `.kiro/steering/`
2. WHEN .kiro 迁移完成后THE Steering 文件 SHALL 更新所有路径引用以反映 Monorepo 目录结构
3. WHEN .kiro 迁移完成后THE Steering 文件 SHALL 更新 `product.md``tech.md``structure.md` 为 Monorepo 视角的内容
### 需求 11FastAPI 后端骨架
**用户故事:** 作为后端开发者,我希望有 FastAPI 项目骨架,以便快速开始小程序后端 API 的开发。
#### 验收标准
1. WHEN 后端骨架创建时THE Scaffold SHALL 在 `apps/backend/` 下生成 FastAPI 项目结构,包含入口文件、路由目录、中间件目录、配置文件
2. THE 后端骨架 SHALL 配置 OpenAPI 文档自动生成
3. THE 后端骨架 SHALL 配置数据库连接模块,支持连接 `zqyy_app` 数据库
4. THE 后端骨架 SHALL 包含独立的 `pyproject.toml`,声明 FastAPI 及相关依赖
### 需求 12共享包基础结构
**用户故事:** 作为开发者,我希望有统一的共享包存放跨项目复用的工具代码,以便避免代码重复。
#### 验收标准
1. WHEN 共享包创建时THE Scaffold SHALL 在 `packages/shared/` 下生成 Python 包结构,包含 `__init__.py``pyproject.toml`
2. THE 共享包 SHALL 提取并包含以下通用工具模块字段枚举定义、金额精度处理工具CNYnumeric(2))、时间处理工具
3. WHEN ETL 或后端项目引用共享包时THE uv_Workspace SHALL 通过 workspace 路径依赖解析 `packages/shared`
### 需求 13多门店数据隔离
**用户故事:** 作为系统架构师,我希望在同一数据库内通过 RLS 实现多门店数据隔离,以便未来扩展到多门店场景。
#### 验收标准
1. THE 数据库设计 SHALL 在所有业务表中包含 `site_id` 字段标识门店归属
2. WHEN RLS 策略启用时THE 数据库 SHALL 根据当前会话的 `site_id` 参数自动过滤查询结果,仅返回该门店的数据
3. WHEN 每个门店运行 ETL 时THE ETL_Pipeline SHALL 作为独立进程执行,使用该门店的 `site_id` 标识数据
### 需求 14基础设施配置管理
**用户故事:** 作为运维人员,我希望基础设施配置纳入版本控制,以便环境配置可追溯、可复现。
### 需求15避免影响kiro性能完成Monorepo后根据文件和目录结构。编辑.kiroignore
验收标准:完善
#### 验收标准
1. THE Scaffold SHALL 在 `infra/` 下创建 `jump_proxy/``tailscale/``firewall/` 子目录
2. THE infra 目录 SHALL 纳入 Git 版本控制
3. IF infra 目录中包含敏感配置文件THEN THE `.gitignore` SHALL 排除这些敏感文件,同时保留非敏感的配置模板

View File

@@ -0,0 +1,215 @@
# 实施计划Monorepo 迁移
## 概述
将现有 ETL 仓库迁移为 Monorepo 单体仓库,分 7 个阶段执行。每个阶段包含具体的代码/文件操作任务,按依赖顺序排列。
## 任务
- [x] 1. Monorepo 骨架搭建
- [x] 1.1 在 `C:\NeoZQYY\` 创建完整目录结构
- 创建所有一级目录:`apps/``gui/``packages/``db/``docs/``infra/``scripts/``samples/``tests/``tmp/``.kiro/`
- 创建 `apps/` 子目录:`etl/pipelines/feiqiu/``backend/``miniprogram/``admin-web/`
- 创建 `db/` 子目录:`etl_feiqiu/schemas/``etl_feiqiu/migrations/``etl_feiqiu/seeds/``zqyy_app/schemas/``zqyy_app/migrations/``zqyy_app/seeds/``fdw/`
- 创建 `docs/` 子目录:`prd/``contracts/openapi/``contracts/schemas/``contracts/data_dictionary/``permission_matrix/``architecture/``database/``h5_ui/``ops/``audit/``roadmap/`
- 创建 `infra/` 子目录:`jump_proxy/``tailscale/``firewall/`
- _Requirements: 1.1, 1.2, 1.3, 1.4, 14.1_
- [x] 1.2 生成所有一级目录的 README.md
- 每个 README 包含作用说明、内部结构描述、Roadmap 段落
- 一级目录列表:`apps/``gui/``packages/``db/``docs/``infra/``scripts/``samples/``tests/`
- `apps/etl/README.md` 的 Roadmap 记录未来 sdk/connectors 拆分计划
- `packages/README.md` 的 Roadmap 记录 etl_sdk、authz、data_contracts 候选
- `db/README.md` 的 Roadmap 记录 FDW 演进计划
- _Requirements: 1.5, 1.6_
- [x] 1.3 编写 README 结构完整性属性测试
- **Property 1: README.md 结构完整性**
- **Validates: Requirements 1.5**
- [x] 1.4 初始化 Git 仓库并生成版本控制配置
-`C:\NeoZQYY\` 执行 `git init`
- 生成 `.gitignore`:排除 `tmp/``__pycache__/``.env``*.pyc``.hypothesis/``.pytest_cache/``logs/``node_modules/`、虚拟环境目录、`infra/` 下的敏感文件
- 生成 `.kiroignore`
- _Requirements: 2.1, 2.2, 2.3, 14.2, 14.3_
- [x] 1.5 配置 pyproject.toml 和 uv workspace
- 生成根 `pyproject.toml`,声明 workspace 成员:`apps/etl/pipelines/feiqiu``apps/backend``packages/shared``gui`
- 为每个 Python 子项目生成独立 `pyproject.toml`
- _Requirements: 3.1, 3.2_
- [x] 1.6 编写 Python 子项目配置完整性属性测试
- **Property 2: Python 子项目配置完整性**
- **Validates: Requirements 3.2**
- [x] 1.7 生成环境配置模板
- 生成根 `.env.template`包含公共配置项模板DB_HOST、DB_PORT、TIMEZONE 等)
- _Requirements: 4.1_
- [x] 2. 检查点 - 骨架验证
- 确保所有目录和文件已创建ask the user if questions arise.
- [x] 3. ETL 项目平移
- [x] 3.1 复制 ETL 业务代码到 Monorepo
-`C:\ZQYY\FQ-ETL``api/``cli/``config/``loaders/``models/``orchestration/``scd/``tasks/``utils/``quality/` 复制到 `apps/etl/pipelines/feiqiu/`
-`tests/` 复制到 `apps/etl/pipelines/feiqiu/tests/`
-`requirements.txt``pytest.ini``run_etl.bat``run_etl.sh` 复制到 `apps/etl/pipelines/feiqiu/`
- _Requirements: 5.1, 5.3_
- [x] 3.2 迁移数据库文件到 db/etl_feiqiu/
-`database/schema_*.sql` 复制到 `db/etl_feiqiu/schemas/`
-`database/migrations/` 复制到 `db/etl_feiqiu/migrations/`
-`database/seed_*.sql` 复制到 `db/etl_feiqiu/seeds/`
-`database/connection.py``database/operations.py``database/base.py` 保留在 ETL 内部(`apps/etl/pipelines/feiqiu/database/`
- _Requirements: 5.2_
- [x] 3.3 迁移 GUI 到顶层
-`C:\ZQYY\FQ-ETL\gui/` 复制到 `C:\NeoZQYY\gui/`
- 生成 `gui/pyproject.toml`,声明 PySide6 依赖
- _Requirements: 5.6_
- [x] 3.4 调整 ETL 的 pyproject.toml 和 pytest.ini
- 更新 `apps/etl/pipelines/feiqiu/pyproject.toml`,从 `requirements.txt` 提取依赖
- 更新 `apps/etl/pipelines/feiqiu/pytest.ini`,设置 `pythonpath = .`
- _Requirements: 5.4, 5.5_
- [x] 3.5 编写文件迁移完整性属性测试
- **Property 5: 文件迁移完整性**
- **Validates: Requirements 5.1, 5.2, 5.3**
- [x] 4. 检查点 - ETL 平移验证
-`apps/etl/pipelines/feiqiu/` 下运行 `pytest tests/unit`,确保所有单元测试通过
- Ensure all tests pass, ask the user if questions arise.
- [x] 5. 小程序前端平移
- [x] 5.1 复制小程序项目到 Monorepo
-`C:\ZQYY\XCX\`(除 Prototype 目录)复制到 `apps/miniprogram/`
-`C:\ZQYY\XCX\Prototype\` 复制到 `docs/h5_ui/`
- 生成 `apps/miniprogram/README.md`
- _Requirements: 6.1, 6.2, 6.3_
- [x] 6. 数据库 Schema 重组
- [x] 6.1 编写 etl_feiqiu 六层 Schema DDL
- 创建 `db/etl_feiqiu/schemas/meta.sql`:从现有 `etl_admin` schema 迁移调度、游标、运行记录表
- 创建 `db/etl_feiqiu/schemas/ods.sql`:从现有 `billiards_ods` 迁移所有表定义schema 名改为 `ods`
- 创建 `db/etl_feiqiu/schemas/dwd.sql`:从现有 `billiards_dwd` 迁移,保留 main+EX 拆分
- 创建 `db/etl_feiqiu/schemas/core.sql`:设计统一维度/事实最小字段集表
- 创建 `db/etl_feiqiu/schemas/dws.sql`:从现有 `billiards_dws` 迁移汇总表
- 创建 `db/etl_feiqiu/schemas/app.sql`:创建面向外部的视图 + RLS 策略(以 `site_id` 隔离)
- _Requirements: 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8_
- [x] 6.2 编写 Schema 表定义迁移完整性属性测试
- **Property 6: Schema 表定义迁移完整性**
- **Validates: Requirements 7.3, 7.6**
- [x] 6.3 编写 Core schema 最小字段集属性测试
- **Property 7: Core schema 最小字段集**
- **Validates: Requirements 7.5**
- [x] 6.4 编写 zqyy_app 数据库 Schema DDL
- 创建 `db/zqyy_app/schemas/init.sql`:用户表、角色表、权限表、用户角色关联表、任务表、审批表
- 所有业务表包含 `site_id` 字段
- _Requirements: 8.1, 8.2, 13.1_
- [x] 6.5 编写 FDW 映射配置
- 创建 `db/fdw/setup_fdw.sql`CREATE SERVER、CREATE USER MAPPING只读角色、IMPORT FOREIGN SCHEMA
- _Requirements: 8.3, 8.4, 8.5_
- [x] 6.6 编写业务表 site_id 存在性属性测试
- **Property 10: 业务表 site_id 字段存在性**
- **Validates: Requirements 13.1**
- [x] 6.7 编写测试数据库创建脚本
- 创建 `db/etl_feiqiu/scripts/create_test_db.sql`:创建 `test_etl_feiqiu`,复用生产 DDL
- 创建 `db/zqyy_app/scripts/create_test_db.sql`:创建 `test_zqyy_app`,复用生产 DDL
- 创建 `db/scripts/migrate_test_data.sql`:从 `LLZQ-test` 迁移测试数据的脚本
- _Requirements: 9.1, 9.2, 9.3_
- [x] 6.8 编写测试数据库结构一致性属性测试
- **Property 8: 测试数据库结构一致性**
- **Validates: Requirements 9.1, 9.2**
- [x] 7. 检查点 - 数据库 Schema 验证
- 确保所有 DDL 文件语法正确ask the user if questions arise.
- [ ] 8. .kiro 迁移与 Steering 更新
- [-] 8.1 复制 .kiro/steering/ 到 Monorepo
-`C:\ZQYY\FQ-ETL\.kiro\steering\` 所有文件复制到 `C:\NeoZQYY\.kiro\steering\`
-`C:\ZQYY\FQ-ETL\.kiro\specs\` 复制到 `C:\NeoZQYY\.kiro\specs\`(包含本 spec
- _Requirements: 10.1_
- [~] 8.2 更新 Steering 文件为 Monorepo 视角
- 更新 `product.md`:从单一 ETL 扩展为 Monorepo 全局视角ETL + 后端 + 小程序 + GUI
- 更新 `tech.md`:新增 FastAPI、uv workspace、Donut+TDesign 技术栈
- 更新 `structure-lite.md`:反映 Monorepo 目录结构和模块边界
- 更新所有 steering 文件中的路径引用,移除旧仓库路径(`FQ-ETL``C:\ZQYY\FQ-ETL`
- _Requirements: 10.2, 10.3_
- [~] 8.3 编写 Steering 文件路径更新属性测试
- **Property 9: Steering 文件路径更新**
- **Validates: Requirements 10.2**
- [ ] 9. FastAPI 后端骨架
- [~] 9.1 创建 FastAPI 项目结构
- 创建 `apps/backend/app/__init__.py``main.py``config.py``database.py`
- 创建 `apps/backend/app/routers/__init__.py`
- 创建 `apps/backend/app/middleware/__init__.py`
- 创建 `apps/backend/app/schemas/__init__.py`
- 创建 `apps/backend/tests/__init__.py`
- `main.py` 中配置 FastAPI 实例,启用 OpenAPI 文档自动生成
- `database.py` 中配置 `zqyy_app` 数据库连接
- _Requirements: 11.1, 11.2, 11.3_
- [~] 9.2 生成 apps/backend/pyproject.toml
- 声明 FastAPI、uvicorn、psycopg2-binary、neozqyy-shared 等依赖
- 配置 uv workspace 源引用 `neozqyy-shared`
- _Requirements: 11.4_
- [~] 9.3 生成 apps/backend/README.md
- 包含作用说明、项目结构、启动方式、Roadmap
- _Requirements: 1.5_
- [ ] 10. 共享包搭建
- [~] 10.1 创建 packages/shared 包结构
- 创建 `packages/shared/src/neozqyy_shared/__init__.py`
- 创建 `packages/shared/src/neozqyy_shared/enums.py`:字段枚举定义(从 ETL models/ 提取通用枚举)
- 创建 `packages/shared/src/neozqyy_shared/money.py`金额精度工具Decimal + ROUND_HALF_UPscale=2
- 创建 `packages/shared/src/neozqyy_shared/datetime_utils.py`:时区转换、日期范围计算
- 创建 `packages/shared/tests/__init__.py`
- _Requirements: 12.1, 12.2_
- [~] 10.2 生成 packages/shared/pyproject.toml
- 声明包名 `neozqyy-shared`最小依赖python-dateutil、tzdata
- _Requirements: 12.3_
- [~] 10.3 编写配置优先级属性测试
- **Property 3: 配置优先级 - .env.local 覆盖**
- **Validates: Requirements 4.3**
- [~] 10.4 编写必需配置缺失检测属性测试
- **Property 4: 必需配置缺失检测**
- **Validates: Requirements 4.4**
- [ ] 11. 检查点 - 全局验证
- 验证 uv workspace 依赖解析:在根目录运行 `uv sync`
- 验证 ETL 单元测试:在 `apps/etl/pipelines/feiqiu/` 下运行 `pytest tests/unit`
- Ensure all tests pass, ask the user if questions arise.
- [ ] 12. RLS 与多门店隔离验证
- [~] 12.1 编写 RLS 按 site_id 隔离属性测试
- **Property 11: RLS 按 site_id 隔离**
- **Validates: Requirements 13.2**
- 需要集成测试环境test_etl_feiqiu 数据库)
- [ ] 13. 最终检查点
- 确保所有文件已创建、所有 README 已编写、所有 DDL 语法正确
- Ensure all tests pass, ask the user if questions arise.
## 备注
- 标记 `*` 的任务为可选测试任务,可跳过以加速 MVP
- 每个任务引用具体需求编号,确保可追溯
- 检查点确保增量验证,避免问题累积
- 属性测试验证通用正确性,单元测试验证具体边界情况
- 文件复制操作需要用户在终端手动执行涉及跨目录操作Kiro 负责生成目标文件内容