--- name: invoice-wrapup description: 铁路发票批次收尾:把交付目录里的发票 PDF 提取乘客姓名加进文件名,再把名单 xlsx 逐人标注开票状态并附上 PDF 超链接。当用户说"收尾这批发票""给发票 PDF 加姓名""名单里标开票状态/附发票链接""处理 output/<批次> 目录""invoice-wrapup"时触发。适用于一个批次跑完后、要交付名单前的整理动作。不负责:跑开票自动化本身(那是 invoice_tool.py 的 android 子命令)、生成名单/台账。 --- # 铁路发票批次收尾(invoice-wrapup) 一个开票批次跑完后,交付目录(通常 `output/<批次号>/`,可能还带一个 `手动/` 子目录放补开的发票)里散落着发票 PDF,名单 xlsx 还没标状态。这个 skill 把两步收尾动作固化下来。 ## 输入 - **PDF 目录**:一个或多个,含发票 PDF。两种文件名形态都支持: - 自动流水线:`YYYYMMDD_HHMMSS_真实姓名_脱敏名.pdf`(姓名已在名里) - 官方下载:`<长数字>-电子发票[ (n)].pdf`(姓名还没加,需要先第 1 步) - **名单 xlsx**:至少有「姓名」列(默认第 2 列),第一行是表头。 ## 两步流程 ### 第 1 步 · 给 PDF 加姓名 只对**还没有姓名**的 PDF(官方下载那种)需要。用现成脚本,从 PDF 正文里抽脱敏证件号后面的乘客名,插进文件名: ```bash # 先干跑看结果 python3 scripts/add_invoice_passenger_name.py "" # 确认无误再落地 python3 scripts/add_invoice_passenger_name.py "" --apply ``` `YYYYMMDD_...` 那种文件名里已带姓名,跳过本步。 ### 第 2 步 · 名单标状态 + 附链接 扫所有 PDF 目录建「姓名 → PDF」映射,在 xlsx 尾部追加两列:`开票状态`(已开票 / 未开票)和 `发票PDF`(文件名 + `file://` 超链接): ```bash python3 scripts/annotate_roster_invoices.py "<名单.xlsx>" "" ["" ...] ``` 例(本次的用法,主目录 + 手动补开目录): ```bash python3 scripts/annotate_roster_invoices.py \ "output/01/测试名单-成都(1).xlsx" \ "output/01" "output/01/手动" ``` 常用可选项(默认值通常够用): - `--sheet 名单` 指定工作表(默认第一个 sheet) - `--name-col 2` 姓名所在列(1-based,默认 2) - `--status-header` / `--link-header` / `--done-label` / `--missing-label` 改列名和标签文案 ## 收尾核对 脚本跑完会打印: - `matched rows`:匹配上发票的人数 - `roster without pdf`:名单里没找到发票的人 → 大概率是**没开成/漏开**,回报给用户 - `pdf without roster`:有发票但名单里没有的名字 → 大概率是**姓名不一致或多开**,人工核对 姓名匹配前会去掉空格和全角空格(`王 艳`、`王楚渃 ` 这类),但错别字/异体字不会自动对齐,落在 `without pdf` 里就要人工看。 ## 硬规则 - xlsx 是**原地改写**,跑之前确认是副本或已受 git 跟踪;本项目 `output/` 在 `.gitignore` 里,改坏了没有历史,先备份。 - 不删任何 PDF;第 1 步只重命名,且遇到重名会自动加 `_2` 后缀。 - 不覆盖原始发票资料含义,只往文件名/表格尾部**追加**信息。