# Tern Client Services: timesheet, progress bill, expense claim and work-in-progress documents

The billing pack a small professional services firm produces for one month: the timesheet in three formats, the fee schedule it prices from, the retainer the first two invoices are drawn against, a progress bill for the third, work in progress at a mid-month cut-off and its roll-forward, an expense claim with mileage, and the pipeline, quote, activity and contact exports behind them.

All parties, amounts and identifiers are fictional. Fixed snapshot: 2026-09-08. Every record is derived from the shared operating model `crm-services`, so identifiers join across this set and across the business-kit fixtures that use the same model.

## Reconciliation identities this set asserts

- hours times hourly_rate equals billable_amount on all 24 time entries, totalling 7200.00.
- The 3 invoices total the same 7200.00, so every recorded hour is billed exactly once.
- The retainer of 4000.00 is drawn to 0.00 by SVCINV-1 and SVCINV-2, leaving 3200.00 payable in cash on SVCINV-3.
- Work in progress rolls forward from 0.00 to 0.00: everything added in the period was transferred to billed.
- The expense claim of 221.57 allocates by project without residue and is the expenses column of project-profitability.csv.
- Won deals total 9000.00, the sum of the three project budgets.

## Files

| File | Format | Validity | What it is |
| --- | --- | --- | --- |
| `timesheet-export.csv` | csv | valid | Timesheet export CSV |
| `timesheet-export.json` | json | valid | Timesheet export JSON |
| `timesheet-export.xlsx` | xlsx | valid | Timesheet export workbook |
| `timesheet-PROJECT-3.pdf` | pdf | valid | Project timesheet PDF |
| `fee-schedule.csv` | csv | reference | Professional fee schedule |
| `fee-schedule.pdf` | pdf | reference | Fee schedule PDF |
| `retainer-ledger.csv` | csv | valid | Retainer ledger |
| `invoice-register.csv` | csv | valid | Invoice register with retainer draws |
| `invoice-register.json` | json | valid | Invoice register JSON |
| `progress-bill-SVCINV-3.pdf` | pdf | valid | Progress bill PDF |
| `retainer-statement.pdf` | pdf | valid | Retainer statement PDF |
| `wip-report.csv` | csv | valid | Work in progress at 2026-08-15 |
| `wip-rollforward.csv` | csv | valid | Work in progress roll-forward |
| `mileage-log.csv` | csv | valid | Mileage log |
| `expense-claim.csv` | csv | valid | Expense claim with mileage |
| `expense-claim-mileage-rate-drift.csv` | csv | invalid | Expense claim whose mileage was paid at a superseded rate |
| `expense-claim.pdf` | pdf | valid | Expense claim PDF |
| `project-profitability.csv` | csv | valid | Project profitability |
| `utilisation-report.csv` | csv | valid | Specialist utilisation report |
| `pipeline-export.csv` | csv | valid | Sales pipeline export |
| `pipeline-export.xlsx` | xlsx | valid | Sales pipeline workbook |
| `quotes-export.csv` | csv | valid | Quote export |
| `activities-export.csv` | csv | valid | Sales activity export |
| `contacts-export.csv` | csv | valid | Contact export with quoted fields |
| `contacts-export-semicolon.csv` | csv | valid | Contact export in the semicolon dialect |
| `services-reconciliation.json` | json | reference | Professional services reconciliation assertions |

## Deliberate defects

These files are broken on purpose. Each one is a single named mutation of a correct file in the same directory, so a parser under test can be checked against both.

- **`expense-claim-mileage-rate-drift.csv`** The 3 receipted lines recompute. All 3 mileage lines fail: 48 km at 0.62 is 29.76 but the file states 27.84. The shortfall is 9.44, which is 236 km times the 0.04 difference between the two rates.

## Notes and limits

- All three projects belong to one client in this operating model, which is why the client_id column never varies. The pipeline export is the file with more than one company in it.
- Every time entry is at the standard rate. The out-of-hours and travel rates exist in the fee schedule and are marked used_this_period false so a rate-lookup test has a correct negative case.
- The internal COST rate is used only by project-profitability.csv. It is never billed and appears on no invoice.
- Sales activity minutes and billable hours are different measures and must not be added together. No activity in activities-export.csv is billable.
- Worker names are role labels, not people, and every contact and company is fictional.
