---
name: ar-hexiao-daily
description: >-
  应收核销日清：编排出纳李明妹每天回款核销（智云取数、核销判定、核销日清清单、
  日清后统一写盈亏明细 + 流转安全子集、挂账重扫）。必须先生成《核销日清》并通过写前校验，
  随后直接写工作副本，无需另行询问确认。当用户说「跑昨天的核销 / 做核销 / 应收核销 / 回款核销 / 核销清单 /
  挂账还有哪些没做 / 日清 / 昨天到账核销 / 重扫挂账 / 收入提取 / 拉智云 / 抓核销 /
  导智云 / 回填审核 / 确认回填 / 可以写了 / 按这个写 / 跑X月X号的核销 / 补上周的核销 /
  哪几天没跑 / 有没有漏的天 / 补跑核销 / 把没跑的都跑了 / 这几天的一起做」，用本技能。
---

# 应收核销日清（SOD 级 · 日清后自动写工作副本）

**主战场从第 6 步开始**：智云按核销日筛 → 判定 → 准备流转定位计划 → 校验 → **《核销日清》** → 独立写盈亏明细 → 尽力回填流转状态。
1–4 她提才做；第 5 步销售不绑隔天。

**取数只有一个入口**：财务管理 →「回款记录」，主表按目标核销日筛，再抓每笔明细（下单；下单为空时回查结算 / 同币种核销明细 / 订单明细 SOD）。
**最新核销日显示机制**：父回款记录只出现在最新一次核销日。每天正常按日做不会漏；如果漏跑历史日，父记录后来又核销而移到新日期，则从累计子明细按真实核销日还原，生成增补日清。同一 SO 的前后两次回款可能属于不同父 AR，取数必须按 SO 全局补取截至目标日的历史核销，累计时不得再按当前 AR 隔断。
**「回款核销对账」已废弃**（预存静默丢单）。

**数据源**：第 6 步智云 = 核销金额真相；流转表 = 备份 + 单号 + 是否更新，**金额不从流转推**。
**写表**：盈亏只动工作副本「明细」；流转在强三键唯一命中后按§3.2登记月份行、单号、SO交付金额和按核销额扣减的预收公式。流转匹配先按到账日期＋到账金额筛选；收款形式为 PayPal 或美元户且金额格为 `原币金额*流转汇率` 时，金额键改用公式中的原币金额与智云原币到账额比较，不比较双方汇率换算后的本币金额。金额候选确定后，再用智云销售名称或客户名称匹配流转表公司名称或汇款人，四种直接名称组合任一成立均算名称命中；PayPal/美元户付款方是英文时，再读取表头为「到账名称」「系统客户名称」的对照表，把英文到账名称转换为中文系统客户名称后与智云客户名称比较。对照缺失、空目标或一对多时不猜，仍需人工处理；最终必须只剩一行。「单号」格按 `SO  交付金额` 写，交付金额取SO最新本币交付额；预收按本笔实际核销额生成完整数字扣减公式，两种金额分别保存和校验。
**永不写智云。** 金额只由 `scripts/*.py` 算。

**交付额变动口径（2026-07-29）**：

- 盈亏表原始应收是历史基线；智云最新实际交付额 `D` 是计提与剩余应收真相源。
- 仅当同一父回款、同一核销记录NUM的完整多 SOD 集合属于同一 SO，并且全部命中盈亏同一行，且 SOD 本次核销合计、SOD 交付额合计都等于 SO 交付金额时，允许合并核销这一行：实收 SOD 保留全部编号，应收、计提和回款明细统一写 SO 交付金额。该场景是“原始应收不覆盖”的唯一例外；缺记录号、集合不完整、金额不守恒或跨父回款仍挂账。
- 部分回款实际未收 `U = D - 累计实际回款 R`，禁止用旧应收减回款。`|U|<=1.00`
  时按业务结清尾差处理：实际回款保持原值，记录精确差额，不新增未回款行；超过 1.00 元才拆行或按超收规则挂起。
- 人工拆行后原始应收合计必须保持不变：未收行应收=`U`，已收侧应收合计=`原始应收合计-U`。
- 回款明细写本次实际回款。部分回款在日清与写前校验通过后，自动把当前未结清行转为已回款行，并在其正下方新增未回款行。
- 累计回款 `R < D` 时两行计提都留空；只有 `R = D` 时，最后结清行计提填 `D`。
- **同一 SO 含多个不同 SOD 时，计提再加一层 SO 级闸门**：只有该 SO 的完整 SOD 集合全部核销结清，才允许填写任何 SOD 的计提。前面的 SOD 已结清但同 SO 仍有未结清、缺失或交付额不明的 SOD 时，已结清行的计提仍留空并带 `W_SO_ACCRUAL_DEFERRED`。最后一个 SOD 结清时，同一次计划按智云各 SOD 最新本币交付额补填此前已结清 SOD 的计提；一个 SOD 拆成多行时只在最后一条已结清业务行计提一次。已有非空计提与智云交付额不一致时禁止覆盖并转冲突。完整多 SOD 共用同一盈亏行的合法合并场景仍只按 SO 交付金额计提一次。
- 本批只核销同一 SO 的部分 SOD、但写完后使整个 SO 全部结清时，检查历史待补计提 SOD 的月份。优先读取当前工作区以前日期的《判定结果》；缺少历史日清时，直接用盈亏表“收款时间”判断月份。判断月份与本批月份不同的，在本次处理结果中提示涉及的跨月计提补填数量、月份待确认项和冲突项；该 SO、本次 SOD、历史 SOD、历史日期/月份、日期来源、补填金额、目标年度/行和写前校验结论保留在判定及校验记录中。历史日清和收款时间都缺失或无效时才标“待确认”。
- 最终结清且原始应收 `B0 ≠ D` 时，原始应收不改，差异列写公式“应收金额-计提金额”，
  同时无损保存缓存值 `B0-D`（保留到分，不得按有效数字截断或舍入）；公式必须按写入后的实际行列动态生成。
  应收与本次核销不一致时必须先查该 SO 的最新实际交付额再判断结清或拆行。
