Skip to main content

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

BiMonthlyPeriod

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.