Xero and Invoice Workflow
Invoice generation, invoice item sources, Xero OAuth, and submission behavior.
Invoice objects
Invoices are represented by:
| Entity | Role |
|---|---|
PayrollInvoice | Header record for client/project period, status, invoice number, totals, notes, Xero reference, and creator. |
PayrollInvoiceItem | Line record sourced from a timesheet or expense. Stores source id, project, description, quantity, unit rate, amount, and sort order. |
Invoice statuses are:
draft, pending, generated, approved, submitted_to_xero, paid, voidEligibility
PayrollInvoiceService looks for:
- approved timesheets in client/project/week scope
- approved expenses in client/project/date range scope
It excludes records already linked to an invoice item where the invoice is in a blocking status:
draft, pending, generated, approved, submitted_to_xero, paidA void invoice does not block a source timesheet or expense from being regenerated.
Timesheet invoice amount
Timesheet invoicing has a two-path calculation:
If current TimesheetCalculation.billTotal > 0:
amount = calculation bill total + material total
Otherwise:
amount = total hours x matched client base rate
+ normalized allowance total
+ material totalThe first path is preferred because it uses the current award calculation snapshot. The fallback path exists for older or uncalculated timesheets.
Expense invoice amount
Expense invoice items use the approved expense amount. The expense line is separate from timesheet labor, allowance, and material totals.
Materials and allowances in invoice fallback
When falling back from award bill total, PayrollInvoiceService normalizes selected materials and allowances:
- Materials are matched against active
ClientMaterialrows by id or normalized name. - Selected materials without a match still appear, but amount defaults to 0.00.
- Calculated allowance lines are preferred over raw selected allowance payloads.
- If no calculated lines exist, it falls back to time-entry allowance selections and then
Timesheet.location.allowances. - Project allowance rates override client allowance amounts when a matching project allowance row exists.
Xero OAuth and submission
Xero OAuth routes are:
/xero/auth/xero/callback/xero/test/xero/disconnect
API submission routes include:
/api/xero/timesheets/{id}/submit/api/xero/expenses/{id}/submit/api/xero/timesheets/submit-batch/api/xero/expenses/submit-batch
Xero services store submission timestamps, references, and errors back on the domain records so portals can show current integration status.