← Back to lab
Lab

Billing scheduled hours, paying worked hours

A client is billed the hours scheduled and a guard is paid the hours worked, at rates fixed when the shift is created.

↓

Two figures from one shift

  • InvoiceService bills a client with useScheduledHours set to true and computes a guard's pay with it set to false.
  • A guard who books on fifteen minutes late is billed to the client in full and paid from actual attendance.
  • The difference is the firm's margin, and the current system treats it that way rather than as a client credit.

Grace and window

  • Fifteen minutes of grace at book-on, none at book-off. The grace moves the baseline rather than acting as a cliff: booking on at 10:16 for a 10:00 start costs one minute, not sixteen. Leaving early is deducted from the first minute.
  • The booking window is a separate rule that shares the number. The button that books a guard on works from fifteen minutes before the shift until it ends.
  • Lateness within the window stays unbounded. A guard arriving at 09:20 after traffic has to be able to book on; otherwise the record shows a shift nobody worked.

Rate snapshots

  • Rates snapshot onto the shift when it is created, and the past is never re-rated. An invoice already sent does not change.
  • The system being replaced has the rule and a fallback that breaks it. When a snapshot is null or zero, RateResolver reads the site's live rate at the moment the invoice is generated, and two invoices for the same past period, run a week apart, can differ.
  • Its propagation is bounded by a date the caller supplies rather than by whether a shift has been invoiced.
  • The redesign removes the fallback. A rate change reaches exactly the shifts not yet invoiced.

Statutory figures

  • Statutory sick pay (£23.75 a day, three waiting days, a 28-week cap) and holiday accrual (12.07% of hours worked) are UK law and change every April.
  • The current code holds them as literals in five and two places. They become configuration with effective dates, for the same reason shifts keep their snapshotted rates.

Where it stops holding

The snapshot rule holds while the snapshot itself is right. When a shift was created with a wrong rate and has already been invoiced, the rule forbids re-rating it; the correction is a voided invoice, with the reason recorded, not a changed shift.

Up next
A discrepancy register→