QP Fleet Current Project State Snapshot

Last updated: 2026-06-01T03:17:34.549Z

# QP_CURRENT_STATE.md 
> 生成时间:2026-05 | 面向读者:ChatGPT / Codex / Cursor / 新接手开发者
> 这是一份**真实工程现状快照**,不是理想架构文档。

---

## 1. 项目定位

QP Fleet System 是 QuickPath 内部车队运营与财务管理系统。
- 不是单一应用,是"多层协作"的运营+财务体系。
- 当前主线:**C2.1g Business Validation(Ops Upload & Task Center 真实业务验证)**;暂停新增功能,先验证员工真实可用性,再决定是否同步 4020。
- Internal Ops 新增清洁记录查看:`/ops/cleaning-submissions`(只读,读取 `Cleaning_Submissions`,不写 Google Sheet)。
- 2026-05-25 支线最小收尾:A-guide 已接入 ECS 表格控制中心只读展示(含 control/show、缓存、刷新、同步、默认来源与数据来源类型),不新增写入;下一步主线回归 V3 财务收口。
- 部署地址:`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):
  Guide-A 规则总表驱动
  - TabType=Show: cache/DataHub/local cache first
  - TabType=Ctrl: CONTROL_BACKTRACE to original Google Sheet
  - PARAM_CONFIG: Guide-A / A_management_fee_rules / Guide-Owner / Guide-OP-detail
  - 展示字段:TabName/TableCategory/TabType/SourceMode/CacheMode/WriteMode/Description/Notes

ECS Table UI (/ops/table?tab=...):
  先读 Guide-A 元数据,再按 TabType 决定读取链路(Show=缓存优先,Ctrl=回溯原始表)

原则:本地没有再 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 内部车队运营与财务管理系统。
- 不是单一应用,是"多层协作"的运营+财务体系。
- 当前主线:**C2.1g Business Validation(Ops Upload & Task Center 真实业务验证)**;暂停新增功能,先验证员工真实可用性,再决定是否同步 4020。
- 部署地址:`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 文档为准。*

- V3.2 Step8.3: Upgraded `/ops/cleaning-upload` to Fleet Ops Quick Entry Cleaning flow with plate search, lock/unlock, upload overlay, front-end compression, wake lock, and resumable upload prompts (overwrite/append).
- Added cleaning APIs: search-plates, init, upload-photo, finalize, log-error; writes to Cleaning_Submissions, VIN8 tab, clean tab (YES only), System_Log/System_Error.

- 2026-05-24:完成 V3.2 Step8.5,仅增强 `/ops/cleaning-today` 只读看板入口与筛选:新增顶部 Back/ViewAll/Refresh、新增 `plate/ctxLot/canDispatch/ctxWho` 筛选、保留 `?date=YYYY-MM-DD`,并增加空状态与只读声明;未改上传链路、Drive 层级、Finance/OP、Etsy/4030。

- 2026-05-24:A档快速PR完成 `/ops/cleaning-upload` 中文文案优化与员工可读性提升:页面标题、字段名、按钮文案改为中文优先;`Checkout` 调整为 `还车检查(暂未开放)`;`状态更新` 调整为 `车辆状态更新(暂未开放)`;保留既有三个入口与 Cleaning 上传主流程;未改任何 API、上传逻辑、Drive 层级及 Finance/OP/Etsy/BookCars。

- 2026-05-24:A档快速PR收口验收增强:`/ops/cleaning-upload` 顶部新增“当前仅开放:清洁完成上传;还车检查和车辆状态更新暂未开放。”提示,上传成功卡片按钮优化为“继续上传下一辆 / 查看今日清洁看板 / 查看该车记录”;`/ops/cleaning-today` 与 `/ops/cleaning-submissions` 改为中文优先文案(标题、筛选项、按钮、状态与空状态),未改筛选逻辑、读取逻辑、软删除逻辑,Cleaning 主流程进入收口验收阶段。
- 2026-05-24:A档快速PR修复 Cleaning 记录页批量隐藏交互:`/ops/cleaning-submissions` 与 `/ops/cleaning-today` 的“一键隐藏当前无效记录”改为收集当前页全部可标记删除项并逐条调用 `POST /api/ops/cleaning-submissions/mark-deleted`;无候选时提示“当前没有可隐藏的无效记录。”;批量完成提示成功/失败数量,并在完成后自动刷新当前筛选结果;未改上传逻辑、Drive删除、Sheet物理删除、Finance/OP/Etsy/BookCars。

