4ab5597fd5
* feat: multi-groomer calendar view with per-groomer filtering Add groomer view mode to the appointments calendar: - Toggle between "Status" (existing) and "Groomer" color coding - Per-groomer visibility toggles with color-coded buttons - Appointments colored by assigned groomer in groomer view - Groomer name shown on appointment blocks in groomer view - Unassigned appointments shown in neutral gray Satisfies groombook/groombook#11 requirements for side-by-side/unified groomer schedule visibility and per-groomer filter/toggle. Co-Authored-By: Paperclip <noreply@paperclip.ing> * feat: tip and payment splitting between staff roles Implements groombook/groombook#12 — track which staff worked on each pet and calculate tip distribution based on who was involved. Changes: - DB: Add bather_staff_id to appointments (optional secondary staff) - DB: Add invoice_tip_splits table (per-staff tip share ledger) - API: appointments POST/PATCH accept batherStaffId - API: GET /invoices/:id now includes tipSplits[] - API: POST /invoices/:id/tip-splits — saves tip distribution - API: GET /reports/tip-splits — payroll summary of tip earnings - Frontend: Bather/Assistant select on New Appointment form - Frontend: Tip Distribution section in Invoice Detail modal - Auto-populates 70%/30% split when bather is assigned - Editable percentages before payment; saved on Mark as Paid - Displays recorded splits on paid invoices Co-Authored-By: Paperclip <noreply@paperclip.ing> * fix: remove unused staff import from invoices route Co-Authored-By: Paperclip <noreply@paperclip.ing> --------- Co-authored-by: Groom Book CTO <cto@groombook.app> Co-authored-by: Paperclip <noreply@paperclip.ing>
26 lines
1.1 KiB
SQL
26 lines
1.1 KiB
SQL
-- Add bather/assistant staff tracking to appointments and tip split ledger (closes groombook/groombook#12)
|
|
|
|
-- Secondary staff member (e.g., bather) who assisted the primary groomer
|
|
ALTER TABLE "appointments"
|
|
ADD COLUMN "bather_staff_id" uuid REFERENCES "public"."staff"("id") ON DELETE set null ON UPDATE no action;
|
|
--> statement-breakpoint
|
|
|
|
-- Stores per-staff tip allocations calculated when an invoice is paid
|
|
CREATE TABLE "invoice_tip_splits" (
|
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
|
"invoice_id" uuid NOT NULL,
|
|
"staff_id" uuid,
|
|
"staff_name" text NOT NULL,
|
|
"share_pct" numeric(5, 2) NOT NULL,
|
|
"share_cents" integer NOT NULL,
|
|
"created_at" timestamp DEFAULT now() NOT NULL
|
|
);
|
|
--> statement-breakpoint
|
|
ALTER TABLE "invoice_tip_splits"
|
|
ADD CONSTRAINT "invoice_tip_splits_invoice_id_invoices_id_fk"
|
|
FOREIGN KEY ("invoice_id") REFERENCES "public"."invoices"("id") ON DELETE cascade ON UPDATE no action;
|
|
--> statement-breakpoint
|
|
ALTER TABLE "invoice_tip_splits"
|
|
ADD CONSTRAINT "invoice_tip_splits_staff_id_staff_id_fk"
|
|
FOREIGN KEY ("staff_id") REFERENCES "public"."staff"("id") ON DELETE set null ON UPDATE no action;
|