- `R` 按智云同一 SO/SOD 截至目标日的有效逐单核销明细，加上此前已成功写表且对应父 AR 没有逐单明细的顺序分配台账共同计算。本次核销只是本次回款明细，不能替代累计值；同一 SO 跨父 AR、跨“父回款兜底/逐 SO 明细”来源的历史回款都必须合并。同一父 AR 后来取得逐单明细时排除其旧兜底记录，禁止双计。
- 逐 SO 核销金额无法唯一落到多个 SOD 时，按盈亏“明细”行号从小到大，从该 SO 的首个未结清 SOD 开始顺序核销；当前 SOD 按最新交付额核满后，余额继续进入下一个未结清 SOD，最后不足的 SOD 按部分回款拆行。各 SOD 分配金额合计必须等于本次逐 SO 核销金额；缺交付额、累计超收、全部未结清 SOD 可承接金额不足或拆行不守恒时整笔挂账，禁止只写前半段。
- 加载父回款后立即识别“整笔回款”，但必须先加载其全部关联订单再执行父 AR 金额守恒检查。父总到账优先使用智云明确返回的“总到账金额”，该值直接用于审计，不再减去手续费、税费或其他费用；仅当该字段缺失时，才按 `净到账 + 明确手续费 + 明确税费 + 明确其他费用` 计算，禁止用税率或固定比例反推。整笔回款优先按各订单“订单已核销金额”合计与父总到账比较；所有订单该字段都缺失时，才允许用完整、可比的订单交付额合计兜底。智云已明确返回父回款原币总到账，且关联订单的原币金额完整并属于同一种订单币种时，父 AR 审计直接比较原始数值合计；即使父回款与订单币种标签不同，也不为该项审计套用订单汇率。部分订单有已核销金额、部分缺失时禁止混算；父总到账低于首选口径或兜底口径超过 1 元时，整笔父 AR 及其全部关联 SO 以 `E_PARENT_WRITEOFF_MISMATCH` 挂账，禁止进入 SOD 匹配和写表。父总到账高于订单金额合计属于正常预收，超出部分保留为父回款未分配金额，后续核销继续使用，不得分摊进当前 SO/SOD。交付额兜底通过时逐 SO 金额取各订单交付额并记录 `W_WHOLE_PAYMENT_DELIVERY_FALLBACK`，不得进入父回款瀑布分配。非整笔回款没有逐 SO 本次核销金额时才回退父回款总到账，再按交付额升序从首个未结清订单续核；禁止均分或比例分摊。
- 跳过和异常必须给出本条证据：SO/SOD、核查年度/行、实际与期望金额及状态、无法继续的原因和处理动作。SOD 历史归属冲突用 `E_SOD_HISTORY_MISMATCH`；不得把同 SO 的其他 SOD 历史回款借入当前 SOD，不得因 SO 总额对平自动重分配历史。超收提示不再附普通部分回款的拆行指令。整单跳过在写前复核全部业务行，挂账重扫标记已完成并保留原 E 码；流转状态仍以校验及执行结果为准。
- 父回款“下单”关联为空时，必须继续回查同一父回款的“结算”关联提取 SO；结算也无单号才判无关联订单。先按项目交付日期选定年度盈亏表，再检查该 SO 的全部业务行（含同 SOD 拆分行）。至少存在一行且所有行“是否结账”均为“是”时，以 `OK_SO_ALREADY_SETTLED` 整单跳过；保持历史金额、计提、收款日期和方式，不新增拆分行、不补计提。此状态不等于本批回款已逐笔写入。作废、父 AR 金额守恒失败和无法确定交付年度仍保留原异常。当前来源新增 SOD、交付额与历史应收差异等保留为来源提示。SO 仍有未结账行时，继续按既有本批金额、日期、方式及累计回款规则判断是否已填；仅目标 SOD 已结账而本批事件证据不匹配时保留 `E_SETTLED_CURRENT_EVENT_UNCOVERED`，列出期望值和历史值。
- 订单交付年度只读取智云“下单”订单详情中的“项目交付日期”，禁止从 SO/SOD 编号、下单日期或其它字段推测。项目交付日期缺失或冲突时分别以 `E_DELIVERY_DATE_MISSING` / `E_DELIVERY_DATE_CONFLICT` 挂账；日期明确后只在对应年度盈亏工作副本中定位和写入。对应年度表存在且订单唯一命中时正常核销，缺少该年度工作副本或该年度表中没有订单时以 E3 挂账。一个核销日涉及多个交付年度时，各年度表分别完成写前指纹、写入、备份和回读；流转按月登记必须等全部年度盈亏写入并回读成功后执行。
- 无逐 SO 明细的父回款只有在盈亏写入成功或幂等确认已存在后，才写入 `03_台账/父回款顺序分配台账.json`。同一父回款重跑必须复用原分配；部分回款已拆行落表时，即使仍有未结账承接行，也按拆分组累计已收识别本父回款已落表并幂等跳过，承接行只留给后续新的父回款。有逐 SO 累计核销真相时同样比较拆分组表内累计已收，已覆盖目标累计就跳过，不得把本次金额再次写入未结账行。若总到账、币种口径或关联订单变化则挂起，禁止移动游标或覆盖历史。
- 核销明细先按“核销记录NUM”识别同一物理记录的跨快照重复；不同记录号先保留为不同原始记录。缺记录号时禁止用业务字段冒充物理唯一键。
- 非整笔回款有逐 SO“本次核销金额/本币”时优先使用逐单金额；没有本币金额时使用同币种逐 SO 原币金额。随后必须核对父回款总到账：原始明细合计未明显超过父总到账时全部保留；超过 1 元时，只允许在同一父 AR 内按相同 SO、金额和币种识别精确重复组，每组保留一个核销记录NUM。折叠后仍超过 1 元、没有精确重复组、缺记录号或金额币种不可比时，整笔父 AR 挂账。整笔回款继续按“订单已核销金额→全部缺失才用交付额”执行父 AR 守恒检查。
- 非整笔回款没有有效逐 SO 金额时，才回退父回款总到账并按既定交付额升序未结清瀑布分配；仍禁止均分、比例分摊或用业务字段猜测删除明细。
- 同一 SOD 已经拆成多行时，`B0` 是这些拆分行应收的合计，不是本次命中的单行应收；由此判断是否需要业务值差异。
- 智云有逐 SO“本次核销金额本币”时优先使用；没有本币列但有“本次核销金额”时直接使用，
  不再反向要求父回款汇率，也不因父回款与订单币种文本不同挂起。