- 2026-05-24:A档快速PR(验收收口文案与默认显示优化)完成:`/ops/cleaning-upload` 上传成功卡片新增验收提示“上传成功后,请到“今日清洁看板”确认记录是否有效。测试记录可在“清洁记录列表”中隐藏。”;`/ops/cleaning-today` 与 `/ops/cleaning-submissions` 按钮文案统一为“一键隐藏测试/失效记录”,并将状态说明改为“有效 = 文件夹还在;文件夹不存在/无链接 = 测试或失效记录;已删除 = 已隐藏记录。”;默认仍只显示有效记录(不显示 Deleted=YES 与无效记录);未改上传逻辑、Drive 层级、Google Sheet 写入逻辑及 Finance/OP/Etsy/BookCars。
- 2026-05-24:B档功能PR新增 `/ops/status-update` 草稿页与配套 API:新增 `GET /ops/status-update`、`GET /api/ops/status-update/search-plates`、`POST /api/ops/status-update/submit-draft`;页面支持车牌尾号搜索与锁车(数据源优先 `A_overview` / 本地 DataHub overview),提交只写入 `Status_Update_Drafts`(字段:submittedAt/plate/vinLast8/owner/oldStatus/newStatus/submittedBy/note/sourcePage/rawPayload),明确提示“当前为状态更新草稿,不会改变真实车辆状态”;未改 Finance API/OP公式、Cleaning上传逻辑、Drive层级、Etsy/4030/BookCars。
- 2026-05-25:V3.1 Step5F-0 开始,新增 `GET /finance-owner-legacy-report-v1` 旧报表数据结构复刻页(四模块:结算汇总 / 收益明细 / 报销费用明细 / 花销费用明细),参数支持 `month` + `owner`,优先复用 `finance-owner-detail`、`finance-owner-report-v1-calc`、`finance-expense-flow-debug` 现有读取结果;缺失字段统一前端显示“暂无数据 / 缺少字段”,不报错。未改 Finance 公式、未写 Google Sheet、未影响 OP / Cleaning / Etsy / BookCars。
- 2026-05-25:C档前置最小修复仅针对 Dashboard UI/状态读取层:修复 `/finance-dashboard` 月份默认来源(优先 URL `?month=YYYY-MM`,无则当前月/既有默认),并确保页面 `monthInput` 与实际请求 `/api/finance-dashboard-month` 的 month 一致;顶部新增只读口径提示(当前加载月份、Finance Master cache-first + Google Sheet fallback、Owner 搜索仅列表筛选不触发重算);`/finance` 外壳在 dashboard 视图下禁用 Owner 输入并提示“Dashboard 为全车主汇总,Owner 只用于 Owner 页面”;“Recalculate This Month”降权为“管理员重算(会写入 Sheet,耗时较久)”并新增明确确认弹窗。未改财务公式、未改 OP 规则、未改 `/api/finance-step6`、未改 `/api/finance-batch-monthly` 计算逻辑、未新增 Google Sheet 写入、未改 Cleaning/Etsy/BookCars。
- 2026-05-25:C档核心工程前置诊断新增只读页面与只读 API:新增 `GET /finance-dashboard-debug` 与 `GET /api/finance-dashboard-debug`,用于定位 Dashboard 在 `month=2026-03` 时 Owners/PayToOwners 为 0 的缺失层级(cache、Google Sheet fallback、OwnerMonthKey、月份格式)。诊断输出覆盖 `Finance_Summary_Master` / `Finance_Cars_Master` / `Finance_Reimbursement_Master` / `Finance_Batch_Overview` 四表的来源、总行数、月匹配行、样例 key、列名、cache 状态与 sheet fallback 状态,并给出下一步建议。明确只读:不写 Google Sheet、不触发重算、不改公式。未改 `/api/finance-step6`、未改 `/api/finance-batch-monthly`、未改 OP 规则、未改 Cleaning/Etsy/BookCars。
- 2026-05-25:V3.1 Step5F-1 最小修复完成,目标为 2026-03 Finance Master 结果层与 cache 链路(不改财务公式/OP 规则)。`/api/finance-batch-monthly` 新增批量完成后自动刷新 Finance Master 本地缓存(默认开启,可用 `refreshCache=0` 关闭),并在响应返回 `cacheRefreshed/cacheRefreshResults`;同时 `/api/finance-cache-refresh` 支持 `outputSheetId` 参数,刷新 Master cache 时按目标输出表读取,不再固定默认表。本次修复涉及 2026-03 月份生成链路与缓存一致性:Google Sheet 写入保持原有四张 Master 表写入逻辑;cache 刷新改为明确执行;未改 OP 公式、未改 Guide-OP-detail 规则、未改 A_Records/A_Turo_Payouts 口径、未改 Cleaning/Etsy/BookCars。
- 2026-05-25:V3.1 Step5F-2 完成,旧版车主月报复刻页 `/finance-owner-legacy-report-v1` 四模块切换为真实数据口径:结算汇总与收益明细优先读取 `Finance_Summary_Master`/`Finance_Cars_Master`(通过 `/api/finance-owner-detail` cache-first 链路);报销费用明细优先读取 `Finance_Reimbursement_Master`(按 PaidBy 归集展示);花销费用明细读取 `A_Flow` 调试口径(按 owner/BelongsTo/Plate 归集展示),并明确与报销分离。缺字段统一显示“缺少字段/暂无数据”且页面不报错。未改 Finance 公式、未写 Google Sheet、未影响 OP / Dashboard / Cleaning / Etsy / BookCars。
- 2026-05-25:V3.1 Step5F-3 最小字段对齐修复:`/finance-owner-legacy-report-v1` 修正 month 提示逻辑(仅非法 `YYYY-MM` 才提示)、花销费用日期展示统一为 `YYYY-MM-DD`(仅前端显示格式化,不改原数据)、花销“费用类型/备注”增加多字段兼容(`feeType/Fee Type/费用类型/category/Type/备注说明/Note`),收益明细增加车辆字段别名兼容读取(出租率/出租天数/出租次数/均价尝试 `UtilizationRate/RentalDays|RentalDayCount/TripCount|RentalCount/AvgDailyRate|AveragePrice` 及中文别名)。未改 Finance 公式、未改 OP 规则、未改 `/api/finance-step6`、未改 `/api/finance-batch-monthly`、未新增 Google Sheet 写入。
- 2026-05-25:V3.1 Step5F-4 A档快速 PR 完成:`/finance-owner-legacy-report-v1` 仅展示层优化,新增顶部数据来源轻提示;结算汇总按“收入类/扣费类/返还报销类/最终结果”分组并高亮“最终应付车主”;收益明细为出租率/出租天数/出租次数/均价缺失值改为“待接月度统计”,并新增“运营字段待接 A_Records 月度统计”说明;报销费用明细与花销费用明细各自补充口径说明文案。未改 Finance 公式、未改 OP 规则、未改 `/api/finance-step6`、未改 `/api/finance-batch-monthly`、未涉及 Google Sheet 写入。
- 2026-05-25:V3.1 Step5F-5 A档快速 PR 完成:修复 `/finance-owner-legacy-report-v1` 结算汇总中“最终应付车主 Final Net To Owner”标签被当作 `<span ...>` 文本显示的问题,改为正常中英文字段名展示并保留最终金额绿色高亮;同时在 Finance 入口页新增“旧版车主月报预览”快捷入口(`/finance-owner-legacy-report-v1`),方便日常验收进入旧版预览。未改 Finance 公式、未写 Google Sheet、未影响 OP/Cleaning/Etsy/BookCars,未改 `/api/finance-step6` 与 `/api/finance-batch-monthly`。
- 2026-05-25:V3.1 Step5F-6 完成,旧版车主月报 `/finance-owner-legacy-report-v1` 收益明细补齐运营统计字段(出租率/出租天数/出租次数/均价):优先读取 `Finance_Cars_Master` 既有字段,缺失时通过新增只读接口 `GET /api/finance-owner-legacy-monthly-stats` 按 `owner+month+plate` 从 `A_Records` 当月行程补算(tripCount、rentalDays、utilizationRate、avgDailyRate,均价基于 `Finance_Cars_Master.rentalBaseIncome / rentalDays`);无行程显示“0/暂无行程”,不再大面积显示“待接月度统计”。本次仅展示层与只读读取增强,未改 Finance 公式、未改 OP、未改 `/api/finance-step6`、未改 `/api/finance-batch-monthly`、未写 Google Sheet。
- 2026-05-25:V3.1 Step5F-7 完成,旧版车主月报 `/finance-owner-legacy-report-v1` 修正口径:报销费用明细由“汇总”改为“A_Flow 明细行”并按 `PaidBy=owner` 过滤(不再按 Belongs To 判定报销);花销费用明细继续按 Belongs To 归属口径展示并保留说明;收益明细“车型”改为读取 overview/Finance Master 车型字段,不再固定平台字样;出租率/出租天数/出租次数/均价继续走 `A_Records` 只读补算链路并按跨月重叠天数计算。未改公式、未写 Sheet、未影响 OP/Dashboard/Cleaning/Etsy/BookCars,未改 `/api/finance-step6` 与 `/api/finance-batch-monthly`。
- 2026-05-25:V3.1 Step5F-8 完成,`/finance-owner-legacy-report-v1` 报销费用明细改为专用 PaidBy 口径读取:扩展 `/api/finance-expense-flow-debug` 只读参数 `mode`(`paidBy` / `belongsTo` / `ownerAny`)与 `paidByOwner`,页面改为双通道读取(报销明细仅 `mode=paidBy&paidByOwner=owner`;花销明细继续 `mode=belongsTo`)。报销列表保留展示 Belongs To 字段但不参与筛选。未改 Finance 公式、未改 OP、未改 `/api/finance-step6`、未改 `/api/finance-batch-monthly`、未写 Google Sheet、未影响 Dashboard/Cleaning/Etsy/BookCars。
- 2026-05-25:V3.1 Step5F-10 完成,新增 `GET /finance-owner-legacy-report-v2` 纯后端渲染版本,保留旧页 `/finance-owner-legacy-report-v1` 不改动;V2 支持 `month=YYYY-MM&owner=车主名`,四模块(结算汇总/收益明细/报销费用明细/花销费用明细)均由服务端渲染输出,避免 inline JS 拼接语法风险。数据口径保持现有规则:结算汇总与收益明细读取 `finance-owner-detail`(`Finance Master / owner detail`)并继续只读接入 `A_Records` 运营补算;报销费用明细读取 `A_Flow` 且仅按 `PaidBy=owner` 过滤(不按 `Belongs To` 限制);花销费用明细读取 `A_Flow` 且按 `Belongs To=owner`。同时在 Finance 入口新增“旧版车主月报 V2”按钮。未改 Finance 公式、未改 OP 规则、未改 `/api/finance-step6`、未改 `/api/finance-batch-monthly`、未写 Google Sheet、未影响 Dashboard/Cleaning/Etsy/BookCars。
- 2026-05-25:V3.1 Step5F-7 补丁修复完成(仅 A_Records 车牌匹配):`/api/finance-owner-legacy-monthly-stats` 与 `/api/finance-owner-legacy-monthly-stats-debug` 的 Vehicle 车牌提取由旧的 `CA ` 固定截断逻辑改为 `extractPlateFromVehicleText` + 统一 normalize(转大写、去 `#`、去空格、仅保留字母数字);修复 `Henry (CA #9NLY246)` 等文本被提取成 `#9NLY24` 的问题,匹配前对 `ownerPlates` 与 `extractedPlate` 同口径标准化,确保 `ownerPlateMatched` 与 `statsByPlate` 有效统计恢复。未改 Finance 公式、未改 OP 规则、未写 Google Sheet、未改 Dashboard/Cleaning/Etsy/BookCars。
- 2026-05-26:V3.1 Step5F-9 完成,`/finance-owner-legacy-report-v2` 新增展示层展开/收起交互:收益明细、报销费用明细、花销费用明细支持模块级折叠(默认:收益/报销展开,花销收起);收益明细每车新增“查看行程/收起行程”(数据来自 `/api/finance-owner-legacy-monthly-stats` 已参与本月统计的 overlap 行程);每车新增“查看费用/收起费用”(数据来自 `A_Flow` 只读链路 `/api/finance-expense-flow-debug`,按 `month+plate` 过滤,不按 PaidBy/owner 筛选)。本次仅改 V2 展示与必要只读读取,未改公式、未改 OP、未改 `/api/finance-step6`、未改 `/api/finance-batch-monthly`、未写 Google Sheet,未影响 V1 与 Dashboard/Cleaning/Etsy/BookCars。
- 2026-05-26:A档文档任务完成,新增 `docs/QP_FINANCE_DATA_MAP.md`(Claude 审计结果正式化):补齐财务系统总数据流、数据源总表、`A_Turo_Payouts / A_Records / A_Flow / A_overview` 关系、字段字典、收入口径、费用归属 vs 报销归属、API 数据地图、页面数据地图、cache-first 策略、出租天数/出租率/报销费用/车辆花销推导例子、已知坑点。仅文档更新;未改代码、未改 `server.js`、未写 Google Sheet、未改 Finance 公式、未改 OP、未触碰 Dashboard/Cleaning/Etsy/BookCars。
- 2026-05-26:V3.1 Step5F-10(V2 打印与车主可读版优化)完成,`/finance-owner-legacy-report-v2` 仅展示层优化:页面标题改为“车主月度报表 Owner Monthly Report”并在顶部展示车主与月份;四模块保留且默认状态为收益明细展开、报销费用明细展开、花销费用明细收起、每车行程/每车费用明细收起;结算汇总“最终应付车主 Final Net To Owner”按正负金额高亮(正数绿色、负数红色并提示车主需向公司补付);表格统一金额右对齐、长备注自动换行、费用明细收据链接统一显示“查看收据”;新增打印样式,打印时隐藏返回链接/加载按钮/技术说明与调试弱文案,仅保留标题、月份、车主、四模块及当前展开内容;内部版本提示移至页底弱化展示。未改财务公式、未改 OP、未改 `/api/finance-step6`、未改 `/api/finance-batch-monthly`、未写 Google Sheet、未改 V1 与 Dashboard/Cleaning/Etsy/BookCars。
- 2026-05-26:V3.1 Step5F-11(旧版车主月报 V2 最终验收收口记录)完成:`/finance-owner-legacy-report-v2` 最小可用版已收口;已完成项包括结算汇总展示、收益明细报告、出租率/出租天数/出租次数显示、每车行程展开、每车费用展开、报销费用明细按 `PaidBy=owner`、花销费用明细按 `Belongs To=owner`、展开/收起、打印样式与车主可读版基础美化。本次仅文档更新,不改 `server.js`、不改 API、不改公式、不改 OP、不写 Google Sheet,且未触碰 Dashboard/Cleaning/Etsy/BookCars。

