feat: P1-P3 全栈集成 — 数据库基础 + DWS 扩展 + 小程序鉴权 + 工程化体系

## P1 数据库基础
- zqyy_app: 创建 auth/biz schema、FDW 连接 etl_feiqiu
- etl_feiqiu: 创建 app schema RLS 视图、商品库存预警表
- 清理 assistant_abolish 残留数据

## P2 ETL/DWS 扩展
- 新增 DWS 助教订单贡献度表 (dws.assistant_order_contribution)
- 新增 assistant_order_contribution_task 任务及 RLS 视图
- member_consumption 增加充值字段、assistant_daily 增加处罚字段
- 更新 ODS/DWD/DWS 任务文档及业务规则文档
- 更新 consistency_checker、flow_runner、task_registry 等核心模块

## P3 小程序鉴权系统
- 新增 xcx_auth 路由/schema(微信登录 + JWT)
- 新增 wechat/role/matching/application 服务层
- zqyy_app 鉴权表迁移 + 角色权限种子数据
- auth/dependencies.py 支持小程序 JWT 鉴权

## 文档与审计
- 新增 DOCUMENTATION-MAP 文档导航
- 新增 7 份 BD_Manual 数据库变更文档
- 更新 DDL 基线快照(etl_feiqiu 6 schema + zqyy_app auth)
- 新增全栈集成审计记录、部署检查清单更新
- 新增 BACKLOG 路线图、FDW→Core 迁移计划

## Kiro 工程化
- 新增 5 个 Spec(P1/P2/P3/全栈集成/核心业务)
- 新增审计自动化脚本(agent_on_stop/build_audit_context/compliance_prescan)
- 新增 6 个 Hook(合规检查/会话日志/提交审计等)
- 新增 doc-map steering 文件

## 运维与测试
- 新增 ops 脚本:迁移验证/API 健康检查/ETL 监控/集成报告
- 新增属性测试:test_dws_contribution / test_auth_system
- 清理过期 export 报告文件
- 更新 .gitignore 排除规则
This commit is contained in:
Neo
2026-02-26 08:03:53 +08:00
parent fafc95e64c
commit b25308c3f4
224 changed files with 17660 additions and 32198 deletions

View File