- **盈亏表金额统一为人民币本币**：外币订单在没有逐 SO 核销明细时，交付额、计提和回款明细
  必须按订单行汇率换算为本币（优先使用智云本币金额）；禁止把 USD 等原币数直接写入盈亏表。
- 有逐 SO“本次核销金额”时原样使用，手续费/税费只保留为父回款总额审计，禁止二次加到逐单金额；非整笔回款没有逐 SO 金额时，费用并入父回款总到账后按剩余未收顺序分配。费用字段为负、外币费用无法换算或口径不可比时挂起，不猜。
- 禁止用 SO/AR 白名单、点名单号或上传盈亏表改变本次核销金额。上传表只用于写后离线差异分析，
  用来发现规则缺口，不能覆盖智云判定、已有非空值或冲突。
- 细则见 `config/业务规则.md`。

## 0. 按她的话直接跳

| 她说的话 | 直接做 | 命令链 |
|---|---|---|
| 跑昨天的核销 / 做核销 / 回款核销 | 自动解析核销日并查漏天 → 自己取数→判定→准备流转计划→校验→日清→独立写盈亏→尽力回填流转状态 | 见 §3.1 |
| 只出清单 / 只预览 / 不要写表 | 跑到日清后停止，不执行 apply | 见 §3.1 上半 |
| 跑 X 月 X 号的核销 / 补上周的 | 同上，日期用**她说的那天**，不再二次确认 | `--date <那天>` |
| 把没跑的都跑了 / 这几天的一起做 | **§0.45**：自动列出日期 → **从早到晚一天一天跑几遍** | 每天走一遍 §3.1 |
| 哪几天没跑 / 有没有漏 | 查漏天 | `batch_ledger.py gaps` |
| 拉智云 / 导智云 | 取数进 01_ | `fetch_zhiyun.py --date <核销日>` |
| 挑收入 / 日记账 | 第 2 步（**按到账日，不是核销日**） | `extract_income.py` |
| 挂账 / 重扫 / 空的和部分 | 重扫 | `rescan_holds.py --ledger …` |
| 我文件放好了 / 缺什么 | 盘点 | `inspect_inputs.py` |

**「跑昨天的核销」= 完整执行到工作副本写入和复核；只有她明确说“只出清单/不要写表”才停在日清。**

## 0.4 ★ 接到指令后固定核销日，不再二次确认

**这条链路有两个互不相干的日期，混了就是做错账：**

| 日期 | 是什么 | 驱动哪几步 |
|---|---|---|
| **到账日期** | 钱哪天到的银行 | 第 1–4 步（日记账 / 挑收入 / 流转表 / 建回款） |
| **核销日期** | **销售哪天在智云把这笔钱核到订单上** | **第 6 步起的主战场（本技能默认说的就是它）** |

她的口径原话：「与建回款无固定隔天关系；核了就进那个核销日，没核就进更后的日期」
→ **两者天然不是同一天**，可能差好几天。所以：

1. **先查漏天**：`batch_ledger.py gaps`。有从没跑过的核销日，程序在内部按最早日期到目标日期的顺序补跑；
   不把多个核销日混成一批，也不在中途询问是否继续。
   > 为什么必须查：`--date yesterday` 是相对**运行那天**算的。她周一跑取的是周日（销售周末不核销、必空批），
   > 周二跑取周一——**中间漏掉的那几天永远没人管，程序一声不吭**。请假、出差、故障同理。
   > 漏一天 = 那天的到账永远不会回填进盈亏表，事后也看不出来。
2. **把日期在任务内部固定下来并立即取数**：用户说了具体日期就用具体日期；说“昨天”就按运行时解析为前一天；
   说“上个工作日”就跳过周末。日期只在入口解析一次，禁止在取数、判定、校验或写入之间再次询问。
3. **一次只跑一个核销日**。禁止把几天合成一批：混批会让 AR 覆盖率校验、幂等校验
   和她对着清单逐行核对**全部失真**（她核的是"这一天的到账"）。程序也会直接拒绝。
   **要补多天 → 你自己跑多遍，见 §0.45**，不是把几天塞进一批。
4. **取数 0 笔 ≠ 出错**：那天销售一笔没核销就是空批，如实说「这天没有核销，已记台账」，
   别让她以为没跑成。
5. **正常日清不会因后续再次核销而漏**：原核销日当时已经处理；只有历史日没跑或旧判定结果缺键时才启动迁移还原。

**所有产出（判定结果 / 日清 / 文件名）一律按核销日命名**，不按"跑的那天"——
她补跑 7-22 时若按运行日命名，会跟今天那批撞名甚至盖掉。

## 0.45 补多天：先规划 → 一天一天跑几遍

**她不是天天来**（约一周两天，看她哪天有空），一来往往积了好几天的核销。
处理办法是**你多跑几遍**，不是把几天合成一批。

**顺序钉死：从早到晚。** 因为同一个订单可能**分两天核销**（7-21 核一半、7-23 核另一半），
两笔填的是她表里**同一行**——跨核销日仍先跑早的写进去，晚的那天再来时才看得到"已经填了一半"
接着算；跨日顺序反了会抢同一行。**同一核销日内**若同一 SO/SOD 由不同父回款依次核销，必须按核销记录NUM确定顺序，逐笔建立分笔回款拆行链；每个父 AR 保留独立业务行，禁止合计后覆盖成一行。