- 2026-05-26:V3.3 Step1(Finance Monthly Snapshot 基础层)完成最小可用底座:新增 `POST /api/finance-snapshots/system-auto`(生成 System Auto Version,默认不覆盖,已存在返回 alreadyExists)与 `GET /api/finance-snapshots`(按 owner/month 查询 snapshot 列表);新增 `/finance-snapshots` 内部管理页(查询 + 生成 + 列表)。Snapshot 存储采用本地 JSON 目录 `data/finance-snapshots/`,文件名 `<month>__<ownerNormalized>__system-auto.json`。本次仅新增 snapshot 新层,不改 Finance 公式、不改 OP 规则、不改 `/api/finance-step6`、不改 `/api/finance-batch-monthly`、不写 Google Sheet、不做 Manual Adjustment。
- 2026-05-26:V3.3 Step1.1(Snapshot 详情查看与基础预览)完成:新增只读 API `GET /api/finance-snapshots/:snapshotId`,可返回 snapshot `raw`(完整 JSON)与 `detail`(基础信息、数据摘要、关键金额、车辆明细预览);`/finance-snapshots` 列表页新增“查看详情”按钮与页面内只读详情预览区域。仅查看不编辑;未改 Finance 公式、未改 OP、未改 `/api/finance-step6`、未改 `/api/finance-batch-monthly`、未写 Google Sheet、未做 Manual Adjustment/Display Version 切换/Lock。
- 2026-05-26:V3.3 Step1.4(Snapshot 管理页基础收口优化)完成:仅优化 `/finance-snapshots` 只读管理页展示体验(未改 Snapshot 保存逻辑、未改 Snapshot API 业务逻辑)。新增 completeness 颜色标识:`Complete` 绿色、`Missing Cars/Missing Expenses/Missing Stats/Missing Summary` 橙色、`Need Review` 红色;新增解释文案(`Complete = 可作为人工调整底稿`、`Need Review = 数据不完整,不建议进入人工调整`);增强筛选提示(默认提示输入 month/owner,owner 为空表示查看该月份全部 owner,month 为空表示查看全部 snapshot);对 `Missing/Need Review` 旧测试快照增加“不完整(保留旧测试快照,不删除)”标记;页面底部新增下一步提示(Step1 完成后进入 Step2 Manual Adjustment,且 Manual Adjustment 只基于 Complete snapshot)。未改 Finance 公式、未改 OP、未改 `/api/finance-step6`、未改 `/api/finance-batch-monthly`、未写 Google Sheet、未做 Manual Adjustment。

