# apps/backend — FastAPI 后端

为微信小程序和管理后台提供 RESTful API，连接 `zqyy_app` 业务数据库，直连 `etl_feiqiu` ETL 库只读访问 `app.v_*` RLS 视图。

## 技术栈

- Python 3.10+ / FastAPI 0.115+ / Uvicorn
- PostgreSQL（psycopg2 直连，纯 SQL，无 ORM）
- JWT 认证（python-jose + bcrypt）
- WebSocket（实时日志推送）
- neozqyy-shared（共享枚举、金额精度、时间工具）

## 目录结构

```
apps/backend/
├── app/
│   ├── main.py              # FastAPI 入口（lifespan 管理 + 路由注册）
│   ├── config.py            # 配置加载（根 .env < .env.local < 环境变量）
│   ├── database.py          # 数据库连接（zqyy_app 读写 + etl_feiqiu 只读 RLS）
│   ├── auth/                # 认证模块
│   │   ├── dependencies.py  # FastAPI 依赖注入（CurrentUser）
│   │   └── jwt.py           # JWT 签发/验证/密码哈希
│   ├── routers/             # 18 个路由模块（详见 API 参考）
│   ├── schemas/             # Pydantic 请求/响应模型
│   ├── services/            # 业务逻辑层
│   ├── middleware/          # 中间件（ResponseWrapper 全局响应包装）
│   ├── ai/                  # AI 模块（DashScope Application API + 8 个应用）
│   │   ├── config.py            # AIConfig — 环境变量加载（DASHSCOPE_*）
│   │   ├── dashscope_client.py  # DashScope Application API 统一封装
│   │   ├── dispatcher.py        # AIDispatcher — 事件调度 + 调用链编排
│   │   ├── circuit_breaker.py   # 熔断器（按 app_id 独立）
│   │   ├── rate_limiter.py      # 限流器（用户/门店维度）
│   │   ├── budget_tracker.py    # Token 预算追踪（日/月限额）
│   │   ├── run_log_service.py   # AI 运行日志 CRUD
│   │   ├── exceptions.py        # 异常层级（DashScopeError 基类）
│   │   ├── cache_service.py     # AI 缓存读写（biz.ai_cache + status 状态控制）
│   │   ├── conversation_service.py  # 对话管理（session_id 双轨）
│   │   ├── schemas.py           # AI 相关 Schema（SSEEvent 等）
│   │   ├── apps/                # 8 个 AI 应用（app1_chat ~ app8_consolidation）
│   │   ├── prompts/             # Prompt 模板（app2/app8 独立模板）
│   │   └── data_fetchers/       # 共享数据获取层（NS2 新增）
│   │       ├── member_data.py   # 客户消费/会员卡/备注数据
│   │       ├── assistant_data.py # 助教信息/服务记录
│   │       └── page_context.py  # 页面上下文文本化（10 种入口）
│   └── ws/                  # WebSocket（实时日志）
├── tests/                   # 后端测试
├── pyproject.toml           # 依赖声明
└── README.md
```

## 启动

```bash
# 安装依赖（在 monorepo 根目录）
uv sync --all-packages

# 启动开发服务器
cd apps/backend
uv run uvicorn app.main:app --host 127.0.0.1 --port 8000 --reload
```

API 文档自动生成于：
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc

## 架构概览

### 全局响应包装与 Schema 规范（RNS1.0）

后端通过 ASGI 中间件和 Pydantic 基类实现统一的响应格式：

- `ResponseWrapperMiddleware`（`middleware/response_wrapper.py`）：所有 JSON 成功响应（2xx）自动包装为 `{ "code": 0, "data": <原始响应体> }`；SSE（`text/event-stream`）和非 JSON 响应透传不包装
- `http_exception_handler` / `unhandled_exception_handler`：异常统一格式化为 `{ "code": <HTTP状态码>, "message": <错误详情> }`，未捕获异常返回 500 并记录完整堆栈
- `CamelModel`（`schemas/base.py`）：所有小程序 API 响应 schema 的基类，`alias_generator=to_camel` 自动将 snake_case 字段转为 camelCase 输出，同时通过 `populate_by_name=True` 接受两种格式输入

