feat(Payroll): add regular-rate-of-pay workweek distribution helpers - #2473
krisxcrash wants to merge 1 commit into
Conversation
Ports gusto-web's evenlyDistributeValue (pro-rata distribution across workweeks, weighted by calendar days, with rounding-remainder reconciliation) and its existence-based needsWorkweekBreakdown / needsWorkweekBreakdownForEarning detection predicates into a pure, framework-agnostic TypeScript module (SDK-1135). Workweek boundaries are accepted as an external input and rounding precision is caller-supplied — the Embedded API does not yet expose per-workweek fields (backend work is landing under EMBPAY-705/709 but is alpha-only and not in this SDK's vendored API version), so this PR covers only the pure math, with no UI or API wiring. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
This PR likely isn't needed. I tested it against staging (RRoP flag on) using the test fest's worked example: one Nonexempt employee, $22/hr, 80 regular hours, 5 overtime hours, $200 commission, biweekly period with two workweeks. I ran the same payroll two ways:
The key result: with no breakdowns at all, the backend still computed a correct Regular Rate of Pay premium ($170.88, not the flat 1.5x of $165). It does this by evenly spreading each total across the pay period on its own, then splitting by workweek. That's the exact same even split this PR's The small $0.32 gap is only because the 5 OT hours actually landed in week 1, not spread evenly. Closing that gap needs the employee's real per-week hours. This helper doesn't have those; it takes one pay-period total and splits it evenly, so it can never do better than the backend's own even split. Conclusion: client-side distribution adds no accuracy over the backend. The helper is redundant unless we start collecting true per-week actuals from partners. One side note: the breakdown-write request returned a 500 once, then succeeded on retry. Worth a look separately. Posted by Claude on behalf of Steve |
|
This one is already taken care of on the backend. see report here #2473 (comment) Closing for now |
Summary
src/components/Payroll/Rrop/rropHelpers.ts: a pure, framework-agnostic TypeScript port of gusto-web'sevenlyDistributeValue(workweek-weighted pro-ration with rounding-remainder reconciliation onto the first workweek) plusneedsWorkweekBreakdown/needsWorkweekBreakdownForEarningexistence-based detection predicates, ported from gusto-web'suseEmployeesNeedWorkweekBreakdowns.{ startDate, endDate }[]input, never derived client-side. Once the API ships, boundaries are expected to arrive asstart_date/end_dateon each compensation'sbreakdowns[]rows (frompayrolls#prepare/#update/#create), not as a standalone workweeks list — a future integration ticket will extract aWorkweek[]from that shape.workweeksarray returns{}here instead of throwing (gusto-web's real code throws onworkweeks[0]before its own length check).Known gaps / open questions (tracked, not resolved, in this PR)
includedInRegularRateOfPay(gusto-web) vs.included_in_overtime_pay(proposed API) — naming/semantic equivalence is unconfirmed; the new predicate's parameter is named generically to avoid committing to either.Test plan
npm run test -- --run src/components/Payroll/Rrop— 32/32 passing, covering the worked examples (equal/uneven/three-way splits, non-contiguous "gappy" workweeks, empty array, single workweek, remainder-to-first-week assignment, a precision 0–6 sweep, and a US DST-transition case)npm run test -- --run(full suite, on top of the rebased base branch) — passingnpx tsc --noEmitandnpx eslintclean on changed files🤖 Generated with Claude Code