seubert-claims/tasks/tasks-prd-renewal-groups.md

9.1 KiB
Raw Permalink Blame History

Relevant Files

New Files

  • ondeck/src/lib/renewal-group-recommendations.ts - Pure TS recommendation engine: groups policies by expiration window, calculates renewal dates per rule.
  • ondeck/src/lib/renewal-group-recommendations.test.ts - Unit tests for the recommendation engine.
  • ondeck/src/app/(dashboard)/manager/setup/page.tsx - New Client Setup Queue page (server component).
  • ondeck/src/app/(dashboard)/manager/setup/[clientId]/page.tsx - Setup Wizard page for a specific client (server component, fetches client + policies).
  • ondeck/src/components/renewal-groups/setup-wizard.tsx - Main wizard client component with state, drag-and-drop orchestration, advocate selector, and save logic.
  • ondeck/src/components/renewal-groups/group-card.tsx - Droppable group card showing policies, inline name editor, renewal date picker, rule selector, and default-group radio.
  • ondeck/src/components/renewal-groups/policy-chip.tsx - Draggable policy pill used inside group cards and the unassigned policies tray.
  • ondeck/src/app/api/clients/setup-queue/route.ts - GET: returns unconfigured clients (missing renewalDate or claimsAdvocate).
  • ondeck/src/app/api/clients/[id]/setup/route.ts - POST: persists wizard output (groups, renewalDate, claimsAdvocate, notes, setupCompletedAt). PUT: saves draft.
  • ondeck/src/app/api/admin/renewal-settings/route.ts - GET/PUT: reads and writes global renewal group defaults from app_settings.
  • ondeck/src/app/(dashboard)/admin/renewal-settings/page.tsx - Admin Panel page for global defaults (grouping window, renewal date rule).

Modified Files

  • ondeck/prisma/schema.prisma - Add setupCompletedAt DateTime? to Client; add new AppSetting model for key-value settings store.
  • ondeck/src/app/(dashboard)/layout.tsx - Add badge on Manager nav item showing count of unconfigured clients.
  • ondeck/src/app/(dashboard)/manager/page.tsx - Add "New Client Setup" summary card linking to the queue page.
  • ondeck/src/app/(dashboard)/clients/[id]/page.tsx - Pass setupCompletedAt and policies to ClientDetail; add "Edit Setup" button for Manager/Admin.
  • ondeck/src/components/clients/client-detail.tsx - Render "Edit Setup" button that navigates to the wizard for the current client.
  • ondeck/src/app/(dashboard)/admin/page.tsx - Add "Renewal Groups" section linking to the new settings page.

Notes

  • Unit tests should be placed alongside source files (e.g., renewal-group-recommendations.ts and renewal-group-recommendations.test.ts in the same directory).
  • Run tests with npx jest src/lib/renewal-group-recommendations.
  • After any schema.prisma change, run npx prisma migrate dev --name <migration-name> and npx prisma generate.
  • @dnd-kit/core, @dnd-kit/sortable, and @dnd-kit/utilities are already installed.