**你的动作**：
1. `batch_ledger.py gaps` 在内部确定补跑范围。
2. **依次跑**：从最早漏跑的工作日开始，第 1 天走完整主路径（判定→日清→写入）→ 再跑第 2 天……
3. 对话只在任务完成后报告实际处理范围；运行中不请求确认、不让用户选择下一天。
4. 全部日期写完后运行 `build_task_reports.py --date-from … --date-to …`，只生成一份整合《核销日清》。工作簿仅保留 `任务范围`、`回款明细`、`流转表怎么填` 三个工作表；首页汇总全部核销日期，回款明细和流转填写页按行增加“核销日期”并合并各日内容。跨月计提补填在本次处理结果中提示，不另设工作表；页面不展示流转统计，填写指引集中在日清的流转表怎么填中。整合表校验成功后自动删除本批已选日期的日期级《核销日清》《变更清单》《订单写入差异》Excel；判定、计划和台账等非 Excel 审计文件继续按日保留。
5. 发生缺凭据、缺表、写前指纹变化或无法安全判定时，立即停止受影响日期并在结果中说明原因，不通过提问绕过安全闸。

⛔ 不许为了省事把几天并批；⛔ 不许跳过中间某天直接跑最新的那天。

## 0.46 父记录按最新核销日迁移：补跑时还原

智云父回款只显示在最新一次核销日；子表保留每个订单各自的历史核销日。

1. **每天正常做**：只跑当天目标核销日；后续再核销不会让已经写过的历史行丢失，不做全历史追扫。
2. **补跑漏日/连续多日**：对明确日期范围跑 `audit_shifted_details.py --date-from … --date-to …`。
3. 报告 `needs_rerun=true` 的日期从早到晚逐日重跑 `classify → validate → worklist`；程序从更新日期文件的累计子明细还原原核销日。
4. 幂等校验跳过已写行，只把新增/冲突行放进增补清单；增补日清与写前校验通过后直接写工作副本。
5. 只有本次目标日来源覆盖 `AR/SO = 100%` 才允许说“这天完整”。

> ⚠ **顺序钉死：`validate_plan` 必须在 `build_worklist` 之前**（清单状态以校验为准）。
> ⚠ **`build_flow_plan` 在日清前跑**（或由 worklist 自动生成）；日清要展示流转自动写 M / 手填 K。

### 完整流程跑完 · 结尾照抄（一个字别改）

```
✅ 核销日期 <YYYY-MM-DD（周X）> 的核销处理完成
📁 《核销日清》：<核销日清_YYYYMMDD.xlsx>  ← 只看这一份就够
   · 盈亏：写入 N 行 · 已填过·跳过 S 行 · 冲突·安全跳过 C 行
   · 挂账待办 H 行 · 异常 K 行
   · 流转：自动写 M 笔 · 须你手填 F 笔
   · 第一列是单号，第二列是状态，「怎么办」写了每行该干嘛
🔒 智云没写；根目录基线没动；只写了本次工作副本（写前已备份、写后已回读）
📁 变更清单 / 订单写入差异：<对应产出路径>
📁 换电脑使用：<盈亏工作副本_便携版.xlsx>（无历史外链，不作为下一轮写入基线）
```

⛔ 禁止说「填进智云」。⛔ 禁止跳过日清和写前校验。⛔ 禁止让核销日期在任务中途漂移。

## 0.5 硬禁止

1. 禁止自写 Python 读她的 Excel；只准调 `scripts/`。
2. 禁止把客户名、账号、凭据打进对话。
3. 缺输入就停下报缺，禁止凑合。
4. **禁止跳过《核销日清》和写前校验直接 apply**；主流程生成日清后无需另行确认，直接写工作副本。
5. 流转**仅**强三键唯一命中（`hits==1` 且 matched_by 为直接强三键或中英文对照强三键）：先按到账日期＋到账金额筛选；PayPal/美元户的简单 `原币金额*流转汇率` 公式改按公式原币金额匹配智云原币金额。再以智云销售名称/客户名称匹配流转表公司名称/汇款人；四种直接组合任一成立算名称命中。付款方为英文时，读取「到账名称→系统客户名称」对照表，转换后仅与智云客户名称比较；缺失、空值、一对多、公式无法严格解析、弱命中、0命中或多命中都手填。
6. **禁止把「判不出来」悄悄跳过**：每笔到账及其每个 AR/SO 都必须进入 auto/hold/exception；两级覆盖率不过立即退出。
7. 禁止写智云；原流转行日期、金额保留，跨月新增行按§3.2写核销日期和结转余额；除§3.2月度流转拆行、“唯一命中 SOD”或“按已确认规则从同 SO 首个未结清 SOD 开始顺序核销”形成的最后一笔部分回款外禁止自动插行。
8. **禁止让日期漂移**：每次接到指令必须在入口确定「核销日期 = 哪一天」，后续所有取数、判定、校验和写入都沿用该日期；不需要用户二次确认。
9. **禁止把多个核销日合成一批**（程序会拒）；多日任务由 agent 从早到晚逐日执行。
10. **禁止在写入失败/复核没过时"绕过去再试一次"**——那说明工作副本在校验后发生变化，
    正确动作是**重新校验并重出日清后再写**，不是加参数硬写。

## 0.6 怎么跟她说话

**短 · 像人 · 自动推进。** 一两句说完；她是出纳不是程序员，长篇大论她不看。
缺输入、缺凭据或表结构异常时停止并一次性报告原因，不在任务中途追问。细则 → `references/跟明妹沟通.md`。

