travel_subsidy
When the user uploads 发票.zip and 火车票.zip, use the included data tables to calculate eligible business-trip subsidy records, split related vs remaining files, create output workbooks, package two result zips, and report progress at every key step.
安装 / 下载方式
TotalClaw CLI推荐
totalclaw install github:LeoYeAI~openclaw-master-skills~travel-subsidycURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/github%3ALeoYeAI~openclaw-master-skills~travel-subsidy/file -o travel-subsidy.md# Travel Subsidy
Use this skill only when the user provides **two zip archives** named exactly:
- `发票.zip`
- `火车票.zip`
The archives contain:
- invoice / ticket files (`.pdf`, `.jpg`, `.jpeg`, `.png`, `.webp`)
- and at least one structured data table describing the corresponding files
This skill calculates which records can be used to support **出差补助** and produces two result zip packages.
## Goal
Process the two archives as follows:
1. Unzip both archives into a dedicated run directory.
2. Read the included structured tables.
3. Match each table row to its corresponding file by filename or stable file identifier.
4. Do **not** OCR the files unless the table is obviously unusable or missing required fields.
5. Build a chronological travel evidence set.
6. Infer travel city / route information:
- for train tickets: use the provided 始发站/到达站所在城市 fields directly
- for invoices: infer city from `备注`
- if it is a lodging invoice, determine the hotel city from the hotel name
- if it is an air-ticket-related invoice, extract route/city information from `备注`
7. Determine which records can support a valid 出差补助 claim.
8. Put the records/files related to 出差补助 into one folder.
9. Put all remaining records/files into another folder.
10. Produce two zip outputs:
- Zip 1: 出差补助计算表 + 出差补助相关文件
- Zip 2: 剩余文件 + 剩余信息整理表
11. Report progress to the user at every key node.
## Mandatory progress updates
You must give the user a visible progress update at every key node.
At minimum, send these updates:
1. `已收到发票.zip和火车票.zip,开始检查压缩包`
2. `压缩包检查完成,开始解压文件`
3. `解压完成,开始识别数据表和票据文件`
4. `已识别发票数据表与火车票数据表,开始读取结构化信息`
5. `结构化信息读取完成,开始建立文件与表格行的对应关系`
6. `对应关系建立完成,开始提取城市与行程信息`
7. `城市与行程信息提取完成,开始组装出差行程`
8. `出差行程组装完成,开始计算可报销出差补助`
9. `计算完成,开始拆分补助相关文件和剩余文件`
10. `拆分完成,开始生成出差补助计算表和剩余信息表`
11. `表格生成完成,开始打包输出文件`
12. `打包完成,准备回传结果`
13. `任务完成`
If processing many rows/files, also emit periodic progress, for example:
- `发票信息处理进度:X / N`
- `火车票信息处理进度:Y / M`
- `行程组装进度:K / T`
If any fatal or partial failure occurs, immediately report:
- which step failed
- which file or row failed
- whether partial outputs were still produced
## Input validation rules
Only use this skill if both required archives are present.
Expected exact filenames:
- `发票.zip`
- `火车票.zip`
If one archive is missing, stop and tell the user clearly.
Do not guess if filenames are ambiguous unless the user explicitly says which file is which.
## Working directory rules
Create a dedicated run directory under `{baseDir}/runs/`.
Example:
mkdir -p "{baseDir}/runs"
ts="$(date +%Y%m%d-%H%M%S)"
run_dir="{baseDir}/runs/travel-subsidy-${ts}"
mkdir -p "$run_dir/input" "$run_dir/invoice_zip" "$run_dir/train_zip" "$run_dir/work" "$run_dir/output"
Never modify the original uploaded archives in place.
## Archive extraction rules
1. Save or copy both input archives into `$run_dir/input/`.
2. Unzip:
- `发票.zip` into `$run_dir/invoice_zip/`
- `火车票.zip` into `$run_dir/train_zip/`
3. Protect against zip slip / path traversal.
4. Ignore hidden files, temp files, directory metadata, and macOS junk files.
## Structured table rules
Each archive is expected to include at least one structured table such as:
- `.xlsx`
- `.xls`
- `.csv`
Prefer structured tables over OCR or raw visual parsing.
### Table discovery
For each archive:
1. Locate the most likely data table file.
2. If multiple tables exist, prefer the one with:
- more rows
- column names related to filename / file identifier / remarks / date / amount / city
3. If no suitable data table is found, stop and report clearly.
### Row-to-file mapping
For every row, try to match the corresponding source file using one or more of:
- 原文件名
- 文件名
- 附件名
- 文件路径
- 唯一编号
- a normalized basename without extension
Do not silently drop unmatched rows.
Keep an exception list for:
- row found but file missing
- file found but row missing
- duplicate filename mapping
- ambiguous mapping
## Required source fields
### Common output-preservation rule
For both output workbooks, preserve as much as possible the following key fields from the source tables:
- 文件名
- 发票号
- 销售方名称
- 发票价税合计
- 项目名称
- 备注
If the source tables use different column names, normalize them into the above output columns.
### Train ticket table
The train ticket table is expected to provide or imply:
- 对应文件名
- 日期 / 出发日期 / 乘车日期
- 始发站所在城市
- 到达站所在城市
- 备注 or other supporting fields if present
- for those with "备注" as "差额退票" or "退票手续" or other related keywords, such ticket should not be counted into subsidy calculation, but instead should be recorded in the remaining set with a clear remark of "退票,不计入差补".
Use the city fields directly when available.
For train tickets, normalize the preserved fields as follows:
- `文件名`: the matched source file name
- `发票号`: if a ticket number / order number / unique ticket identifier exists, use it; otherwise leave blank
- `销售方名称`: always fill as `火车票`
- `发票价税合计`: preserve the fare / ticket amount if present
- `项目名称`: fill as `火车票`
- `备注`: preserve original remarks and append any matching / eligibility notes if needed
### Invoice table
The invoice table is expected to provide or imply:
- 对应文件名
- 发票号
- 销售方名称
- 金额 / 价税合计
- 项目名称
- 发票类型 or 票据类型 or 项目类别
- 开票日期 / 日期
- 备注
- 酒店名称 or item text if present
For invoices, city information must be inferred as follows:
1. If it is a lodging / hotel invoice:
- determine city from the hotel name
- prefer explicit city names already present in hotel name or remarks
- if hotel name contains a clear city prefix such as `上海...酒店`, use that city
- if city cannot be determined confidently, mark as unresolved rather than inventing
- plese noted that the resident date should also be extracted from "备注" rather than using "开票日期" since the invoice may be issued after the stay.
2. If it is an air-ticket-related invoice:
- extract route or city information from `备注`
- prefer explicit segment text like `南京-上海`, `上海至北京`, `MU5101 南京/北京`
- normalize extracted cities into standard city names
3. For other invoice types:
- use `备注` if it clearly contains travel city clues
- otherwise keep city unresolved
## City normalization rules
Normalize city names to stable city labels.
Examples:
- `南京南`, `南京站`, `禄口机场` -> `南京`
- `上海虹桥`, `上海浦东`, `上海南` -> `上海`
- `北京南`, `首都机场`, `大兴机场` -> `北京`
District handling for subsidy standard:
- `南京六合`
- `南京溧水`
- `南京高淳`
These three use the lower subsidy standard.
If a record only clearly indicates `南京` without the district, do not automatically treat it as 六合/溧水/高淳.
## Business rules for subsidy eligibility
Apply these subsidy rules:
- Standard subsidy:
- 南京市外:`200元/天/人`
- 南京六合、溧水、高淳:`100元/天/人`
### Evidence rules
1. **Same-day round trip**
- Must have evidence of outbound and return travel on the same date
- Examples:
- round-trip train tickets on the same day
- or other same-day round-trip evidence if clearly present in the tables
- If same-day round trip is established, that day can count as one subsidy day
2. **Not same-day round trip**
- Must have evidence of:
- outbound travel from 南京
- return travel to 南京
- and lodging invoice(s) for the trip
- If travel or lodging evidence is incomplete, do not include the trip in subsidy-eligible output unless the evidence clearly still satisfies the rule
3. **Driving / ETC**
- This skill only handles evidence present in the two uploaded archives
- If no ETC/car-related evidence exists in the structured data, do not infer self-driving eligibility
4. **No impossible overlap**
- A person cannot be in multiple places at the same time
- If evidence implies overlapping conflicting trips, flag them in remarks and exclude the conflicting portion unless it can be resolved deterministically
## Trip-building rules
Assume:
- departure origin is always `南京`
- the final itinerary eventually returns to `南京`
You must support multi-city loop itineraries such as:
- `南京 -> 上海 -> 北京 -> 南京