Expense Management
En resumen
Expense Management handles reimbursement claims for umpires, officials and delegates with structured line items, attached receipt URLs, per-tenant travel and per-diem rates (Sweden 18.50 SEK per km, France 0.55 EUR per km), a five-state approval workflow from draft through paid, payout via the standard Payment pipeline and category-or-OrgNode reporting — every state change written to an immutable FinancialAuditLog with structured details for full audit traceability.
Cómo funciona
Expense claims are created at /expense-claims/ with itemised expense lines, optional embedded TravelExpense, receipt URLs and a source reference (which tournament, which event, which assignment). The lifecycle moves through five states: draft (free editing by the submitter), submitted (locked for review), approved (with reviewer_id, comment and timestamp captured), paid (with payment method and external reference) or rejected (with mandatory comment, blocking payout). Travel reimbursement uses /expenses/travel/calculate, which combines distance reimbursement (distance_km * rate_per_km) with per-diem allowance (per_diem_days * per_diem_rate) for car, public transport, train, plane or other; the rate is tenant-configurable so Sweden runs at 18.50 SEK per km and France at 0.55 EUR per km.
The approval surface — /expense-claims/{id}/submit, /approve, /reject — runs through the same RBAC layer as other admin actions. Payment runs through /expense-claims/{id}/pay with optional payment method and external reference, hooking into the Payment Processing pipeline so reimbursements settle through the configured gateway or bank transfer. Reporting comes in two cuts: /expense-reports/by-category groups every expense by category (travel, meals, accommodation and so on) with totals, and /expense-reports/by-org-node groups per OrgNode with category breakdown per node, both filterable by org_node_id, season_id and status.
Every mutation — create, submit, approve, reject, pay — appends an immutable FinancialAuditLog entry with structured details (amount, currency, payment method, reviewer, rejection comment), giving auditors a complete trail per claim.
Capacidades clave
- Expense claim creation with itemised lines, embedded TravelExpense and receipt URLs
- Five-state lifecycle: draft -> submitted -> approved -> paid, with rejected as a terminal alternative
- Travel reimbursement combining distance-rate and per-diem with tenant-configurable rates
- Approval workflow with reviewer_id, comment and timestamp on every transition
- Payment via /expense-claims/{id}/pay using the standard Payment Processing pipeline
- Category and OrgNode reports filterable by season and status
- Immutable FinancialAuditLog entries on every state change for full audit traceability
En la práctica
An umpire officiates a regional tournament 240 km away. He opens the app, creates an ExpenseClaim, adds a hotel line with receipt photo and a travel line with start and destination addresses; /expenses/travel/calculate computes 240 km * 18.50 SEK plus one per-diem day. He submits.
The district secretary receives the claim, opens it, approves with comment Verified against tournament roster — the audit log captures her id and timestamp. The treasurer batches the week's approved claims, hits Pay on each, the platform transfers the amounts via bank file and writes Payment rows; /expense-reports/by-category for the quarter then shows umpire travel as the second-largest category and lets the board adjust the next budget cycle.
Funcionalidades de este subsistema
5| ID | Status | Funcionalidades |
|---|---|---|
| F08.07.01 | Entregado | Expense claim submission (umpires, officials, delegates) ✅ PL-F0807 |
| F08.07.02 | Entregado | Travel expense calculation (distance, per diem) ✅ PL-F0807 |
| F08.07.03 | Entregado | Expense approval workflow ✅ PL-F0807 |
| F08.07.04 | Entregado | Expense reimbursement processing ✅ PL-F0807 |
| F08.07.05 | Entregado | Expense category reporting ✅ PL-F0807 |