### 双数据库连接

| 连接 | 数据库 | 用途 | 函数 |
|------|--------|------|------|
| 业务读写 | `zqyy_app` | 用户、队列、调度、执行日志 | `get_connection()` |
| ETL 只读 | `etl_feiqiu` | 数据查看器、游标监控 | `get_etl_readonly_connection(site_id)` |

ETL 只读连接自动设置 `default_transaction_read_only = on` 和 RLS `app.current_site_id`，确保门店数据隔离。

### 认证体系

后端支持两套认证：

1. 管理后台认证（`/api/auth/*`）：用户名 + 密码 → JWT
2. 小程序认证（`/api/xcx-auth/*`）：微信 code → openid → JWT
3. 租户管理后台认证（`/api/tenant/auth/*`）：用户名 + 密码 → JWT（`aud=tenant-admin`，与小程序完全隔离）

JWT 令牌分两种：
- 完整令牌：已审批用户，包含 `user_id` + `site_id` + `roles`
- 受限令牌（`limited=True`）：待审批用户，仅允许访问申请相关端点

依赖注入：
- `get_current_user`：要求完整令牌
- `get_current_user_or_limited`：允许受限令牌

### 配置加载

优先级（低 → 高）：根 `.env` → 应用 `.env.local` → 环境变量

关键配置项：
- `DB_HOST` / `DB_PORT` / `DB_USER` / `DB_PASSWORD` / `APP_DB_NAME` — 业务数据库
- `ETL_DB_*` — ETL 数据库（缺省复用业务库参数）
- `JWT_SECRET_KEY` — JWT 签名密钥（生产必须设置）
- `CORS_ORIGINS` — 允许的跨域来源
- `ETL_PROJECT_PATH` — ETL CLI 工作目录
- `WX_APPID` / `WX_SECRET` — 微信小程序配置
- `WX_DEV_MODE` — 开发模式（启用 mock 登录）
- `BUSINESS_DAY_START_HOUR` — 营业日分割点（默认 8 点）

### 后台服务

应用启动时通过 lifespan 拉起两个后台服务：
- `TaskQueue`：任务执行队列（从 `task_queue` 表消费，按 site_id 隔离）
- `Scheduler`：定时调度器（从 `scheduled_tasks` 表读取配置，自动入队）

同时注册触发器 job handler：
- `task_generator`：任务生成器（每日凌晨 4:00）
- `task_expiry_check`：任务过期检查（每小时）
- `recall_completion_check`：召回完成检测（ETL 数据更新后）
- `note_reclassify_backfill`：备注重分类回填（召回完成后）

## 路由总览