- ❌ 报脚本名/E 码/auto=143；❌ 解释原理；❌ 一次抛一堆问题
- ✅ 「处理完了：**盈亏写入 N、冲突安全跳过 C；流转自动写 M、手填 F**。清单和变更报告在 <路径>。」
- ✅ 多日任务只在完成后报告实际处理范围，不在运行中等待“开始”或“继续”。

## 0.8 判不准就挂账并报告

同 SO 全部未结清 SOD 不能完整、安全承接 / 结清差额超过 1.00 元且无法按既定规则处理 → 自动挂账并在日清、运行报告中说明原因，禁止在任务中途提问或猜测。跨年订单按智云项目交付日期自动查对应年度盈亏工作副本，日期缺失或冲突、缺表或缺单时挂账。

## 1. 红线

1. 金额只由脚本算。
2. 对话不回显客户名、账号或凭据。
3. 整笔回款先通过父 AR 金额守恒检查；有逐 SO 核销金额的分笔回款正常落单。同一核销日内同一 SO/SOD 的不同父回款命中同一盈亏行时，按核销记录NUM排序并逐笔拆行：本笔不足则写独立已收行并把剩余应收交给下一笔，只有运行累计达到最新交付额的最后一笔才计提并最终结清；全部本批回款后仍不足时，再保留一条未回款承接行。独立小额父回款合计不超过 1.00 元且全链结清时，按结清尾差处理：已有完整聚合结清行就保留并幂等跳过；新建链把小额父回款并入最后一笔正常业务行，不单独成行，但在计划审计中保留每个父 AR、金额和顺序。边界 1.00 元包含在内，多笔小额按合计判断；超过 1.00 元仍按父 AR 逐笔拆行。除该尾差例外外，每个父 AR 的回款金额、收款日期和收款方式必须独立保留，日清带 `W_SPLIT_PAYMENT_SEQUENTIAL`；跨核销日仍按日期顺序累计。非整笔回款缺逐 SO 金额时按“父回款总到账→交付额从小到大→首个未结清订单续核”的规则处理。禁止均分/比例分摊；同 SO 多 SOD 歧义按盈亏未结清行顺序核销，当前 SOD 核满后余额继续进入下一个，最后不足的 SOD 拆行。日清必须按“最新交付额 − 截至本父回款的跨父 AR 运行累计实际回款”计算未收并保持原始应收合计不变。
4. 永不写智云。
5. 写盈亏只许「明细」；写前备份、写后回读。
6. **回填**：日清与写前校验通过后，先执行盈亏写入和回读，再按§3.2登记月度流转。流转失败只转人工处理，保留已验证的盈亏结果。
7. 回填金额 = 第 6 步智云，不用流转表金额。
8. 列名模糊匹配；找不到列 → 报错。
9. **AR + AR/SO 两级来源覆盖率硬校验**；核销日清首页必须显示覆盖数、历史子核销还原行和交付额回补数。
10. 盈亏写入或回读失败时，不执行流转登记。

## 2. 工作区

### 2.0 写入副本的唯一基线（硬规则）

每次新跑或重跑，必须新建一个独立工作区，并把本次可能写入的每个年度盈亏权威基线分别复制到
`02_我的表副本/`；到账流转基线仍只复制一份：

```
<2026年盈亏权威基线.xlsx>
<2025年盈亏权威基线.xlsx>  # 本批有2025年交付订单时才需要
<到账流转测试副本.xlsx>
```

各年度盈亏权威基线由用户指定的下载版建立；下载原件只读，稳定副本固定保存为对应年度“权威基线”。
禁止把任何已跑过、已写过、名称含“重跑/结果”的工作副本再作为下一轮写入起点；
文件夹名称和哈希相同不能替代五个业务字段的空值/原始值核验。复制后先记录两份根文件和
两份新副本的 SHA-256，确认副本与根文件一致，才能开始 `classify → validate → worklist → apply`。
根目录两份文件永远只读；所有写入、备份和变更清单只允许落在新工作区的副本中。

```
工作区/
  01_智云导出/    ← 回款记录 / 订单交付 / 核销明细 / 订单明细
  02_我的表副本/  ← 盈亏、流转副本（日清与写前校验通过后自动写）
  03_台账/        ← 挂账台账 + **跑批台账.json** + **父回款顺序分配台账.json**
  04_产出/        ← 判定、写入计划、流转计划、核销日清、变更清单（**均按核销日命名**）
```

## 3. 流程编排（11 步）

每步三句：`✅ 做完了` / `📁 路径` / `👉 下一步 + 触发词`。

> **1–4 步按「到账日」走，6 步起按「核销日」走，不是同一天**（§0.4）。她今天说"挑收入"
> 指的多半是今天/昨天到的账；说"跑核销"指的是销售某天核销的那批。**别把两个日期串成一个。**

| 步 | 名称 | 谁做 | 入口 |
|----|------|------|------|
| 1–4 | 日记账→挑收入→流转→建回款 | **她做**（次要·按到账日） | 不提别串 |
| 5 | 销售核销 | 销售 | 不绑隔天 |
| **0.4** | **定核销日 + 查漏天** | **你(agent)** | `batch_ledger.py gaps` → 内部确定日期，直接执行 |
| **6** | 智云取数（按任务固定的核销日） | `fetch_zhiyun` 自动抓取 | → `01_` 四件套 |
| **6a** | 漏日补跑迁移审计 | 脚本 | `audit_shifted_details.py`（仅补跑/多日） |
| 6b | 核销判定（SOD 级） | 脚本 | `classify_hexiao.py` |
| 7 | 流转定位计划 | 脚本 | `build_flow_plan.py`，只生成计划 |
| **8a** | 写入前校验（盈亏） | 脚本 | `validate_plan.py` |
| **8b** | 《核销日清》 | 脚本 | `build_worklist.py` |
| **8c** | 统一写入 | 脚本 | 日清后 `apply_all`：盈亏写入与回读，再登记月度流转 |
| 9 | 挂账重扫 | 脚本 | `rescan_holds` |
| 10–11 | 核对/收工 | 她 | 比其它 sheet 总数 |
| — | 跑批留痕（哪天跑过/漏了） | 脚本(自动) | `batch_ledger` 三个阶段自动登记 |