---

## 12. V3.3 Step2-0(Manual Adjustment 设计)

- 2026-05-26:已新增 `docs/QP_FINANCE_MANUAL_ADJUSTMENT_PLAN.md`。
- 本次仅完成 Manual Adjustment 设计文档(业务规则、数据结构、处理流程、边界、Step2 拆分)。
- 当前仍处于“文档先行”阶段,**尚未进入代码实现**。
- 明确未改:`server.js`、API、Finance 公式、OP、step6、batch monthly、Google Sheet 写入链路。
- 2026-05-26:V3.3 Step2.1(Manual v1 创建最小版)完成:新增 `POST /api/finance-snapshots/manual-v1`,仅允许基于 `Complete + SYSTEM_AUTO` 快照创建 `Manual v1` 本地 JSON(文件名 `<month>__<ownerNormalized>__manual-v1.json`),写入最小 adjustment 字段(`adjustmentType/plate/amount/reason`)并复制 base snapshot `data`,默认不覆盖已存在 manual-v1(返回 `alreadyExists:true`)。`/finance-snapshots` 页面新增“创建 Manual v1”按钮(仅 Complete + SYSTEM_AUTO 显示)和最小表单提交流程。未做重算、未改公式、未改 OP、未改 `/api/finance-step6`、未改 `/api/finance-batch-monthly`、未写 Google Sheet。