| 前缀 | 模块 | 说明 | 认证 |
|------|------|------|------|
| `/api/auth` | `auth.py` | 管理后台登录/刷新令牌 | 无 |
| `/api/xcx-auth` | `xcx_auth.py` | 小程序微信登录/申请/状态/店铺切换 | 部分 |
| `/api/xcx/tasks` | `xcx_tasks.py` | 小程序任务列表/详情/置顶/放弃/恢复 | JWT |
| `/api/xcx/notes` | `xcx_notes.py` | 小程序备注 CRUD | JWT |
| `/api/xcx/performance` | `xcx_performance.py` | 小程序绩效概览/明细 | JWT |
| `/api/xcx/config` | `xcx_config.py` | 小程序配置（项目类型筛选器等） | JWT |
| `/api/xcx/board` | `xcx_board.py` | 小程序三看板（助教/客户/财务） | JWT |
| `/api/admin/applications` | `admin_applications.py` | 管理端申请审核 | JWT |
| `/api/business-day` | `business_day.py` | 营业日配置查询 | JWT |
| `/api/tasks` | `tasks.py` | 任务注册表/Flow 定义/配置验证 | JWT |
| `/api/execution` | `execution.py` | 任务执行/队列管理/历史/日志 | JWT |
| `/api/schedules` | `schedules.py` | 调度任务 CRUD + 启停 | JWT |
| `/api/db` | `db_viewer.py` | ETL 数据库只读查看器 | JWT |
| `/api/etl-status` | `etl_status.py` | ETL 游标/执行记录监控 | JWT |
| `/api/env-config` | `env_config.py` | 环境变量查看/编辑 | JWT |
| `/api/xcx-test` | `xcx_test.py` | MVP 全链路验证 | 无 |
| `/api/wx-callback` | `wx_callback.py` | 微信消息推送回调 | 签名验证 |
| `/api/retention-clue` | `member_retention_clue.py` | 维客线索 CRUD | JWT |
| `/api/tenant/auth` | `tenant_auth.py` | 租户管理员登录/刷新令牌 | 无 |
| `/api/tenant` | `tenant_users.py` | 租户用户审核/管理（申请列表/关联建议/审核/用户编辑/绑定） | 租户JWT |
| `/api/tenant/excel` | `tenant_excel.py` | 租户 Excel 上传/校验/冲突/确认/记录/模板下载 | 租户JWT |
| `/api/tenant` | `tenant_clues.py` | 租户维客线索管理（客户搜索/线索CRUD/隐藏显示） | 租户JWT |
| `/api/tenant/site-admins` | `tenant_site_admins.py` | 店铺管理员 CRUD（列表/创建/编辑/删除/重置密码，仅 tenant_admin） | 租户JWT |
| `/api/admin` | `admin_tenant_admins.py` | 管理端租户管理员 CRUD（列表/创建/编辑/删除/重置密码） | JWT+管理员 |
| `/api/admin` | `admin_registry.py` | 注册体系管理（租户列表/店铺列表/简写ID/店铺同步） | JWT+管理员 |
| `/api/admin/ai` | `admin_ai.py` | AI 监控后台（Dashboard/调度状态/调用明细/缓存/预算/批量/告警，13 端点） | JWT+管理员 |
| `/api/admin/dev-trace` | `admin_dev_trace.py` | 开发调试全链路日志（日期/请求列表/详情/清理/设置/覆盖率，8 端点） | JWT+管理员 |
| `/api/admin/task-engine` | `admin_task_engine.py` | P18 任务引擎运营看板（转移日志分页+历史、待审核任务分页+重新分配+关闭、参数管理 CRUD，9 端点） | JWT+管理员 |
| `/api/xcx/chat` | `xcx_chat.py` | 小程序 CHAT 对话/消息/发送/SSE 流式 | JWT |
| `/api/admin/db-health` | `admin_db_health.py` | 数据库健康监控（4 库连接池/大小/慢查询） | JWT |
| `/api/admin/triggers` | `admin_triggers.py` | 触发器统一视图（biz/ai/etl 三源聚合） | JWT |
| `/api/trigger-jobs` | `trigger_jobs.py` | 触发器任务管理（列表/详情/PATCH 配置编辑） | JWT |
| `/api/ops` | `ops_panel.py` | 运维面板（服务启停/Git/系统信息） | 无 |
| `/ws/logs` | `ws/logs.py` | WebSocket 实时日志推送 | — |
| `/health` | `main.py` | 健康检查 | 无 |

> 详细 API 端点说明见 [`docs/API-REFERENCE.md`](docs/API-REFERENCE.md)

## 服务层