### 3.1 主路径命令

**⚠ 照抄，别自己改路径、别加 `--workspace`。**
所有脚本默认就用技能自带的 `工作区/`，**不传最稳**。传了 `--workspace .` 这种相对路径，
产出会分家（判定落一处、日清落另一处），写入时流转计划找不到 → **只写盈亏、静默漏掉流转**。
（程序现在会自动纠正并喊一声，但别去踩。）她的表放在别处时，才传**绝对路径**。

```bash
cd "<本skill目录>"                # ← 只做这一件事，后面全用相对脚本名
HX=2026-07-24                     # ★ 由用户指令确定；不再等待确认

# ① 内部检查漏跑日期；有漏跑日期时从早到晚自动逐日处理
python3 scripts/batch_ledger.py    gaps

# ② 取数。由脚本自动从智云抓取；只有带有**当前取数版本标记**的四件套才会自动跳过；旧版文件默认强制重取。
#    认证只从本机凭据库、环境变量或 MD_PSS_ID 读取；不在流程中询问，也不写进命令行或文件。
#    明确使用新手导四件套时，加 --accept-unversioned-existing；不得默认复用无版本旧文件。
python3 scripts/fetch_zhiyun.py    --date "$HX" --force
python3 scripts/verify_sources.py  snapshot
python3 scripts/inspect_inputs.py
# 仅补跑/连续多日时：按任务确定的补跑范围审计父记录迁移，不追扫无关历史
python3 scripts/audit_shifted_details.py --date-from "$HX" --date-to "$HX"
python3 scripts/classify_hexiao.py --hexiao-date "$HX"   # 数据不是这天就退出，防取错日子
python3 scripts/build_flow_plan.py
# 兼容入口：月度流转 prefill 不写表，统一等待盈亏验证后的 status 阶段。
python3 scripts/apply_flow.py \
  --plan 工作区/04_产出/流转写入计划_校验后.json \
  --workspace 工作区 --phase prefill --in-place
python3 scripts/validate_plan.py                          # 判定结果与盈亏副本自动找
python3 scripts/build_worklist.py
# 日清生成并通过校验后直接统一写工作副本；只有明确要求“只出清单/不要写”才在此停止。
python3 scripts/apply_all.py \
  --checked 工作区/04_产出/写入计划_校验后.json \
  --ledger  工作区/02_我的表副本/<盈亏副本.xlsx> \
  --ledger-year 2025=工作区/02_我的表副本/<2025年盈亏副本.xlsx> \
  --in-place --flow-in-place
# 流转计划不传会自动取 工作区/04_产出/流转写入计划_校验后.json
# apply_all 先独立写盈亏并回读，再尽力登记和回填流转；流转失败只转人工，不阻断盈亏。
# 盈亏写入成功后自动生成《订单写入差异》；只核对本批实际写入订单及拆出的新增行。
# 差异判定排除“收款时间”“收款方式”；这两列仍按规则写入并接受写后回读校验。
# 与人工/上传盈亏表做离线对比时使用 compare_ledgers.py：先按 SO+SOD 分组，
# 再优先按计提/回款/结账做最小差异配对；报告同时保留0.005技术结果、精确差额和1.00元业务结果。

# 连续多日全部完成后运行一次；各日期仍必须从早到晚分别判定和写入。
# 整合《核销日清》成功后，本批已选日期的日期级同类 Excel 会自动删除，最终只交付这一份整合表。
python3 scripts/build_task_reports.py --date-from "<开始日期>" --date-to "<结束日期>"

python3 scripts/verify_sources.py verify
```

多日任务中，`classify_hexiao.py`、`validate_plan.py`、`build_flow_plan.py`、`build_worklist.py` 必须传入当前日期对应的显式输入和输出路径，不得依赖“最新文件”猜测。长期工作副本保留内部公式和历史外链公式；便携版只把历史外链公式转换为缓存值，并按剩余公式重建计算链。交付的所有 Excel 逐个运行 `python D:\BESTEASY\financial_pj\tools\xlsx_lightweight_audit.py <文件路径> --strict`。

`--confirmed` 仅为旧命令兼容参数，不再是写入条件。用户明确说“只出清单/不要写表”时不得 apply；普通核销指令在日清和写前校验通过后直接 apply。

**写入前程序会自己再核一次**（工作副本在“校验 → 写入”之间发生变化就拒写）：
盈亏比**指纹 + 每行 SO/SOD 身份**，流转比**命中行的日期/公司/金额**。
报「写入前复核没过」= 工作副本变了 → **重跑 validate + build_worklist 出新清单后再写**，
⛔ 不许加参数硬写、不许只跳过报错那条（插一行会让它之后的全部错位）。

### 3.2 到账流转按月登记与预收结转

#### 盈亏材料缺少订单时先登记订单信息

E2/E3 挂账仅说明当前任务材料缺少对应明细，不能据此认定未交付。日清及写前校验通过后，流转行强三键唯一匹配、SO 和本币交付金额依据明确且无冲突时，可在原到账行的单号格追加待处理订单。保留原有内容及颜色；相同 SO 和金额不重复追加，金额变化、已有金额无法解析或匹配不唯一时转人工核对。

订单预填只改单号格，另存待处理依据；不新建核销完成事件，不扣预收余额，不改原有完成状态、日期和到账金额。后续盈亏实际写入并通过回读校验后，才按已验证核销金额更新余额和完成状态；仍有待处理分项时保持部分完成。金额复核必须使用相同口径，不能把交付额与部分回款金额直接比较。

历史任务不随代码更新自动补写。补填须使用当前材料的独立副本、限定回款范围、生成写入计划并校验前后差异，核对历史内容保留和重复执行结果后再发布新材料版本，禁止整任务重跑。


