feat: tip and payment splitting between staff roles #34

Merged
ghost merged 3 commits from feat/tip-splitting into main 2026-03-17 22:03:46 +00:00
ghost commented 2026-03-17 22:01:22 +00:00 (Migrated from github.com)

Summary

Implements groombook/groombook#12 — track which staff worked on each pet and calculate tip distribution.

Database:

  • appointments.bather_staff_id — nullable FK to staff; tracks the bather/assistant who assisted the primary groomer
  • invoice_tip_splits — ledger of per-staff tip shares (staffName snapshotted for historical accuracy)
  • Migration 0007_tip_splitting.sql

Backend:

  • appointments POST/PATCH now accept batherStaffId
  • GET /api/invoices/:id includes tipSplits[] in response
  • POST /api/invoices/:id/tip-splits — saves tip distribution (replaces existing splits, validates percentages sum to 100%)
  • GET /api/reports/tip-splits?from=&to= — payroll summary aggregating tip earnings per staff member

Frontend:

  • New "Bather / Assistant (optional)" select on the appointment booking form
  • Bather name shown in appointment detail view
  • "Tip Distribution" section in Invoice Detail modal:
    • Auto-populates 70%/30% split when bather is assigned to the linked appointment
    • Editable names and percentages; validation shows when total ≠ 100%
    • Splits saved automatically when marking invoice as paid (non-blocking if it fails)
    • Recorded splits displayed on paid invoices

Test plan

  • Create appointment with a groomer and bather → bather appears in appointment detail
  • Create invoice from that appointment → Tip Distribution section shows 70/30 default split
  • Adjust percentages → validation shows green "100% ✓" when correct
  • Mark as paid with tip amount → tip splits saved
  • Reopen invoice → recorded splits shown with amounts
  • GET /api/reports/tip-splits → returns per-staff tip earnings
  • CI passes (lint, typecheck, test, build)

🤖 Generated with Claude Code

## Summary Implements [groombook/groombook#12](https://github.com/groombook/groombook/issues/12) — track which staff worked on each pet and calculate tip distribution. **Database:** - `appointments.bather_staff_id` — nullable FK to staff; tracks the bather/assistant who assisted the primary groomer - `invoice_tip_splits` — ledger of per-staff tip shares (staffName snapshotted for historical accuracy) - Migration `0007_tip_splitting.sql` **Backend:** - `appointments` POST/PATCH now accept `batherStaffId` - `GET /api/invoices/:id` includes `tipSplits[]` in response - `POST /api/invoices/:id/tip-splits` — saves tip distribution (replaces existing splits, validates percentages sum to 100%) - `GET /api/reports/tip-splits?from=&to=` — payroll summary aggregating tip earnings per staff member **Frontend:** - New "Bather / Assistant (optional)" select on the appointment booking form - Bather name shown in appointment detail view - "Tip Distribution" section in Invoice Detail modal: - Auto-populates 70%/30% split when bather is assigned to the linked appointment - Editable names and percentages; validation shows when total ≠ 100% - Splits saved automatically when marking invoice as paid (non-blocking if it fails) - Recorded splits displayed on paid invoices ## Test plan - [ ] Create appointment with a groomer and bather → bather appears in appointment detail - [ ] Create invoice from that appointment → Tip Distribution section shows 70/30 default split - [ ] Adjust percentages → validation shows green "100% ✓" when correct - [ ] Mark as paid with tip amount → tip splits saved - [ ] Reopen invoice → recorded splits shown with amounts - [ ] `GET /api/reports/tip-splits` → returns per-staff tip earnings - [ ] CI passes (lint, typecheck, test, build) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This repo is archived. You cannot comment on pull requests.