Tasks

  • 1.0 Database & Schema

    • 1.1 Add setupCompletedAt DateTime? @map("setup_completed_at") field to the Client model in prisma/schema.prisma.
    • 1.2 Add a new AppSetting model to prisma/schema.prisma with fields key String @id, value String @db.Text, updatedAt DateTime @updatedAt. Map to table app_settings.
    • 1.3 Run npx prisma migrate dev --name add_setup_completed_at_and_app_settings to create and apply the migration. (Used prisma db push due to pre-existing schema drift.)
    • 1.4 Run npx prisma generate to update the Prisma client.
    • 1.5 Seed two default rows into app_settings: renewal_group_window_days = "90" and renewal_group_date_rule = "nearest-to-year-start".
  • 2.0 Recommendation Engine

    • 2.1 Create src/lib/renewal-group-recommendations.ts. Define and export the input types: PolicyInput { policyId: string; expirationDate: Date } and RecommendationConfig { windowDays: number; rule: 'nearest-to-year-start' | 'earliest' | 'latest' }.
    • 2.2 Implement the grouping algorithm: sort policies by expirationDate, then use a sliding-window approach to cluster policies whose dates fall within windowDays of each other into the same group.
    • 2.3 Implement the renewalDate calculation for each group based on config.rule: nearest-to-year-start picks the expiration date with the lowest day-of-year value; earliest picks the minimum; latest picks the maximum. All results are expirationDate + 1 day.
    • 2.4 Handle standalone policies (groups of size 1) — they are valid output and their renewalDate is simply expirationDate + 1.
    • 2.5 Policies with a null expiration date must be excluded from grouping and returned separately as ungroupable: PolicyInput[].
    • 2.6 Write unit tests in renewal-group-recommendations.test.ts covering: basic 90-day grouping, cross-year-boundary grouping, all three date rules, standalone policy, null-date exclusion, and empty input. (12/12 pass)
  • 3.0 New Client Setup Queue

    • 3.1 Create src/app/api/clients/setup-queue/route.ts — GET handler that queries clients where claimsAdvocateId IS NULL OR setupCompletedAt IS NULL, including policy count, earliest/latest expiration dates, and createdAt. Returns sorted by createdAt ASC.
    • 3.2 Create src/app/(dashboard)/manager/setup/page.tsx — server component that fetches the queue via Prisma and renders a table/list of unconfigured clients. Restrict to Manager/Admin roles; redirect others.
    • 3.3 Each queue row must show: client name (linked to wizard), policy count, earliest expiry, latest expiry, days in queue (today createdAt).
    • 3.4 Add a "Days in queue" warning: highlight rows where daysInQueue > 5 in amber, > 10 in red.
    • 3.5 Update src/components/layout/nav-bar.tsx to fetch the unconfigured client count client-side and show a numeric badge on the Manager nav link when count > 0.
    • 3.6 Update src/app/(dashboard)/manager/page.tsx and manager-page-client.tsx to add a "New Client Setup" summary card showing the queue count and a link to /manager/setup.
  • 4.0 Setup Wizard UI

    • 4.1 Create src/app/(dashboard)/manager/setup/[clientId]/page.tsx — server component that fetches the client, all its policies, existing policy groups, Claims-dept users, and global settings. Passes all data to <SetupWizard />.
    • 4.2 Create src/components/renewal-groups/setup-wizard.tsx — client component with full state management.
    • 4.3 On mount, if no existing groups, auto-run the recommendation engine. If existing groups already exist, load them directly.
    • 4.4 Render a top toolbar in the wizard: windowDays number input, rule select dropdown, and a "Re-run Recommendations" button with dirty-state confirmation dialog.
    • 4.5 Create src/components/renewal-groups/policy-chip.tsxuseDraggable component with no-expiry warning.
    • 4.6 Create src/components/renewal-groups/group-card.tsxuseDroppable card with inline name editor, rule selector, live renewal date, manual override, notes, and default-group star.
    • 4.7 Render an "Unassigned Policies" tray at the bottom of the wizard.
    • 4.8 Implement policy drag-and-drop via @dnd-kit/core.
    • 4.9 Add group management: "Add Group" button, trash icon to delete, "Split" context action on each chip.
    • 4.10 Add Claims Advocate selector (filtered to Claims dept). "Save & Complete" disabled if no advocate.
    • 4.11 Single-default-group rule with star radio buttons; hidden when only one group.
    • 4.12 "Save & Complete" — validates, calls POST, navigates to client detail on success.
    • 4.13 "Save as Draft" — calls PUT, shows toast, keeps setupCompletedAt null.
    • 4.14 Breadcrumb/back link to the queue page at the top of the wizard.
  • 5.0 API Routes

    • 5.1 Create src/app/api/clients/[id]/setup/route.ts — POST handler with Prisma transaction: upsert groups, update policy assignments, set client fields including setupCompletedAt.
    • 5.2 PUT handler on same route for draft saves (omits setupCompletedAt).
    • 5.3 Both handlers protected: return 403 if not Manager or Admin.
    • 5.4 Create src/app/api/admin/renewal-settings/route.ts — GET/PUT with Admin-only write guard.
    • 5.5 setup-queue/route.ts accepts ?count=true query param returning { count: number }.
  • 6.0 Admin Panel — Global Settings

    • 6.1 Create src/app/(dashboard)/admin/renewal-settings/page.tsx — server component reading settings and rendering <RenewalSettingsForm />.
    • 6.2 Settings form: number input for window days (1365) and select for date rule.
    • 6.3 On save, calls PUT /api/admin/renewal-settings. Shows success/error toast.
    • 6.4 Updated src/app/(dashboard)/admin/page.tsx with a "Renewal Groups" card linking to /admin/renewal-settings.
  • 7.0 Re-open Wizard from Client Detail

    • 7.1 Updated src/app/(dashboard)/clients/[id]/page.tsx to pass setupCompletedAt and canManageSetup props.
    • 7.2 Updated src/components/clients/client-detail.tsx to render "Edit Setup" / "Complete Setup" button for Manager/Admin.
    • 7.3 Wizard loads existing PolicyGroup data when re-opened and shows a re-configure banner.
    • 7.4 API POST handler deletes removed groups (DB groups not in payload) inside the same transaction.