@@ -0,0 +1,245 @@
"""
服务器环境初始化脚本:删除 skip-worktree 排除的文件/目录 + 创建 export 目录树。
在服务器上 git clone + setup-server-git.py 之后运行。
1. 删除已被 skip-worktree 标记的目录和散文件(释放磁盘空间)
2. 创建完整的 export/ 目录树ETL/SYSTEM/BACKEND 三大类)
用法:
python scripts/server/init-server-env.py # 初始化 test + prod默认
python scripts/server/init-server-env.py --envs test # 只初始化 test
python scripts/server/init-server-env.py --envs prod # 只初始化 prod
python scripts/server/init-server-env.py --envs test prod
"""
import argparse
import os
import shutil
import sys
from pathlib import Path
# ============================================================================
# 配置
# ============================================================================
SERVER_ROOT = Path(r"D:\NeoZQYY")
ENV_PATHS: dict[str, Path] = {
"test": SERVER_ROOT / "test" / "repo",
"prod": SERVER_ROOT / "prod" / "repo",
}
# skip-worktree 后可安全删除的目录(与 setup-server-git.py DELETABLE_DIRS 一致)
DELETABLE_DIRS = [
"export",
"docs",
"tests",
"samples",
"infra",
".kiro",
".hypothesis",
".pytest_cache",
r"apps\miniprogram",
r"scripts\ops",
r"scripts\audit",
r"scripts\migrate",
]
# 可安全删除的根目录散文件
DELETABLE_FILES = [
"coach-detail-full.png",
"customer-detail-full.png",
"perf-records-current.png",
"white-screen-debug.png",
"NeoZQYY.code-workspace",
"start-admin.bat",
".kiroignore",
]
# export 目录树(所有环境通用)
EXPORT_DIRS = [
r"export\ETL-Connectors\feiqiu\JSON",
r"export\ETL-Connectors\feiqiu\LOGS",
r"export\ETL-Connectors\feiqiu\REPORTS",
r"export\SYSTEM\LOGS",
r"export\SYSTEM\REPORTS\dataflow_analysis",
r"export\SYSTEM\REPORTS\field_audit",
r"export\SYSTEM\REPORTS\full_dataflow_doc",
r"export\SYSTEM\CACHE\api_samples",
r"export\BACKEND\LOGS",
]
# ============================================================================
# 颜色输出Windows 终端支持 ANSI
# ============================================================================
class C:
"""ANSI 颜色码"""
RED = "\033[91m"
GREEN = "\033[92m"
YELLOW = "\033[93m"
CYAN = "\033[96m"
MAGENTA = "\033[95m"
WHITE = "\033[97m"
GRAY = "\033[90m"
RESET = "\033[0m"
def cprint(msg: str, color: str = C.WHITE) -> None:
print(f"{color}{msg}{C.RESET}")
# ============================================================================
# 函数
# ============================================================================
def get_dir_size_mb(path: Path) -> float:
"""递归计算目录大小MB"""
total = 0
try:
for f in path.rglob("*"):
if f.is_file():
total += f.stat().st_size
except OSError:
pass
return round(total / (1024 * 1024), 1)
def get_file_size_mb(path: Path) -> float:
try:
return round(path.stat().st_size / (1024 * 1024), 2)
except OSError:
return 0.0
def remove_skip_worktree_items(repo_path: Path) -> None:
"""删除指定 repo 下已被 skip-worktree 标记的目录和散文件。"""
cprint("\n [删除] 清理 skip-worktree 排除的目录和文件...", C.YELLOW)
freed_mb = 0.0
# 删除目录
for d in DELETABLE_DIRS:
full = repo_path / d
if full.exists() and full.is_dir():
size = get_dir_size_mb(full)
shutil.rmtree(full, ignore_errors=True)
cprint(f" 已删除: {d}/ ({size} MB)", C.RED)
freed_mb += size
else:
cprint(f" 跳过: {d}/ (不存在)", C.GRAY)
# 删除散文件
for f in DELETABLE_FILES:
full = repo_path / f
if full.exists() and full.is_file():
size = get_file_size_mb(full)
full.unlink()
cprint(f" 已删除: {f} ({size} MB)", C.RED)
freed_mb += size
# 删除根目录下所有 .png 文件
for png in repo_path.glob("*.png"):
if png.is_file():
size = get_file_size_mb(png)
png.unlink()
cprint(f" 已删除: {png.name} ({size} MB)", C.RED)
freed_mb += size
cprint(f" 共释放: {freed_mb:.1f} MB", C.GREEN)
def create_export_tree(repo_path: Path) -> None:
"""在指定 repo 下创建完整的 export 目录树。"""
cprint("\n [创建] 初始化 export 目录树...", C.YELLOW)
for d in EXPORT_DIRS:
full = repo_path / d
if not full.exists():
full.mkdir(parents=True, exist_ok=True)
cprint(f" 已创建: {d}/", C.CYAN)
else:
cprint(f" 已存在: {d}/", C.GRAY)
def test_git_setup(repo_path: Path) -> bool:
"""检查 setup-server-git.py 是否已运行。"""
exclude_file = repo_path / ".git" / "info" / "exclude"
if not exclude_file.exists():
return False
try:
content = exclude_file.read_text(encoding="utf-8", errors="ignore")
return "server-exclude" in content
except OSError:
return False
# ============================================================================
# 主流程
# ============================================================================
def main() -> None:
parser = argparse.ArgumentParser(description="NeoZQYY 服务器环境初始化")
parser.add_argument(
"--envs",
nargs="+",
default=["test", "prod"],
choices=["test", "prod"],
help="要初始化的环境列表(默认: test prod",
)
args = parser.parse_args()
# Windows 终端启用 ANSI 颜色
if sys.platform == "win32":
os.system("") # 触发 ANSI 支持
cprint("=" * 44, C.WHITE)
cprint(" NeoZQYY 服务器环境初始化", C.WHITE)
cprint(f" 目标环境: {', '.join(args.envs)}", C.WHITE)
cprint("=" * 44, C.WHITE)
for env in args.envs:
repo_path = ENV_PATHS.get(env)
if not repo_path:
cprint(f"\n[错误] 未知环境: {env}(可选: test, prod", C.RED)
continue
cprint(f"\n{'=' * 10} 环境: {env} {'=' * 10}", C.MAGENTA)
cprint(f" 路径: {repo_path}")
# 检查 repo 是否存在
if not repo_path.exists():
cprint(" [警告] 目录不存在,跳过。请先 git clone。", C.YELLOW)
continue
# 检查 setup-server-git.py 是否已运行
if not test_git_setup(repo_path):
cprint(" [警告] 未检测到 setup-server-git.py 的配置。", C.YELLOW)
cprint(" 建议先运行: python scripts/server/setup-server-git.py", C.YELLOW)
answer = input(" 是否继续删除操作?(y/N) ").strip()
if answer.lower() != "y":
cprint(f" 已跳过 {env} 环境的删除操作。", C.GRAY)
# 仍然创建 export 目录
create_export_tree(repo_path)
continue
# 步骤 1删除排除的文件/目录
remove_skip_worktree_items(repo_path)
# 步骤 2创建 export 目录树
create_export_tree(repo_path)
cprint(f"\n [完成] {env} 环境初始化完毕。", C.GREEN)
cprint("\n" + "=" * 44, C.WHITE)
cprint(" 全部完成。", C.GREEN)
print()
cprint(" 后续步骤:", C.WHITE)
cprint(" 1. 手动创建各环境的 .env 文件(参考 .env.template", C.WHITE)
cprint(" 2. 确认 .env 中的 export 路径指向 repo/export/ 下对应子目录", C.WHITE)
cprint(" 3. 运行 uv sync --all-packages 安装依赖", C.WHITE)
cprint("=" * 44, C.WHITE)
if __name__ == "__main__":
main()