| 模块 | 职责 |
|------|------|
| `wechat.py` | 微信 `code2session` 接口调用 |
| `matching.py` | 用户申请时的人员匹配（助教/员工） |
| `application.py` | 用户入驻申请的创建/审批/拒绝 |
| `role.py` | 用户权限查询/门店角色检查 |
| `scheduler.py` | 定时调度引擎（cron 解析 + next_run 计算） |
| `task_executor.py` | ETL CLI 子进程执行 + 日志广播 |
| `task_queue.py` | 任务队列管理（入队/消费/重排） |
| `task_registry.py` | ETL 任务/Flow/DWD 表静态注册表 |
| `cli_builder.py` | ETL CLI 命令构建器 |
| `task_generator.py` | 任务生成器（四级漏斗 + 保底 relationship_building，独立连接） |
| `task_manager.py` | 任务管理（置顶/放弃/状态变更） |
| `task_expiry.py` | 任务过期检查与处理 |
| `task_manager.py` | 任务管理（CRUD + 列表扩展 + 详情） |
| `performance_service.py` | 绩效概览 + 明细（ETL 直连查询） |
| `note_service.py` | 备注服务（CRUD + 星星评分） |
| `fdw_queries.py` | ETL 查询集中封装（直连 ETL 库 + 门店隔离 RLS），含区域日粒度查询（`get_finance_overview_area`/`get_finance_revenue_area`）和缓存读写（`get_finance_board_cache`/`set_finance_board_cache`） |
| `note_reclassifier.py` | 备注重分类（召回完成后回填） |
| `recall_detector.py` | 召回完成检测（ETL 数据更新触发） |
| `trigger_scheduler.py` | 触发器调度器（cron/interval/event） |
| `chat_service.py` | CHAT 模块业务逻辑（对话管理/消息持久化/referenceCard） |
| `ai/admin_service.py` | AI 监控后台聚合服务（Dashboard 统计/批量执行/告警管理） |
| `ai/cleanup_service.py` | AI 数据清理服务（90 天保留 + 缓存上限 20000/App） |
| `admin_task_engine.py` | P18 任务引擎运营看板路由（转移日志/待审核任务/参数管理，9 端点） |

## AI 模块（NS2 Prompt 细化）

8 个千问 AI 应用，通过百炼平台调用 Qwen3.5-Plus 模型。分三层架构：

```
应用层（apps/app1_chat ~ app8_consolidation）
  ↓ 调用
数据获取层（data_fetchers/）          ← NS2 新增
  ↓ 查询
基础设施层（database.py / cache_service.py / dashscope_client.py）
```

### 数据获取层（`app/ai/data_fetchers/`）

NS2 新增的共享模块，封装 FDW 查询逻辑，供多个应用复用：

| 函数 | 数据来源 | 消费方 |
|------|---------|--------|
| `fetch_member_consumption_data()` | ETL FDW 视图（结算/商品/会员卡/到店） | App3/6/7 |
| `fetch_member_notes()` | `biz.notes` | App4/6 |
| `fetch_assistant_info()` | ETL FDW 视图（助教维度/月度汇总） | App4/5 |
| `fetch_service_history()` | ETL FDW 视图（服务日志/亲密度） | App4/5 |
| `build_page_text()` | 多数据源（按 contextType 路由） | App1 |

关键约束：
- 金额口径使用 `items_sum`，禁止 `consume_money`
- 所有 FDW 查询通过 `SET LOCAL app.current_site_id` 实现 RLS 隔离
- 部分数据获取失败不阻断 Prompt 生成（错误降级）

### 页面上下文（App1）

App1 通用对话支持 10 种页面入口，通过 `contextType` 路由到对应的文本化函数：

`task-detail` / `customer-detail` / `coach-detail` / `task-list` / `customer-service-records` / `board-finance` / `board-customer` / `board-coach` / `performance` / `my-profile`

每种入口自动获取页面数据并格式化为结构化中文文本，注入 system prompt。

## 依赖

```
fastapi>=0.115
uvicorn[standard]>=0.34
psycopg2-binary>=2.9
python-dotenv>=1.0
python-jose[cryptography]>=3.3
bcrypt>=4.0
psutil>=5.9
neozqyy-shared（workspace 引用）
```

## Roadmap

- [ ] RBAC 权限中间件（基于 `auth.role_permissions` 表）
- [x] 全局响应包装中间件 + CamelModel 基类（RNS1.0）
- [ ] 数据看板 API（助教业绩、财务日报、客户分析）
- [ ] 任务审批流 API
- [ ] 消息推送（微信模板消息/订阅消息）
- [ ] API 限流与审计日志