---

## 13. Staging 测试环境规划(2026-05-26 新增)

为避免未充分验证代码直接影响正式环境,新增 staging 规划:

- Production 保持不变:`/opt/qp-fleet-system` + `qp-fleet-system` + `4020`
- Staging 新增环境:`/opt/qp-fleet-system-staging` + `qp-fleet-staging` + `4021`
- 发布流程更新:PR 合并后先部署 staging,staging 验收通过后再部署正式 4020。
- 运维禁令继续生效:禁止 `pm2 restart all` / `pm2 delete all`;禁止误碰 Etsy Image Tool(4030)。
- 2026-05-26:V3.3 Step2.2(Manual v1 PAYOUT_ADJUSTMENT 最小重算版)完成:Manual v1 从 System Auto 派生后执行最小重算,仅处理 `PAYOUT_ADJUSTMENT`。在 `data.cars` 按 plate 查找目标车并更新收入字段(兼容 `Income_Payout/incomePayout/income/totalIncome/ownerIncome`),同步更新车辆最终结算字段(兼容 `FinalSettlement/finalSettlement/Final Net To Owner/finalNetToOwner/netToOwner`),并同步更新 `data.summary` 的 `Total Income` 与 `Final Net To Owner`(字段存在时)。新增 `adjustmentsApplied`、`adjustmentSummary`。不覆盖 System Auto、不写 Google Sheet、不改 finance-step6/batch monthly。

- 2026-05-26:V3.3 Step2.3(Manual v1 Difference Preview 最小版)完成:`GET /api/finance-snapshots/:snapshotId` 新增 `detail.diffPreview` 只读差异预览,`/finance-snapshots` 详情区新增 “Manual差异预览” 展示。仅用于查看 base vs manual 的最小差异,不修改 Manual v1 创建逻辑、不改 System Auto、不写 Google Sheet、不改 Finance 公式/OP/step6/batch monthly。
- 2026-05-27:A档快速PR(staging 4021)完成 `/ops/cleaning-upload` 重复上传冲突收尾:当同日期+同车辆已有清洁照片/目录时,前端改为中文傻瓜式二选一(“补充上传(推荐)/ 覆盖重传”);覆盖重传新增二次确认(“确认覆盖上传?删除后无法恢复”);后端 `init` 支持 `resumeMode=replace` 并仅清空当天该车目标目录,不影响其他日期/车牌;`finalize` 在 `Cleaning_Submissions.rawPayload` 记录 `uploadMode`(`supplemental upload` / `replace upload`)。影响范围仅 Cleaning Upload 轻支线;Google Sheet 仍写 `Cleaning_Submissions`(附模式标记)、VIN8、clean(YES)、System_Log;不影响 Finance API/OP/Owner Report/A-guide/BookCars/Checkout 主系统。部署/验收状态:仅 staging 4021 推进,待页面验收,不发布 4020。
- 2026-05-27:A档快速PR(staging 4021)继续修正 `/ops/cleaning-upload` 重复上传弹窗交互:废弃浏览器原生 confirm,改为页面内移动端友好三选项弹窗(`覆盖上传 / 追加上传 / 取消上传`);其中“覆盖上传”增加二次确认弹窗(返回 / 确认覆盖上传),文案明确“删除后无法恢复”;行为保持:追加= `supplemental upload`(保留旧照片并追加)、覆盖= `replace upload`(仅清空同日期同车目录后上传本次照片)、取消=中止本次流程且不写入。边界保持不改其他日期/车辆/车牌及 Finance API / A-guide / Owner Report / BookCars。

---

## 15. 配置表每日快照 V1(2026-05-28)

- 新增关键配置表 ECS 本地 JSON 快照保护,覆盖:`Guide-A`、`A_management_fee_rules`、`Guide-Owner`、`Guide-OP-detail`、`A_overview`。
- 快照保存到当前项目目录下的 `cache/snapshots/YYYY-MM-DD/{TabName}.json`;production 为 `/opt/qp-fleet-system/cache/snapshots/...`,staging 为 `/opt/qp-fleet-system-staging/cache/snapshots/...`。
- 新增内部手动 API:`POST /api/ops/config-snapshots/create`,可指定 `tabs` 与 `reason`;`tabs` 为空时默认快照全部关键配置表。
- 快照 JSON 仅保存只读备份字段:`tabName`、`reason`、`createdAt`、`rowCount`、`rows`。
- 保留策略:每日快照仅保留最近 7 天,清理范围限制在 `cache/snapshots` 日期文件夹内。
- `POST /api/ops/guide-a/low-risk-update` 在执行 Guide-A 低风险写入前,会先自动创建 `Guide-A` 快照,`reason=before-guide-a-low-risk-update`。
- 当前 V1 不做恢复页面、不做 diff 页面、不做一键还原;手动快照 API 不写 Google Sheet,不影响财务计算、Cleaning Upload、Owner Report、BookCars 或 Etsy Image Tool。

---

## 2026-05-31 流水追加:PR #295~#300 Internal Ops 文档补录

> 本记录按流水追加,不覆盖旧记录。核对范围为当前 `main` 代码中的 Cleaning / Claim / Checkout 上传链路、公共停车场逻辑、CallHandling 自动 Follow-up 与相关 QP 文档。

