Skip to main content

Function: computeCatchupCentavos()

computeCatchupCentavos(svc, companyId, contractorId, assignmentId, period, newByDate, excludeFromBaseline?): Promise<number>

Defined in: src/server/services/catchupPay.ts:84

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 / assignment does not overlap the period).

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​

Error when a bundle read fails or is truncated (#170/#171 — better no catch-up than a silently wrong one); DateError on a malformed stored date; MoneyError on a non-integer stored rate.