Award Calculation Engine
How the award calculator converts approved timesheet input, client rates, event rates, and allowance lines into current calculation snapshots.
Purpose
The award calculation engine converts raw timesheet data into a payroll and billing snapshot. It does not replace the allowance matrix. It consumes calculated allowance lines, hours, client rates, event rates, and optional matrix rules, then writes a TimesheetCalculation with line-level TimesheetCalculationLine records.
The important output is the current calculation snapshot used by payroll review and invoice generation.
Main classes
| Class | Responsibility |
|---|---|
AwardTimesheetCalculationManager | Orchestrates snapshot creation, supersedes previous current/draft calculations, persists a new current calculation, and links it to the timesheet. |
AwardTimesheetCalculator | Builds the calculation payload and calculation lines from timesheet, project, worker, rate, allowance, and feature-flag inputs. |
TimesheetAwardCalculationSubscriber | Queues recalculation when timesheets, time entries, allowance lines, or client allowances change. |
RecalculateTimesheetAwardCalculationsCommand | Manual backfill/recalculation command for existing timesheets. |
Calculation sequence
Timesheet or dependent records change
-> allowance lines are recalculated first when needed
-> award subscriber queues eligible timesheet
-> calculation manager supersedes old current/draft snapshot
-> calculator creates gross/payable hours, totals, and line rows
-> new snapshot becomes current
-> payroll and invoice views read the current snapshotOnly submitted, accepted, and approved timesheets are recalculated automatically. Draft timesheets can still be edited without creating snapshot churn.
Inputs
| Input | Source |
|---|---|
| Worker and project | Timesheet.user, Timesheet.project |
| Raw worked intervals | TimeEntry.date, TimeEntry.startTime, TimeEntry.endTime |
| Lunch/break/location metadata | TimeEntry fields and Timesheet.location metadata |
| Client rates | ClientRate, ClientRateClass, project team EW class and position metadata |
| Event rates | Active client ClientEventRate rows |
| Public holidays | AwardPublicHoliday rows |
| Optional matrix rules | ordinary-hours, break, shift, travel, and callout rule repositories |
| Allowances | Existing TimesheetAllowanceLine rows created by the allowance matrix |
Feature flags
app/config/services.yaml wires the main calculation switches:
| Flag | Default | Effect |
|---|---|---|
AWARD_AMOUNT_APPLICATION_ENABLED | true | Allows calculation lines to produce non-zero pay and bill amounts. |
AWARD_MATRIX_RULES_ENABLED | false | Enables advanced break, shift, travel, and callout matrix rule behavior. |
AWARD_ORDINARY_HOURS_RULES_ENABLED | false | Uses client ordinary-hours rules instead of fallback ordinary caps. |
When advanced flags are disabled, the engine still produces useful ordinary, overtime, weekend, public holiday, allowance, and billing lines using fallback defaults.
Fallback ordinary and overtime rules
Unless ordinary-hours rules are enabled, the engine uses:
daily ordinary cap = 7.6 hours
weekly ordinary cap = 38.0 hours
first overtime bucket = 2.0 hours
first overtime multiplier = 1.5x
remaining overtime multiplier = 2.0x
Saturday multiplier = 1.5x
Sunday multiplier = 2.0xWeekday hours are split into ordinary and overtime buckets. Weekend and public holiday work becomes special-day lines instead of ordinary weekday lines.
Rate resolution
The calculator resolves worker rate context from the project and client:
- Find the timesheet project and client.
- Match the worker against project team metadata where available.
- Use EW class, base class, subcategory code, position, employment type, and client rate rows to find the best client rate.
- Apply casual loading when relevant.
- Derive bill rate from pay rate plus configured billing markup and GST behavior.
The rate data is copied into calculation output so later review can explain which classification and rate source were used.
Event-rate matching
ClientEventRate rows override default multipliers for recognized event keys. The calculator normalizes trigger tokens before matching. Supported concepts include:
- saturday
- sunday
- public holiday
- public holiday overtime
- weekday first overtime
- first overtime
- overtime first two hours
- weekday after two overtime
- remaining overtime
- overtime after two hours
If no active client event rate matches, the fallback multiplier applies.
Line types
Calculation line types come from AwardCalculationLineType and include:
| Type | Meaning |
|---|---|
ordinary | Ordinary paid hours. |
minimum_shift | Minimum payable shift top-up. |
break | Break or meal-break adjustment when matrix rules are enabled. |
overtime | Weekday overtime buckets. |
saturday, sunday, public_holiday | Special-day payable hours. |
shift_loading | Shift loading portion only. |
allowance | Allowance matrix lines copied into award calculation output. |
travel, callout | Advanced matrix-rule outputs when enabled. |
expense, billing | Supporting financial/billing rows. |
Allowance handoff
The award calculator does not rediscover allowance rules. It reads TimesheetAllowanceLine records that already passed the allowance matrix. Each allowance line becomes an award calculation line with allowance quantity, unit rate, pay/bill amount behavior, and rule text.
This is why allowance recalculation should run before award recalculation when both are affected.
Current vs superseded snapshots
The manager treats each calculation as a point-in-time snapshot:
existing current/draft snapshot
-> mark superseded
-> create new calculation
-> mark new calculation currentThis gives payroll and finance one current truth while still preserving prior calculation records for traceability.
Invoice dependency
Invoice generation prefers the current award calculation's positive billTotal. If that value is present and greater than zero, the timesheet invoice amount is:
current award bill total + material totalIf no positive bill total exists, invoice generation falls back to hours x matched client base rate plus allowance total plus material total.