执行顺序：盈亏写入并回读成功后，登记流转。本版本 `prefill` 保留兼容入口但不修改工作簿；`status` 统一登记核销、预收和月份行。禁止根据分类建议提前写流转。

原始到账仍按到账日期、整笔金额及名称强三键唯一定位。同年同月写当前月份行；跨月在最后一条承接行下复制新行，日期为本月首次核销日，金额为上一行剩余预收，收款形式为冲预收。旧行保留日期、金额、历史SO及余额，并追加转月标记；新行不重复登记上月SO。同月后续核销保留本月首次日期。

单号登记SO最新本币交付金额，同一SO只展示一次交付额，不按SOD或多次核销累加。预收独立使用实际核销金额，保留每次扣减项，使用完整数字公式，如 `=8000-3000-5000`，同时保存正确缓存。预收扣减不得替换为SO交付额、累计回款或计提。只有经验证的核销事项进入登记；纯订单结账状态跳过不证明本笔到账已处理。登记行的是否更新应收款为是，未处理SO不提前登记或扣预收。

工作簿自带受控结转记录，关联AR、月份行、核销事件与金额。已登记事件重复执行不新增行、不重复扣款；同一事件金额变化、倒序补录、负数、超余额、跨币种依据缺失均转人工核对。缺事件号的已跳过项目，可通过已发布父AR逐笔记录及当前盈亏行确认身份；没有这类凭据时仍须有既有流转登记。盈亏已经处理而流转尚未登记的，经逐笔凭据核实后自动补登；仅整SO已结账不能代替本笔核销证据。人工旧行的单号金额按交付额保留，不与到账额或预收扣减额求和比较。历史扣减仅从有效预收数字公式或明确余额读取；还剩、剩余、余额文字前缀可以识别。已有SO但预收为空时，先核对已发布的父AR逐笔分配记录及实际盈亏行；本笔已验证核销事项能完整解释到账金额时，自动恢复完整数字预收公式。已有单号仅属旧版预填且全部金额归属于本次核销月份时，按月份规则自动迁移到承接行。未核实的历史金额继续保留人工原因。连续承接关系无法解释时保留原件并说明原因。

写入前验证全部已管理月份行的身份，插行后复核单号、日期、金额、状态、公式及缓存。支持普通筛选、筛选命名范围和同一行相对引用；涉及跨行公式、业务命名范围、表对象、受影响合并格、图形或条件格式等暂不能安全重定位的结构时转人工。平台仍对整个工作簿按固定计划重建并比较；写前逐笔判断流转可执行性，能唯一定位且写法、金额和防重依据完整的项目全部自动填写；单笔业务条件不足只将该笔列为人工，并记录文件、工作表、行号和具体原因。跨行引用等无法安全处理的结构仍保留人工判断。实际写入或回读失败时恢复已验证原副本，保留已验证盈亏结果。

实现：`vendor/scripts/flow_monthly.py`、`build_flow_plan.py`、`apply_flow.py`。用 `vendor/scripts/test_flow_monthly.py` 的合成工作簿覆盖同月、跨月、幂等及整表保护。

### 开关

- `--flow-complete`：渠道表齐了才严判 E0
- `--ledger`（rescan）：真重判挂起
- `--confirmed`：已废弃兼容参数，不再控制写入
- `--in-place` / `--flow-in-place`：就地写（写前备份）

## 4. 你（agent）怎么干

1. **先定核销日**（§0.4）：查漏天 → 在任务内部固定日期 → 立即取数。不要等待确认。
   要补多天 → §0.45：**从早到晚一天一天跑几遍**，别并批。
2. 盘点输入；正常日清不追扫全历史。补跑/多日任务必须按明确日期范围跑迁移审计，不能等她指出订单。
3. 分类后生成流转计划，继续校验、生成日清并执行统一写入；只出清单时停止在写入之前。
4. 写入顺序为：盈亏写入与回读 → 月度流转登记与回读。流转问题转人工处理，保留已验证盈亏结果。
5. 写入前复核没过 → **重新校验并重出日清后再写**，不许硬写。
6. 对话只报笔数/路径/成败/日期；缺凭据、缺表或规则无法安全判断时停止并一次性报告，不在处理中追问。
7. 依赖：`pip install openpyxl xlrd`；智云另需 requests/playwright。
8. 测试：`python3 -m pytest tests/ -v`（应 ≥186 例全绿）。

## 5. 验收

- pytest 全绿（含金标端到端，本地有测试数据时）。
- 无 `--confirmed` 时 apply_to_copy / apply_flow / apply_all 可正常执行；旧参数仍兼容。
- 日清与写前校验完成前源表哈希不变。
- **校验后被改过的表**：apply 非 0 且源表哈希**仍然不变**（一个字节没写）。
- 漏天可查：跑过 7-20、7-23 后 `batch_ledger gaps` 能报出 7-21/7-22。
- 多日文件共存时按 `--hexiao-date` 精确选主快照，不再默认取文件名排序第一份。
- 每批次最终只保留一份整合《核销日清》；首页列出全部核销日期，合并明细中的每行带完整核销日期。日期级判定 JSON、计划和台账不删除。
- 父回款因再次核销移到新日期时，补跑旧日能从累计子明细找到父回款并归回真实核销日；正常每日流程不误报。
- 订单交付额空白时，仅在该 SO 的 SOD 交付额完整、唯一、非空时用 SOD 合计回补；否则挂账，不猜。
- 来源覆盖按 AR 和 AR/SO 两级校验；同一 AR 少一个 SO 也必须整批报错。
- 每条原始核销记录必须有“保留 / 跨快照重复 / 系统重复忽略 / 撤销”之一；系统重复忽略只允许发生在父回款明显超核销且精确重复折叠后恢复到 1 元容差内的情况。审计指纹和逻辑金额由 `validate_plan` 复核，任何记录不得无原因消失。
- **金标 2026-07-22**：157 SOD 行级基线、可填与她手填一致路径不倒退。

