QP Fleet Current Project State Snapshot
Last updated: 2026-05-23T00:19:41.913Z
# QP_CURRENT_STATE.md
> 生成时间:2026-05 | 面向读者:ChatGPT / Codex / Cursor / 新接手开发者
> 这是一份**真实工程现状快照**,不是理想架构文档。
---
## 1. 项目定位
QP Fleet System 是 QuickPath 内部车队运营与财务管理系统。
- 不是单一应用,是"多层协作"的运营+财务体系。
- 当前主线:**V3 财务系统收口 + V3.2 Internal Ops 只读页面**。
- 部署地址:`http://47.77.231.107:4020`
- 服务器路径:`/opt/qp-fleet-system`
- PM2 进程名:`qp-fleet-system`(唯一允许操作的进程)
- 端口:`4020`(同机另有 Etsy Image Tool,端口 4030,**禁止误碰**)
---
## 2. 项目文件结构(真实现状)
```
/opt/qp-fleet-system/
├── server.js # 唯一入口,所有路由和页面都在这里
├── package.json # express / googleapis / xlsx / axios
├── service-account.json # Google API 鉴权(不提交)
├── cache/
│ └── finance/ # Finance cache-first 本地缓存
│ ├── A_overview.json
│ ├── A_Records.json
│ ├── A_Turo_Payouts.json
│ ├── A_management_fee_rules.json
│ ├── Guide-Owner.json
│ ├── Guide-OP-detail.json
│ ├── Finance_Summary_Master.json
│ ├── Finance_Cars_Master.json
│ ├── Finance_Reimbursement_Master.json
│ └── Finance_Batch_Overview.json
├── data/
│ └── datahub/
│ └── DataHub.xlsx # 本地中间数据文件(xlsx)
├── data/
│ └── settlements/ # 结算草稿文件(owner__month.json)
└── docs/ # 项目规则 MD 文档
├── CLAUDE.md # AI 工具入口说明(必须先读)
├── QP_CURRENT_STATUS.md
├── QP_PROJECT_OVERVIEW.md
├── QP_VERSION_TREE.md
├── QP_FINANCE_RULES.md
├── QP_DATAHUB_STRUCTURE.md
├── QP_ECS_MASTER_MIGRATION.md
├── QP_INTERNAL_OPS_PLAN.md
└── QP_SCRAPER_ARCHITECTURE.md
```
> ⚠️ `server.js` 是单体文件,所有路由、HTML 页面渲染、API、中间件都在其中。没有 React/Vue 框架,前端是 server-side rendered HTML + inline JS。
---
## 3. 技术栈
| 层级 | 技术 |
|------|------|
| 后端框架 | Express 5 (Node.js) |
| 认证 | Google Service Account (googleapis) |
| 主数据源(当前) | Google Sheet(两个 Sheet ID) |
| 中间层 | DataHub.xlsx(本地) |
| 缓存层 | `/cache/finance/*.json`(本地 JSON) |
| 前端渲染 | Server-side HTML,inline JS,无构建工具 |
| 包管理 | npm(无 lock file 限制)|
| 进程管理 | PM2 |
---
## 4. 数据源结构与三层关系
### 4.1 数据来源层级(当前真实状态)
```
[Google Sheet - 主数据源]
├── DATA_HUB_SHEET_ID = "1_e5chw2tstso6P7AFQwgHpmLtuR9HQBQXCfnPSAx0a8"
│ ├── A_overview ← 车辆/车主/平台/位置/归属关系
│ ├── A_Records ← 行程分类、费用拆解(辅助,非收入主口径)
│ ├── A_Turo_Payouts ← 正式收入口径 ✅
│ ├── A_management_fee_rules
│ ├── Guide-Owner ← 车主 PayOption / OP 规则
│ ├── Guide-OP-detail ← 各费用类型 OP1/OP2/OP3 处理规则
│ └── Guide-A ← ECS Table UI registry(ECS-Ctrl=yes 才进入)
│
└── DEFAULT_FINANCE_OUTPUT_SHEET_ID = "1eUESU1D6oj8PoXNxRgplITKZrY9xPZ-5adf2Z4kRICE"
├── Finance_Summary_Master
├── Finance_Cars_Master
├── Finance_Reimbursement_Master
└── Finance_Batch_Overview
[DataHub.xlsx - 本地中间层]
路径:/opt/qp-fleet-system/data/datahub/DataHub.xlsx
作用:接住抓取结果、缓存结果、财务中间结果,降低直接读 Sheet 耦合
读取函数:readDataHubTab(tabName)
[cache/finance/*.json - 本地 JSON 缓存]
作用:Finance API cache-first 读取,减少 Google Sheet 调用频率
刷新入口:GET /api/finance-cache-refresh
状态查询:GET /api/finance-cache-status
```
### 4.2 读取优先级(当前已确认)
```
Finance Master API:
local cache (JSON) → [fallback] Google Sheet
ECS Table UI (/ops/tables):
Google Sheet first → [fallback] DataHub.xlsx
ECS Table UI (/ops/table?tab=...):
DataHub.xlsx → [fallback] Google Sheet
原则:本地没有再 fallback;不确定来源时看 dataSourceDiagnostics 字段
```
### 4.3 Google Sheet / DataHub / ECS 三者关系
```
当前阶段:Sheet-Master + ECS Co-Pilot(副驾驶验证期)
Google Sheet ──→ [抓取/同步] ──→ DataHub.xlsx
↓
cache/finance/*.json
↓
Finance API (cache-first)
↓
/finance/* 页面(只读展示)
ECS(当前)= 读取、展示、验证
ECS(未来)= 主数据源(ECS-Master,尚未切换)
```
---
## 5. 当前主线模块(已完成 - Finance V1)
### 5.1 Finance Shell 入口
- 路由:`GET /finance`
- 左侧菜单分组(Finance / Owner / Operations / Tools)+ 可折叠
- iframe 框架,月份/车主选择器,语言切换(en/zh)
### 5.2 已完成页面(Finance V1 收口状态)
| 页面 | 路由 | 状态 |
|------|------|------|
| Dashboard | `/finance` → `dashboard` view | ✅ READY |
| Finance V1 Acceptance | `financeV1Acceptance` view | ✅ READY |
| Owner Detail | `/finance-owner-detail` | ✅ READY |
| Monthly Settlement Report | `/finance-owner-report` | ✅ READY |
| Owner Print | `/finance-owner-print` | ✅ READY |
| Expense Detail Report | `/finance-expense-report-v1` | ✅ READY |
| Payment Tracking | 内嵌 view | ✅ READY |
| Vehicle Anomalies | view | ✅ READY |
| Cache Refresh | `/finance-cache-refresh` | ✅ READY |
| Payout Debug | `/finance-payout-debug` | ✅ DEBUG工具 |
| Trip Income Debug | `/finance-trip-income-debug` | ✅ DEBUG工具 |
| Car Rule Preview | `/finance-car-trip-rule-preview` | ✅ DEBUG工具 |
### 5.3 Finance V1 线上验收状态(2026-05)
```
Owners = 5
Pay To Owners = $17,818.35
Paid/Remaining = $17,455.01 / $363.34
Henry = NEEDS_REVIEW(人工复核,不是系统错误)
Tan/Roy/Quenna/Ning W = READY
monthly-run-status: readyCount=5, missingCount=0, errorCount=0
```
---
## 6. 当前进行中模块(V3.2 Internal Ops)
### 6.1 /ops 入口
- 路由:`GET /ops`
- 内部运营后台,**不对车主开放**
- 当前全部只读,不写回 Google Sheet
### 6.2 V3.2 已落地步骤
| Step | 内容 | 状态 |
|------|------|------|
| Step2 | `/ops` 首页,模块卡片(Overview/Anomalies/Maintenance等)| ✅ |
| Step3 | Ops Overview Snapshot(复用 `/api/finance-dashboard-month`)| ✅ |
| Step4 | Vehicle Anomalies Snapshot(复用 `/api/finance-vehicles-month`)| ✅ |
| Step4 | ECS Table UI:`/ops/tables` + `/ops/table?tab=...` | ✅ |
| Step4.1 | Guide-A TabType 语义(Ctrl/Show)+ Sheet-first 策略 | ✅ |
| Step5 | 单表字段 checkbox 选择 + 搜索框 | ✅ |
| Step6 | Select All/Clear/Default10 + row limit(50/100/200/500) + sticky header | ✅ |
| Step7 | 分页 + 行顺序(Original/Reverse)+ localStorage 视图偏好 | ✅ |
| Step7.1 | 全量数据分页顺序修复(limit 语义改为 page size)| ✅ |
| Step7.2 | localStorage columns 对齐校验 + 越界修正 + Reset Saved View | ✅ |
| Step8.1 | Cleaning Upload Prototype(`/ops/cleaning-upload` + `/api/ops/cleaning-upload` 受控写入) | ✅ |
---
## 7. 核心 API 清单
### Finance 核心 API(cache-first)
```
GET /api/finance-dashboard-month?month=YYYY-MM
GET /api/finance-owner-detail?owner=...&month=...
GET /api/finance-dashboard-master?month=...
GET /api/finance-owner-master?owner=...&month=...
GET /api/finance-monthly-run-status?month=...
GET /api/finance-owner-report-v1-calc?owner=...&month=...
GET /api/finance-owner-cards?month=...
GET /api/finance-vehicles-month?month=...
GET /api/finance-home-dashboard?month=...
```
### Cache 管理 API
```
GET /api/finance-cache-refresh ← 触发缓存刷新(写 JSON 文件)
GET /api/finance-cache-status ← 查询各 tab 缓存状态
POST /api/datahub-xlsx-upload ← 上传新版 DataHub.xlsx
GET /api/datahub-xlsx-status ← 查询 DataHub.xlsx 状态
```
### Debug API
```
GET /api/finance-payout-debug?...
GET /api/finance-trip-income-debug?tripId=...
GET /api/finance-op-compare-debug?owner=...&from=OP1&to=OP3
GET /api/finance-owner-op?owner=...
GET /api/finance-car-trip-rule-preview-note?...
```
### Settlement 草稿 API
```
GET /api/finance-owner-car-settlement-preview?owner=...&month=...
POST /api/finance-settlement-draft-save
GET /api/finance-settlement-draft-load
```
---
## 8. Cache 体系
### 8.1 cache-first 读取函数(server.js 内)
```javascript
loadFinanceCache(tabName) // 读 JSON cache
readDataHubTab(tabName) // 读 DataHub.xlsx(含 fallback Google Sheet)
readSheet(sheetId, tabName) // 直接读 Google Sheet
```
### 8.2 缓存覆盖 Tab 列表
**FINANCE_CACHE_TABS**(来源:DATA_HUB_SHEET_ID)
- A_overview, A_Records, A_Turo_Payouts, A_management_fee_rules
- Guide-Owner, Guide-OP-detail(+ 其他 Guide 表)
**FINANCE_MASTER_CACHE_TABS**(来源:DEFAULT_FINANCE_OUTPUT_SHEET_ID)
- Finance_Summary_Master, Finance_Cars_Master
- Finance_Reimbursement_Master, Finance_Batch_Overview
### 8.3 兼容性注意(已知坑)
```
- cached rows 可能是二维数组或对象数组,读取层必须兼容两种格式
- ownerMonthKey 可能是 owner__month 或 owner_month,两种都要支持
- rowsToObjectList() 负责标准化处理
```
---
## 9. 财务核心规则(禁止搞错)
```
✅ A_Turo_Payouts = 正式收入口径
❌ A_Records ≠ 正式收入(只做分类/参考)
✅ 收入以 Turo payout 入账月份为准
❌ 不按 trip start/end 做入账
✅ Paid By = 谁垫付(不代表费用归属)
✅ 费用归属 = Plate / Belongs To
✅ PaytoCost = 不参与利润分成(直接返还)
✅ reimbursement = 按类型拆分(toll/EV/ticket/gas/cleaning/smoking/damage)
✅ OP1/OP2/OP3 = PayOption 计算路径
PBP-100%:管理公司拿100%,车主拿0%
PBP-30%: 管理公司拿30%,车主拿70%
✅ Payment Batch = 判断同批 payout 多条记录归属关系(不能随便改逻辑)
✅ 车主打印版 = Owner Standard(不展示内部 debug 字段)
```
---
## 10. ECS 迁移路线(当前阶段)
```
当前:Sheet-Master + ECS Co-Pilot(只读验证)
迁移路线(已确认,不可跳步):
Google Sheet → ECS Table UI → ECS-Master → 后期数据库化
当前说明:Google Sheet 当前仍是主数据源;ECS 当前是副驾驶(展示、读取、测试、验证、逐步承接);ECS-Master 是未来单独大版本,不是当前 V3.2 目标;当前只预留 record_id、updated_at、sync_version、操作日志、冲突检测等未来能力;当前不新增写 Google Sheet,除非用户明确确认。
当前已完成:ECS Table UI(/ops/tables + /ops/table)只读展示
当前下一步:继续完善 ECS Table UI / Internal Ops 只读与验证能力。当前仍是 Sheet-Master + ECS Co-Pilot 副驾驶验证期,不进入 ECS-Master 正式切换。
强制规则:
- 每次只迁移一个模块
- 每个模块:先只读 → 再编辑 → 再主数据源切换
- 不允许直接废掉 Google Sheet 逻辑
```
---
## 11. 当前风险点
| 风险 | 说明 | 严重度 |
|------|------|--------|
| server.js 单体过大 | 所有逻辑在一个文件,维护难度高 | 中(已知,暂不重构)|
| cache 时效性 | cache 未自动定时刷新,依赖手动触发 | 中 |
| 二维数组兼容 | cached rows 格式不一致,需要 rowsToObjectList 适配 | 中 |
| ownerMonthKey 双格式 | owner__month vs owner_month 需要双向兼容 | 低-中 |
| Henry NEEDS_REVIEW | 人工复核状态,非系统错误,但需定期清理 | 低 |
| ECS-Master 未切换 | Google Sheet 仍是主数据源,Sheet 故障会影响数据刷新 | 中 |
| PM2 同机多进程 | 同机运行 Etsy Image Tool,误操作 restart all 会影响生产 | 高 |
| A_Records 误用风险 | 如果不熟悉规则,容易把 A_Records 当收入主口径 | 高 |
---
## 12. 当前下一步重点
### 近期(当前进行)
- V3.2 继续推进:`/ops` 模块从只读展示向 Maintenance/Repair/Clean/Task 扩展
- Finance V1 收口稳定观察期
### 中期(计划中)
- 当前下一步:继续完善 ECS Table UI / Internal Ops 只读与验证能力。当前仍是 Sheet-Master + ECS Co-Pilot 副驾驶验证期,不进入 ECS-Master 正式切换。
- Scraper 统一框架(当前 Turo 优先稳定)
- Owner Portal 正式化
- Checkout 后续完善
### 暂停中(不做)
- 大型重构
- 数据库化重写
- 新增写 Google Sheet 行为(需明确确认才能做)
---
## 13. 开发规则速查(AI 工具必读)
```
禁止事项:
❌ 直接修改 main 分支
❌ 直接操作 ECS 生产数据
❌ pm2 restart all / pm2 delete all
❌ 影响 BookCars / Etsy Image Tool(端口 4030)
❌ 新增写 Google Sheet(未经确认)
❌ 修改 OP1/OP2/OP3/PayOption/Payment Batch 计算逻辑
❌ 用 A_Records 替代 A_Turo_Payouts 做收入来源
❌ 把 Paid By 当费用归属
❌ 把 PaytoCost 纳入利润分成
每次改动必须说明:
✅ 改哪些文件
✅ 改哪些函数或路由
✅ 是否影响 API
✅ 是否影响 OP 财务规则
✅ 是否写 Google Sheet
✅ 是否影响 BookCars / Etsy Tool
```
---
## 14. 上下文缺失说明
以下内容从项目知识库中**无法完整确认**,需要人工补充:
1. **server.js 完整路由列表**:文件过大,只能读到片段,无法枚举所有路由
2. **FINANCE_CACHE_TABS 完整列表**:仅确认了部分 tab 名称,完整列表未完全可见
3. **Guide-A 当前收录的 Tab 列表**:ECS-Ctrl=yes 的表有哪些,未完全确认
4. **Settlement 草稿的完整状态机**:draft save/load/confirm 流程边界未完全可见
5. **Scraper 当前实际运行状态**:本地 Data Collector Machine 的实际抓取频率未知
6. **OP 公式具体数值**:管理费比例、停车费规则的具体数值未在文档中完整列出
7. **Owner 列表**:文档提到 Henry/Tan/Roy/Quenna/Ning W,是否有其他 owner 未确认
8. **BookCars 系统**:提到"不影响 BookCars"但无 BookCars 相关文档,边界不清楚
---
*本文档由 Claude 根据 QP Fleet 项目知识库自动生成。如有出入,以实际代码和 docs/ 目录下 MD 文档为准。*
# QP_CURRENT_STATE.md
> 生成时间:2026-05 | 面向读者:ChatGPT / Codex / Cursor / 新接手开发者
> 这是一份**真实工程现状快照**,不是理想架构文档。
---
## 1. 项目定位
QP Fleet System 是 QuickPath 内部车队运营与财务管理系统。
- 不是单一应用,是"多层协作"的运营+财务体系。
- 当前主线:**V3 财务系统收口 + V3.2 Internal Ops 只读页面**。
- 部署地址:`http://47.77.231.107:4020`
- 服务器路径:`/opt/qp-fleet-system`
- PM2 进程名:`qp-fleet-system`(唯一允许操作的进程)
- 端口:`4020`(同机另有 Etsy Image Tool,端口 4030,**禁止误碰**)
---
## 2. 项目文件结构(真实现状)
```
/opt/qp-fleet-system/
├── server.js # 唯一入口,所有路由和页面都在这里
├── package.json # express / googleapis / xlsx / axios
├── service-account.json # Google API 鉴权(不提交)
├── cache/
│ └── finance/ # Finance cache-first 本地缓存
│ ├── A_overview.json
│ ├── A_Records.json
│ ├── A_Turo_Payouts.json
│ ├── A_management_fee_rules.json
│ ├── Guide-Owner.json
│ ├── Guide-OP-detail.json
│ ├── Finance_Summary_Master.json
│ ├── Finance_Cars_Master.json
│ ├── Finance_Reimbursement_Master.json
│ └── Finance_Batch_Overview.json
├── data/
│ └── datahub/
│ └── DataHub.xlsx # 本地中间数据文件(xlsx)
├── data/
│ └── settlements/ # 结算草稿文件(owner__month.json)
└── docs/ # 项目规则 MD 文档
├── CLAUDE.md # AI 工具入口说明(必须先读)
├── QP_CURRENT_STATUS.md
├── QP_PROJECT_OVERVIEW.md
├── QP_VERSION_TREE.md
├── QP_FINANCE_RULES.md
├── QP_DATAHUB_STRUCTURE.md
├── QP_ECS_MASTER_MIGRATION.md
├── QP_INTERNAL_OPS_PLAN.md
└── QP_SCRAPER_ARCHITECTURE.md
```
> ⚠️ `server.js` 是单体文件,所有路由、HTML 页面渲染、API、中间件都在其中。没有 React/Vue 框架,前端是 server-side rendered HTML + inline JS。
---
## 3. 技术栈
| 层级 | 技术 |
|------|------|
| 后端框架 | Express 5 (Node.js) |
| 认证 | Google Service Account (googleapis) |
| 主数据源(当前) | Google Sheet(两个 Sheet ID) |
| 中间层 | DataHub.xlsx(本地) |
| 缓存层 | `/cache/finance/*.json`(本地 JSON) |
| 前端渲染 | Server-side HTML,inline JS,无构建工具 |
| 包管理 | npm(无 lock file 限制)|
| 进程管理 | PM2 |
---
## 4. 数据源结构与三层关系
### 4.1 数据来源层级(当前真实状态)
```
[Google Sheet - 主数据源]
├── DATA_HUB_SHEET_ID = "1_e5chw2tstso6P7AFQwgHpmLtuR9HQBQXCfnPSAx0a8"
│ ├── A_overview ← 车辆/车主/平台/位置/归属关系
│ ├── A_Records ← 行程分类、费用拆解(辅助,非收入主口径)
│ ├── A_Turo_Payouts ← 正式收入口径 ✅
│ ├── A_management_fee_rules
│ ├── Guide-Owner ← 车主 PayOption / OP 规则
│ ├── Guide-OP-detail ← 各费用类型 OP1/OP2/OP3 处理规则
│ └── Guide-A ← ECS Table UI registry(ECS-Ctrl=yes 才进入)
│
└── DEFAULT_FINANCE_OUTPUT_SHEET_ID = "1eUESU1D6oj8PoXNxRgplITKZrY9xPZ-5adf2Z4kRICE"
├── Finance_Summary_Master
├── Finance_Cars_Master
├── Finance_Reimbursement_Master
└── Finance_Batch_Overview
[DataHub.xlsx - 本地中间层]
路径:/opt/qp-fleet-system/data/datahub/DataHub.xlsx
作用:接住抓取结果、缓存结果、财务中间结果,降低直接读 Sheet 耦合
读取函数:readDataHubTab(tabName)
[cache/finance/*.json - 本地 JSON 缓存]
作用:Finance API cache-first 读取,减少 Google Sheet 调用频率
刷新入口:GET /api/finance-cache-refresh
状态查询:GET /api/finance-cache-status
```
### 4.2 读取优先级(当前已确认)
```
Finance Master API:
local cache (JSON) → [fallback] Google Sheet
ECS Table UI (/ops/tables):
Google Sheet first → [fallback] DataHub.xlsx
ECS Table UI (/ops/table?tab=...):
DataHub.xlsx → [fallback] Google Sheet
原则:本地没有再 fallback;不确定来源时看 dataSourceDiagnostics 字段
```
### 4.3 Google Sheet / DataHub / ECS 三者关系
```
当前阶段:Sheet-Master + ECS Co-Pilot(副驾驶验证期)
Google Sheet ──→ [抓取/同步] ──→ DataHub.xlsx
↓
cache/finance/*.json
↓
Finance API (cache-first)
↓
/finance/* 页面(只读展示)
ECS(当前)= 读取、展示、验证
ECS(未来)= 主数据源(ECS-Master,尚未切换)
```
---
## 5. 当前主线模块(已完成 - Finance V1)
### 5.1 Finance Shell 入口
- 路由:`GET /finance`
- 左侧菜单分组(Finance / Owner / Operations / Tools)+ 可折叠
- iframe 框架,月份/车主选择器,语言切换(en/zh)
### 5.2 已完成页面(Finance V1 收口状态)
| 页面 | 路由 | 状态 |
|------|------|------|
| Dashboard | `/finance` → `dashboard` view | ✅ READY |
| Finance V1 Acceptance | `financeV1Acceptance` view | ✅ READY |
| Owner Detail | `/finance-owner-detail` | ✅ READY |
| Monthly Settlement Report | `/finance-owner-report` | ✅ READY |
| Owner Print | `/finance-owner-print` | ✅ READY |
| Expense Detail Report | `/finance-expense-report-v1` | ✅ READY |
| Payment Tracking | 内嵌 view | ✅ READY |
| Vehicle Anomalies | view | ✅ READY |
| Cache Refresh | `/finance-cache-refresh` | ✅ READY |
| Payout Debug | `/finance-payout-debug` | ✅ DEBUG工具 |
| Trip Income Debug | `/finance-trip-income-debug` | ✅ DEBUG工具 |
| Car Rule Preview | `/finance-car-trip-rule-preview` | ✅ DEBUG工具 |
### 5.3 Finance V1 线上验收状态(2026-05)
```
Owners = 5
Pay To Owners = $17,818.35
Paid/Remaining = $17,455.01 / $363.34
Henry = NEEDS_REVIEW(人工复核,不是系统错误)
Tan/Roy/Quenna/Ning W = READY
monthly-run-status: readyCount=5, missingCount=0, errorCount=0
```
---
## 6. 当前进行中模块(V3.2 Internal Ops)
### 6.1 /ops 入口
- 路由:`GET /ops`
- 内部运营后台,**不对车主开放**
- 当前全部只读,不写回 Google Sheet
### 6.2 V3.2 已落地步骤
| Step | 内容 | 状态 |
|------|------|------|
| Step2 | `/ops` 首页,模块卡片(Overview/Anomalies/Maintenance等)| ✅ |
| Step3 | Ops Overview Snapshot(复用 `/api/finance-dashboard-month`)| ✅ |
| Step4 | Vehicle Anomalies Snapshot(复用 `/api/finance-vehicles-month`)| ✅ |
| Step4 | ECS Table UI:`/ops/tables` + `/ops/table?tab=...` | ✅ |
| Step4.1 | Guide-A TabType 语义(Ctrl/Show)+ Sheet-first 策略 | ✅ |
| Step5 | 单表字段 checkbox 选择 + 搜索框 | ✅ |
| Step6 | Select All/Clear/Default10 + row limit(50/100/200/500) + sticky header | ✅ |
| Step7 | 分页 + 行顺序(Original/Reverse)+ localStorage 视图偏好 | ✅ |
| Step7.1 | 全量数据分页顺序修复(limit 语义改为 page size)| ✅ |
| Step7.2 | localStorage columns 对齐校验 + 越界修正 + Reset Saved View | ✅ |
---
## 7. 核心 API 清单
### Finance 核心 API(cache-first)
```
GET /api/finance-dashboard-month?month=YYYY-MM
GET /api/finance-owner-detail?owner=...&month=...
GET /api/finance-dashboard-master?month=...
GET /api/finance-owner-master?owner=...&month=...
GET /api/finance-monthly-run-status?month=...
GET /api/finance-owner-report-v1-calc?owner=...&month=...
GET /api/finance-owner-cards?month=...
GET /api/finance-vehicles-month?month=...
GET /api/finance-home-dashboard?month=...
```
### Cache 管理 API
```
GET /api/finance-cache-refresh ← 触发缓存刷新(写 JSON 文件)
GET /api/finance-cache-status ← 查询各 tab 缓存状态
POST /api/datahub-xlsx-upload ← 上传新版 DataHub.xlsx
GET /api/datahub-xlsx-status ← 查询 DataHub.xlsx 状态
```
### Debug API
```
GET /api/finance-payout-debug?...
GET /api/finance-trip-income-debug?tripId=...
GET /api/finance-op-compare-debug?owner=...&from=OP1&to=OP3
GET /api/finance-owner-op?owner=...
GET /api/finance-car-trip-rule-preview-note?...
```
### Settlement 草稿 API
```
GET /api/finance-owner-car-settlement-preview?owner=...&month=...
POST /api/finance-settlement-draft-save
GET /api/finance-settlement-draft-load
```
---
## 8. Cache 体系
### 8.1 cache-first 读取函数(server.js 内)
```javascript
loadFinanceCache(tabName) // 读 JSON cache
readDataHubTab(tabName) // 读 DataHub.xlsx(含 fallback Google Sheet)
readSheet(sheetId, tabName) // 直接读 Google Sheet
```
### 8.2 缓存覆盖 Tab 列表
**FINANCE_CACHE_TABS**(来源:DATA_HUB_SHEET_ID)
- A_overview, A_Records, A_Turo_Payouts, A_management_fee_rules
- Guide-Owner, Guide-OP-detail(+ 其他 Guide 表)
**FINANCE_MASTER_CACHE_TABS**(来源:DEFAULT_FINANCE_OUTPUT_SHEET_ID)
- Finance_Summary_Master, Finance_Cars_Master
- Finance_Reimbursement_Master, Finance_Batch_Overview
### 8.3 兼容性注意(已知坑)
```
- cached rows 可能是二维数组或对象数组,读取层必须兼容两种格式
- ownerMonthKey 可能是 owner__month 或 owner_month,两种都要支持
- rowsToObjectList() 负责标准化处理
```
---
## 9. 财务核心规则(禁止搞错)
```
✅ A_Turo_Payouts = 正式收入口径
❌ A_Records ≠ 正式收入(只做分类/参考)
✅ 收入以 Turo payout 入账月份为准
❌ 不按 trip start/end 做入账
✅ Paid By = 谁垫付(不代表费用归属)
✅ 费用归属 = Plate / Belongs To
✅ PaytoCost = 不参与利润分成(直接返还)
✅ reimbursement = 按类型拆分(toll/EV/ticket/gas/cleaning/smoking/damage)
✅ OP1/OP2/OP3 = PayOption 计算路径
PBP-100%:管理公司拿100%,车主拿0%
PBP-30%: 管理公司拿30%,车主拿70%
✅ Payment Batch = 判断同批 payout 多条记录归属关系(不能随便改逻辑)
✅ 车主打印版 = Owner Standard(不展示内部 debug 字段)
```
---
## 10. ECS 迁移路线(当前阶段)
```
当前:Sheet-Master + ECS Co-Pilot(只读验证)
迁移路线(已确认,不可跳步):
Google Sheet → ECS Table UI → ECS-Master → 后期数据库化
当前说明:Google Sheet 当前仍是主数据源;ECS 当前是副驾驶(展示、读取、测试、验证、逐步承接);ECS-Master 是未来单独大版本,不是当前 V3.2 目标;当前只预留 record_id、updated_at、sync_version、操作日志、冲突检测等未来能力;当前不新增写 Google Sheet,除非用户明确确认。
当前已完成:ECS Table UI(/ops/tables + /ops/table)只读展示
当前下一步:继续完善 ECS Table UI / Internal Ops 只读与验证能力。当前仍是 Sheet-Master + ECS Co-Pilot 副驾驶验证期,不进入 ECS-Master 正式切换。
强制规则:
- 每次只迁移一个模块
- 每个模块:先只读 → 再编辑 → 再主数据源切换
- 不允许直接废掉 Google Sheet 逻辑
```
---
## 11. 当前风险点
| 风险 | 说明 | 严重度 |
|------|------|--------|
| server.js 单体过大 | 所有逻辑在一个文件,维护难度高 | 中(已知,暂不重构)|
| cache 时效性 | cache 未自动定时刷新,依赖手动触发 | 中 |
| 二维数组兼容 | cached rows 格式不一致,需要 rowsToObjectList 适配 | 中 |
| ownerMonthKey 双格式 | owner__month vs owner_month 需要双向兼容 | 低-中 |
| Henry NEEDS_REVIEW | 人工复核状态,非系统错误,但需定期清理 | 低 |
| ECS-Master 未切换 | Google Sheet 仍是主数据源,Sheet 故障会影响数据刷新 | 中 |
| PM2 同机多进程 | 同机运行 Etsy Image Tool,误操作 restart all 会影响生产 | 高 |
| A_Records 误用风险 | 如果不熟悉规则,容易把 A_Records 当收入主口径 | 高 |
---
## 12. 当前下一步重点
### 近期(当前进行)
- V3.2 继续推进:`/ops` 模块从只读展示向 Maintenance/Repair/Clean/Task 扩展
- Finance V1 收口稳定观察期
### 中期(计划中)
- 当前下一步:继续完善 ECS Table UI / Internal Ops 只读与验证能力。当前仍是 Sheet-Master + ECS Co-Pilot 副驾驶验证期,不进入 ECS-Master 正式切换。
- Scraper 统一框架(当前 Turo 优先稳定)
- Owner Portal 正式化
- Checkout 后续完善
### 暂停中(不做)
- 大型重构
- 数据库化重写
- 新增写 Google Sheet 行为(需明确确认才能做)
---
## 13. 开发规则速查(AI 工具必读)
```
禁止事项:
❌ 直接修改 main 分支
❌ 直接操作 ECS 生产数据
❌ pm2 restart all / pm2 delete all
❌ 影响 BookCars / Etsy Image Tool(端口 4030)
❌ 新增写 Google Sheet(未经确认)
❌ 修改 OP1/OP2/OP3/PayOption/Payment Batch 计算逻辑
❌ 用 A_Records 替代 A_Turo_Payouts 做收入来源
❌ 把 Paid By 当费用归属
❌ 把 PaytoCost 纳入利润分成
每次改动必须说明:
✅ 改哪些文件
✅ 改哪些函数或路由
✅ 是否影响 API
✅ 是否影响 OP 财务规则
✅ 是否写 Google Sheet
✅ 是否影响 BookCars / Etsy Tool
```
---
## 14. 上下文缺失说明
以下内容从项目知识库中**无法完整确认**,需要人工补充:
1. **server.js 完整路由列表**:文件过大,只能读到片段,无法枚举所有路由
2. **FINANCE_CACHE_TABS 完整列表**:仅确认了部分 tab 名称,完整列表未完全可见
3. **Guide-A 当前收录的 Tab 列表**:ECS-Ctrl=yes 的表有哪些,未完全确认
4. **Settlement 草稿的完整状态机**:draft save/load/confirm 流程边界未完全可见
5. **Scraper 当前实际运行状态**:本地 Data Collector Machine 的实际抓取频率未知
6. **OP 公式具体数值**:管理费比例、停车费规则的具体数值未在文档中完整列出
7. **Owner 列表**:文档提到 Henry/Tan/Roy/Quenna/Ning W,是否有其他 owner 未确认
8. **BookCars 系统**:提到"不影响 BookCars"但无 BookCars 相关文档,边界不清楚
---
*本文档由 Claude 根据 QP Fleet 项目知识库自动生成。如有出入,以实际代码和 docs/ 目录下 MD 文档为准。*