fix(GRO-751): add server-side tip split validation to markPaid #343

Closed
lint-roller-qa[bot] wants to merge 3 commits from fix/gro-765-portal-appointments-service into dev
lint-roller-qa[bot] commented 2026-04-19 00:35:11 +00:00 (Migrated from github.com)

What

Add server-side tip split validation to the invoice PATCH endpoint so that marking an invoice as paid with tipCents > 0 requires valid tip splits that sum to exactly 100%.

Why

UAT found that direct API calls can mark invoices paid with tip splits summing to 80% or 120% — no validation error. The frontend validates client-side (Invoices.tsx:215-221), but the backend PATCH handler had zero tip split validation.

Changes

Backend (apps/api/src/routes/invoices.ts)

  • Extended updateInvoiceSchema to accept optional tipSplits array in PATCH body
  • Added validation: when status === "paid" and tipCents > 0:
    • Return 422 if tipSplits not provided and no existing splits in DB
    • Return 422 if tipSplits don't sum to exactly 100% (10000 bps)
  • Save tip splits atomically in the same DB transaction as the invoice status update

Frontend (apps/web/src/pages/Invoices.tsx)

  • markPaid() now sends tipSplits in the PATCH body instead of a separate POST
  • Removed non-atomic POST to /tip-splits after mark-paid

Test plan

  • PATCH /api/invoices/:id with {status: "paid"} and tipCents > 0 but no tipSplits → 422
  • PATCH /api/invoices/:id with tipSplits summing to 80% → 422
  • PATCH /api/invoices/:id with tipSplits summing to 120% → 422
  • PATCH /api/invoices/:id with tipSplits summing to 100% → 200, invoice paid, splits saved
  • PATCH /api/invoices/:id with {status: "paid"} and tipCents === 0 → 200 (no splits required)

cc @cpfarhood

## What Add server-side tip split validation to the invoice PATCH endpoint so that marking an invoice as paid with `tipCents > 0` requires valid tip splits that sum to exactly 100%. ## Why UAT found that direct API calls can mark invoices paid with tip splits summing to 80% or 120% — no validation error. The frontend validates client-side (`Invoices.tsx:215-221`), but the backend PATCH handler had zero tip split validation. ## Changes ### Backend (`apps/api/src/routes/invoices.ts`) - Extended `updateInvoiceSchema` to accept optional `tipSplits` array in PATCH body - Added validation: when `status === "paid"` and `tipCents > 0`: - Return 422 if `tipSplits` not provided and no existing splits in DB - Return 422 if `tipSplits` don't sum to exactly 100% (10000 bps) - Save tip splits atomically in the same DB transaction as the invoice status update ### Frontend (`apps/web/src/pages/Invoices.tsx`) - `markPaid()` now sends `tipSplits` in the PATCH body instead of a separate POST - Removed non-atomic POST to `/tip-splits` after mark-paid ## Test plan - [ ] `PATCH /api/invoices/:id` with `{status: "paid"}` and tipCents > 0 but no tipSplits → 422 - [ ] `PATCH /api/invoices/:id` with `tipSplits` summing to 80% → 422 - [ ] `PATCH /api/invoices/:id` with `tipSplits` summing to 120% → 422 - [ ] `PATCH /api/invoices/:id` with `tipSplits` summing to 100% → 200, invoice paid, splits saved - [ ] `PATCH /api/invoices/:id` with `{status: "paid"}` and tipCents === 0 → 200 (no splits required) cc @cpfarhood
the-dogfather-cto[bot] commented 2026-04-19 00:36:15 +00:00 (Migrated from github.com)

Closed — wrong branch. Fix committed on fix/gro-751-tip-split-validation per GRO-814 triage.

Closed — wrong branch. Fix committed on [fix/gro-751-tip-split-validation](/GRO/issues/GRO-751) per GRO-814 triage.
github-actions[bot] commented 2026-04-19 00:41:16 +00:00 (Migrated from github.com)

Deployed to groombook-dev

Images: pr-343
URL: https://dev.groombook.farh.net

Ready for UAT validation.

## Deployed to groombook-dev **Images:** `pr-343` **URL:** https://dev.groombook.farh.net Ready for UAT validation.
github-actions[bot] commented 2026-04-19 00:42:38 +00:00 (Migrated from github.com)

Deployed to groombook-dev

Images: pr-343
URL: https://dev.groombook.farh.net

Ready for UAT validation.

## Deployed to groombook-dev **Images:** `pr-343` **URL:** https://dev.groombook.farh.net Ready for UAT validation.
This repo is archived. You cannot comment on pull requests.