## 6. 已知边界（不许夸大）

- 缺逐 SO 金额时若缺交付额、父回款为空，或父回款与订单交付无法形成统一本币/同币种原币口径：hold；同 SO 全部未结清 SOD 不能完整、安全承接时仍 hold。跨年路由只认智云项目交付日期；日期缺失或冲突时挂账，日期明确后只有缺少对应年度表或该表没有订单时才 hold E3。
- 取数版本必须为 `2026-09-03-delivery-local-v8`；旧版或无版本标记的自动导出必须重新取数。明确接受的旧手工导出若缺“核销记录NUM”，单笔逐 SO 金额仍可处理，但不能自动建立同日多父回款拆行链；缺“项目交付日期”时不得自动写入任何年度盈亏表。
- 父回款总到账优先使用智云明确的总到账金额；该字段缺失时才按“净到账 + 明确手续费/税费/其他费用”计算；逐 SO 本次核销金额存在时仍原样使用，费用不重复分配。外币费用无法确定本币或同币种原币口径时挂账。
- 有本次核销金额本币时优先使用；只有本次核销金额时直接使用。外币且无逐 SO 明细时，
  必须用订单汇率或可验证本币金额换算，拿不到则挂账，绝不把原币数字写进盈亏表。
- 流转弱命中/多命中：**手填**，不自动写。
- 盈亏同一行多笔命中：同一 SO/SOD、父 AR 各不相同且顺序与累计守恒时建立逐笔拆行链。不同 SOD 仅在“同一父回款 + 同一核销记录NUM + 完整 SOD 集合 + 两级金额均等于 SO 交付金额”时合并为一行并带 `W_SAME_SO_MULTI_SOD_AGGREGATE`；其余不同 SO/SOD、缺记录号、集合不完整、累计断裂或金额不守恒仍为 E8 挂账。独立小额父回款结清尾差规则保持不变。
- 拆行（E5）：日清按 `最新交付额 − 累计实际回款` 给方案；校验通过后在对应未结清行下方自动插入未回款行，并校验拆前拆后原始应收合计不变。
- 插行时，所有被下移业务行的普通公式必须按原单元格→新单元格的 Excel 复制语义完整平移；相对行列随行移动，`$` 绝对引用保持。禁止只替换“公式所在行号”，也禁止只看旧缓存值判断公式正确。
- 单格 shared master 被复制为新行 follower 时，master `ref` 必须扩展覆盖新单元格；写出前逐组验证唯一 master、master/ref 一致和所有 follower 均位于 `ref` 内，任何一项失败都禁止落表。
- 普通常量回填必须保留原计算链；插行、写入新公式或覆盖原公式时，先移除失效链，再根据工作簿内全部公式格和已有缓存值在生成端重建。交付文件必须满足：公式都有缓存值、`calcChain.xml` 存在、`fullCalcOnLoad=0`、`forceFullCalc=0`；禁止把全量重算留到打开文件的电脑。
- 盈亏工作副本含历史外链时，同时生成同目录同名 `_便携版.xlsx`：只固化外链公式的当前缓存显示值，删除 externalLinks 部件，保留其余公式、样式、图表和数据。便携版用于发送或换电脑打开，不得作为下一轮核销写入基线；长期工作副本仍保留外链和写前指纹规则。
- 交付额变了：计提目标按智云最新交付额，回款明细按实际回款，盈亏表原始应收基线通常不覆盖；只有上述同 SO 完整多 SOD 共用一行的合并核销例外改写为 SO 交付金额；
  最终结清时差异列写公式“应收金额-计提金额”。
- 部分回款：累计未达到最新交付额时，已回款行与新增未回款行的计提均留空；累计达到最新交付额时，只在最后结清行填计提=`D`。
- 同一 SO 多 SOD：单个 SOD 达到 `D` 只代表该 SOD 结清；同 SO 全部 SOD 都结清后才释放计提，并补填此前已结清 SOD。拆分 SOD 只在最后一条已结清业务行计提一次。
- 跨月补填提示：本批完成整个 SO 且历史空计提 SOD 不属于本批时，在本次处理结果中显示跨月计提补填提示，详细依据保留在内部判定及校验记录；月份优先取工作区既有日期级判定结果，缺历史日清时用盈亏表收款时间判断，二者都缺失时才标“待确认”。
- 部分回款阶段两行“差异”都留空；已有非空差异时禁止静默覆盖。旧表没有“差异”列且本次不需要写差异时继续兼容。
- 差异幂等：五项一致但差异空→只补公式；五项与差异都一致→跳过；差异非空但不一致→冲突。
- 同一 SOD 拆成多行时，业务值差异比较使用这些行的应收合计 `B0`；不得拿最后一次命中的单行应收与 `D` 比较。
- 与上传版生成差异表时，已配对行的公式先按两侧真实单元格坐标平移后再比较。仅坐标平移等价的公式单独汇总，不列为错误；平移后仍不等价，以及公式与常量不同，必须进入“公式需复核”。
- 与上传版或写后副本生成差异表时，“收款时间”“收款方式”不参与行是否一致、差异字段数或差异订单清单；这两列仍按业务规则写入，并由写后逐格回读校验。
- 收款时间/方式不看回款类型：到账月=核销月时填到账日期 +「汇」；到账月≠核销月时填核销日期 +「冲预收」。
- **结账**：能走到 auto 的 SOD 任务已做 →「是」（不得用整笔回款「预存部分核销」状态否掉每个小单）。
- **漏天检测的起点 = 台账第一次登记那天**，之前的历史不算漏（装上之前跑过的天要她自己认）。
- **周末默认不算该跑的日子**（`gaps` 会另行说明跳过了几个周末；要补加 `--all-days`）。
- **写入前复核只防"表被动过"**，防不了她把两份副本搞混——所以计划里记的是**文件路径 + 指纹**，
  换一份表就会报出来。