| 日期 | PR编号 | 完成内容 | 影响模块 | 是否影响 Google Sheet | 是否影响 Finance | 是否部署到 4021 | 是否部署到 4020 | 下一步计划 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 2026-05-31 | #295 | 补录 Cleaning/Claim EXIF UX 状态:Cleaning 默认去 EXIF,高级选项折叠;Claim 默认保留 EXIF;Drive 文件夹按 EXIF 模式区分;CallHandling 记录 EXIF/时间戳口径。 | Cleaning Upload、Claim Upload、Drive Evidence、CallHandling | 是:Cleaning 写 `Cleaning_Submissions.rawPayload`;Claim 写 `Claim_Evidence_Submissions.PhotoMode/RawPayload` | 否 | 需以部署记录为准,本文档未验证运行中实例 | 需以部署记录为准,本文档未验证运行中实例 | 若 Cleaning 需要独立 `PhotoMode` 列,另开 Sheet migration / backfill 任务 |
| 2026-05-31 | #296 | 补录 Checkout V1 scaffold 与停车场逻辑统一:`/ops/checkout-upload`、`Checkout_Submissions`、Drive Folder、Overview Location -> Parking Lot 映射、本次实际位置记录。 | Checkout Upload、A_overview、Drive Evidence、RawPayload | 是:写 `Checkout_Submissions` 与 `System_Log` | 否 | 需以部署记录为准,本文档未验证运行中实例 | 需以部署记录为准,本文档未验证运行中实例 | C2.2 继续完善 Checkout Evidence / Claim Candidate |
| 2026-05-31 | #297 | 补录 Checkout parking lookup 与照片限制:锁车后读取系统位置,员工选择实际位置;位置变更写入 Note / CallHandling / RawPayload;Checkout 采用单照片上传组织模式。 | Checkout UI、Parking Lot Logic、Evidence Upload | 是:写 `Checkout_Submissions.RawPayload/Note` | 否 | 需以部署记录为准,本文档未验证运行中实例 | 需以部署记录为准,本文档未验证运行中实例 | 后续补只读查看页与证据完整性校验 |
| 2026-05-31 | #298 | 补录 Compact Checkout UI、Check-in odometer 与 mileage 修正:最近行程默认一行、详情展开、每天允许里程可改、Allowed Mileage / Driven Mileage / Over Mileage 自动计算。 | Checkout UI、A_Records、Mileage | 是:写 `Checkout_Submissions` 里程相关字段 | 否 | 需以部署记录为准,本文档未验证运行中实例 | 需以部署记录为准,本文档未验证运行中实例 | C2.2 明确 mileage 异常处理与人工确认规则 |
| 2026-05-31 | #299 | 补录 Checkout Upload V1 layout 优化:车辆信息紧凑展示,车况与理赔候选默认收起,备注统一在提交前,理赔候选自动汇总到备注 / Follow-up。 | Checkout UI、Claim Candidate、CallHandling | 是:写 `Checkout_Submissions.ClaimCandidates/Note/RawPayload` | 否 | 需以部署记录为准,本文档未验证运行中实例 | 需以部署记录为准,本文档未验证运行中实例 | 将 Claim Candidate 与正式 Claim 边界继续固化到 C2.2 |
| 2026-05-31 | #300 | 补录 Cleaning / Claim / Checkout 位置选择与自动备注统一逻辑:系统位置来自 Overview,实际位置来自员工现场选择,位置变更仅记录本次操作,不直接改 Overview。 | Cleaning Upload、Claim Upload、Checkout Upload、Parking Lot Logic、CallHandling | 是:写各自 submissions 的 Note/RawPayload,并写 CallHandling | 否 | 需以部署记录为准,本文档未验证运行中实例 | 需以部署记录为准,本文档未验证运行中实例 | 后续如需永久改 Overview,必须设计独立审批/确认流程 |

### 2026-05-31 当前 Checkout 阶段结论

- Checkout 当前属于 **C2.1 Checkout Upload V1 / 基础版**。
- 已包含 Vehicle Lock、Trip Lookup、Mileage、Fuel、Evidence Upload、Claim Candidate、CallHandling、Parking Lot Logic。
- 下一阶段:**C2.2 Checkout Evidence & Claim Candidate**。
- 后续阶段:**C2.3 Vehicle Health**、**C2.4 Maintenance Reminder**。

### 2026-05-31 当前仍未写入/未完全落地的内容

- Cleaning 独立 `PhotoMode` 列尚未在当前代码中落地;目前是 `rawPayload.stripExif/uploadMode` 口径。
- Checkout 独立 `PhotoMode` 字段尚未落地。
- Claim Candidate 仍不是正式 Claim;正式 Claim 编号、状态机、财务影响与结算口径尚未落地。
- 4021 / 4020 实际部署状态未通过本次文档任务验证,需以部署流水或 PM2/服务器检查为准。

## 2026-05-31 当前状态补录:C2.1a Task Engine Lite

- Cleaning / Claim / Checkout 上传成功后会生成自动 Task#:`CLN-YYMMDD-XXXX`、`CLM-YYMMDD-XXXX`、`CHK-YYMMDD-XXXX`,日期按洛杉矶时间,后四位在写入前读取 CallHandling 避免与既有 Task# 重复。
- CallHandling 仍是 Lite 版任务承载层:Task# 写入 `Phone#`/`Phone` 列,`Status=Follow-up`,`任务类型=S1`,`Call Type=Other`,车牌字段写完整车牌,Agent 留空。
- CallHandling Description 已从多行长描述改为短单行;Drive 文件夹链接和后台下一步说明移入 `To do` 列。
- Cleaning_Submissions / Claim_Evidence_Submissions / Checkout_Submissions 的 RawPayload 同步保存 Task#;若提交表缺少 `Task#` 表头,后端会自动补表头。
- `/ops/cleaning-upload`、`/ops/claim-upload`、`/ops/checkout-upload` 顶部都有默认收起的“今日自动任务状态”栏;展开后调用 `GET /api/ops/tasks/today` 从 CallHandling 只读统计今日 total / Follow-up / Done / 类型数量和最近任务。
- 本阶段没有引入账号、权限、Done 编辑或独立 Task 表;也不影响 Finance、Guide-A 主控逻辑、Owner Report、BookCars、Overview 写入或 Turo 自动提交。

