Function: computeCatchupCentavos()
computeCatchupCentavos(
svc,companyId,contractorId,assignmentId,period,newByDate,excludeFromBaseline?):Promise<number>
Defined in: src/server/services/catchupPay.ts:49
The marginal pay that applying newByDate (the new per-date hours) would earn in their own
(already-paid) bi-monthly period: pay(baseline overlaid with newByDate) − pay(baseline), using the
same engine + inputs as a real run with the proration cap respected (so hours in a week already at
100% add nothing). Must be called BEFORE the new entries are persisted, so the existing payable set
is the baseline — UNLESS the new entries are already in the table (late contractor hours found in a
closed period): pass their dates as excludeFromBaseline and the baseline is rebuilt without them,
making the marginal identical to the not-yet-persisted case. Returns 0 when the period can't be
priced (no rate / no contracted hours).
The pay engine is consulted with the assignment's bi-monthly rate, the contractor type
(outsourced default; in_house_admin also folds in approved holiday leave), the holidays
config, and the set of approved overage weeks for this assignment (the unified Mon–Sun week, the
same anchor the engine keys on — ADR-0044). Existing entries are read from the period's
settling-week range and counted only when their status is in PAYABLE_ENTRY_STATUSES.
Parameters
svc
SupabaseClient
Service-role Supabase client (bypasses RLS); all queries are still scoped by companyId.
companyId
string
Tenant scope applied to every query.
contractorId
string
Contractor whose leave and overage approvals are loaded.
assignmentId
string
Contractor↔facility assignment supplying the rate, contracted hours, and effective/end dates.
period
Bi-monthly pay period to price (billing and pay both key on the Mon–Sun week, ADR-0044).
newByDate
Map<string, number>
New per-date hours, keyed by entry_date (ISO YYYY-MM-DD); each key OVERWRITES (does not add to) the baseline hours for that date.
excludeFromBaseline?
ReadonlySet<string>
Dates to drop from the baseline before overlaying: pass newByDate's keys when those entries are ALREADY persisted, so they don't cancel themselves out of the marginal.
Returns
Promise<number>
Non-negative marginal pay in integer centavos (clamped at 0); 0 if the assignment/rate is missing or the engine cannot price the period.
Throws
DateError on a malformed stored date (assignment effective/end date); throws from the Centavos guard if a stored bimonthly_rate_centavos is non-integer.