## 2026-05-31 当前状态补录:C2.1b Task Center / 任务中心 Lite

- `/ops/tasks` 已作为 Fleet Ops 任务中心入口落地,用于查看 Cleaning / Claim / Checkout 自动生成的 Task#,并处理 Follow-up 到 Done 的闭环。
- 数据源仍为 `CallHandling`,第一版不新增独立 Task 表;后端仅读取 `Phone#` / `Phone` 中符合 `CLN-YYMMDD-XXXX`、`CLM-YYMMDD-XXXX`、`CHK-YYMMDD-XXXX` 的行。
- `GET /api/ops/tasks` 支持按洛杉矶日期、Status、任务类型和车牌筛选,并返回 total / Follow-up / Done / Cleaning / Claim / Checkout 统计及任务列表。
- `POST /api/ops/tasks/update-status` 按 Task# 查找行,只支持自动任务从 `Follow-up` 标记为 `Done`;写入 Google Sheet 的 `CallHandling.Status`,如有 `Done By` 字段则写 `Done By`,否则写 `Agent`。
- 更新状态时不修改 `Description` / `To do`,不删除行,不允许非 Task# 行被更新,也不让前端用 rowNumber 直接写表。
- `/ops/cleaning-upload`、`/ops/claim-upload`、`/ops/checkout-upload` 的今日自动任务状态栏仍保留,并增加“查看任务中心”入口。
- 当前仍是 Lite 版:无登录系统、无复杂权限、无独立任务数据库、无 Need Review / Waiting Owner 等扩展状态。
- 影响边界保持不变:不影响 Cleaning / Claim / Checkout 上传主流程;不影响 Finance / Guide-A / Owner Report / BookCars / Overview。

## 2026-05-31 当前状态补录:C2.1c Task Center 小闭环增强

- `/ops/tasks` 任务详情已扩展显示 Task#、类型、车牌、Status、任务类型 / Priority、创建时间、Description、To do、Drive 文件夹链接、Submitter、Done By、Done At 与 RowNumber debug;Drive 链接从 `To do` 中提取,原文仍保留。
- Done 闭环现在要求前端页面内确认并填写 / 选择完成人;后端拒绝空 doneBy,按 Task# 更新 Google Sheet `CallHandling` 的 `Status=Done`、`Done By` 和洛杉矶时间 `Done At (YYYY-MM-DD HH:mm)`。
- `CallHandling` 若缺少 `Done By` / `Done At` 表头会在更新前自动补表头;兼容旧表的 `Agent` 回退逻辑保留,但优先写 `Done By`。
- `GET /api/ops/tasks` 已支持 `taskId` 查询,用于 `/ops/tasks?taskId=CLN-260531-0001` 这类成功卡片跳转定位;命中后页面高亮并自动展开该任务,未命中则显示空结果提示。
- Cleaning / Claim / Checkout 上传成功卡片新增“查看任务中心”入口,链接优先带 Task#;今日自动任务状态栏仍保留,并将 Follow-up 入口指向 `/ops/tasks?status=Follow-up`。
- 本阶段仍不新增独立 Task 数据库,不做复杂权限 / 复杂状态,不修改正式 Claim Candidate 审批,不影响 Finance、Guide-A、Owner Report、BookCars、Overview 写入或 Turo 自动提交。

## 2026-05-31 当前状态补录:C2.1d Ops Upload & Task Center 验收收口版

- 当前阶段进入 C2.1d 验收收口:Cleaning / Claim / Checkout / Task Center 先做到员工能看懂、后台能验收、上线前能测试,不继续扩新功能。
- 新增 `/ops/help` 员工使用说明页,覆盖清洁上传、理赔上传、还车检查 Checkout、Task# 含义、Follow-up 处理、Done 含义、Google Drive 文件夹查看方式与常见提醒。
- `/ops/tasks` 默认显示 `Follow-up`,页面明确显示“当前显示:Follow-up”,顶部显示“今日未处理 X 条”,并提供“今日未处理 / 今日已完成 / 全部任务 / 刷新任务”入口。
- Done 任务仍可通过筛选显示,但默认不抢占任务中心页面;移动端任务卡片更紧凑,突出 Task#、Plate、Type、Status,并在有值时显示 Done By / Done At 小字。
- `/ops/cleaning-upload`、`/ops/claim-upload`、`/ops/checkout-upload`、`/ops/tasks` 均已增加 `/ops/help` 使用说明入口。
- 新增 `docs/QP_OPS_UPLOAD_TEST_CHECKLIST.md` 作为上线前人工验收清单,覆盖 Cleaning、Claim、Checkout、Task Center 与 4021 / 4020 上线检查。
- 上传流程、Task# 生成规则、Done By / Done At 写入逻辑均保持不变;不影响 Finance、Guide-A、Owner Report、BookCars、Overview 写入或 Turo 自动提交。
- 下一步:先按清单验证 4021,确认无误后再决定是否同步 4020。

## 2026-05-31 当前状态补录:C2.1e Ops Upload & Task Center 4021 验收修复包

- 本次按 `docs/QP_OPS_UPLOAD_TEST_CHECKLIST.md` 对 Cleaning / Claim / Checkout / Task Center / Help 做收口验收修复,只处理明显 bug、UI 状态与链接/筛选问题,不扩展新业务功能。
- 已确认 `/ops/help` 可作为员工说明入口,并提供返回清洁上传、理赔上传、Checkout 与任务中心的导航;本次未改动该页面业务范围。
- 修复 `/ops/tasks` 的“全部任务”快捷按钮:前端点击后会清空日期筛选并显示全部状态;后端 `GET /api/ops/tasks` 现在区分“未传 date”(默认今天)与“传空 date”(全部日期),避免“全部任务”仍被锁在当天。
- `/ops/tasks` 的当前筛选提示增加日期上下文:默认显示 `Follow-up(YYYY-MM-DD)`,全部任务显示 `全部任务(全部日期)`,便于 4021 验收时判断按钮状态是否正确。
- Cleaning / Claim / Checkout 上传成功卡片已有 Task# 与“查看任务中心”入口,CallHandling 自动 Follow-up 逻辑保持原样;本次未改写上传主流程、Drive 上传流程、Overview 写入规则或 Finance 相关逻辑。
- 本次未修项 / 未扩项:未新增独立 Task 数据库、未新增复杂权限/状态机、未改 Finance、Guide-A、Owner Report、BookCars、Overview 写入,也未自动 merge 或部署到 4020。


## 2026-05-31 当前状态补录:C2.1g Business Validation

- 当前进入 **C2.1g Business Validation(Ops Upload & Task Center 真实业务验证)**,任务类型为 B 档业务验证,不是新增功能开发。
- 验证范围为 Cleaning Upload、Claim Upload、Checkout Upload 与 Task Center,目标是确认员工能在真实业务中独立完成上传、Task# 反馈、Follow-up 查看和 Done 闭环。
- 已新增 `docs/QP_OPS_REAL_WORLD_VALIDATION.md` 作为真实业务验证记录表,覆盖 Cleaning / Claim / Checkout / Task Center 检查项、问题等级和 4020 上线标准。
- 当前暂停新增业务功能:不改 API,不改 Finance,不改 Guide-A,不改 Owner Report,不改 BookCars,不改 Overview。
- 阶段原则:先验证、后上线;只有满足连续 3 天真实使用、Cleaning >= 10、Claim >= 5、Checkout >= 5、Task Center >= 20、无 BLOCKER、无未修复 MAJOR、员工可独立完成后,才建议同步 4020。

## 2026-05-31 当前状态补录:C2.1f Roy UX Round 1(A档 UX 优化)

- `/ops/cleaning-upload`、`/ops/claim-upload`、`/ops/checkout-upload` 已完成 Roy 第一轮 UX 收口:顶部主导航只保留三类上传入口,`使用说明` 改为标题说明下方小号蓝色链接。
- 三页已删除“停车场逻辑”说明块;页面不再展示开发解释文本,锁车后的系统位置 / 实际位置提示仍保留在车辆信息区。
- 顶部日期与提交人已收口为同一行,减少首屏空白和滚动距离。
- 三页提交区新增默认勾选的 `同时创建 Follow-up 任务(推荐)`;取消勾选时仍写 Cleaning / Claim / Checkout Submission,但跳过 Task# 生成、CallHandling 写入和 Task Center 入口。
- 勾选时 Task# 规则和 Task Center Lite 行为保持不变;本次不影响 Finance、Guide-A、Owner Report、BookCars、Overview 写入、Drive 上传逻辑、Done By / Done At 或 MD 同步。

## 2026-05-31 当前状态补录:C2.1f-3 CallHandling 字段与文案收口

- Cleaning / Claim / Checkout 上传后写入 `CallHandling` 的 Status 已从 `Follow-up` 改为 `Waiting Reply`,Task Center 页面显示可用“等待处理”。
- 自动创建任务时 `Agent` 列保持留空,不再写 Roy / Geng / Henry / Tan 等提交人;提交人信息继续保留在各 Submission 表和 `RawPayload` 中。
- `Description` 已按三个流程统一简化:开头带提交人姓名,不再显示 `备注:`,没有备注时不追加备注字段,也不会出现 `备注:无`。
- `To do` 列只写 Drive 文件夹 URL,不再写“链接:”或“下一步:”。
- `createTask=false` 的跳过逻辑保持不变:不写 `CallHandling`,不生成 Task#;Task# 仍写入 `Phone#` / `Phone` 列。
- Task Center 默认识别 `Waiting Reply` 并可从 `Waiting Reply -> Done`;同时兼容旧 `Follow-up` 自动任务,避免历史记录不可见或无法 Done。
- 本次不影响 Submission 写入、Drive 上传、Finance、Guide-A、Owner Report、BookCars、Overview 或 Turo 自动提交。

## 2026-06-01 当前状态补录:C2.1f-4 Checkout Description 异常优先

- Checkout 上传后写入 `CallHandling.Description` 已改为异常优先短格式;无异常时只显示“无异常”和 Checkout 里程,例如 `Henry还车检查;无异常,里程:169999`。
- 有异常时才显示异常内容,并按超里程、缺油、理赔候选、位置变更、员工备注合并为中文逗号分隔的短描述,例如 `Henry还车检查;异常:超里程85,缺油,理赔候选:清洁;里程:169999`。
- `Checkout_Submissions` 和 `RawPayload` 仍保留 checkinMileage、checkoutMileage、drivenMileage、allowedMileage、overMileage、fuelLevel、lowFuel / fuelShortage、claimCandidates、note 等详细字段;本次只简化 `CallHandling.Description`。
- 本次不改 Cleaning / Claim,不改 Drive 上传,不改 Checkout_Submissions 字段,不改 Task# 规则,也不改 Task Center 主逻辑;Task Center 仅自然显示新的 Description。