Initial commit: OnDeck project

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
lorentz 2026-02-18 13:20:52 +00:00
commit b036a93da2
139 changed files with 33198 additions and 0 deletions

403
tasks/mvp-ondeck.md Normal file
View file

@ -0,0 +1,403 @@
# OnDeck MVP — Policy Renewal Workflow System
> Minimum Viable Product scope for the OnDeck policy renewal management platform.
> This document defines the feature set required for initial production deployment.
---
## Table of Contents
1. [User Authentication](#1-user-authentication)
2. [Logging](#2-logging)
3. [AMS360 Data Sync](#3-ams360-data-sync)
4. [Task Management & Renewal Workflow](#4-task-management--renewal-workflow)
5. [Renewal Grouping & Policy Exclusion](#5-renewal-grouping--policy-exclusion)
---
## 1. User Authentication
### 1.1 Authentication Providers
| Provider | Purpose | Status |
|----------|---------|--------|
| Local credentials | Development and testing (3 built-in accounts: admin, manager, ae) | Existing |
| Microsoft Entra ID (Azure AD) | Production SSO | Existing |
### 1.2 Account Linking
When a user signs in via Microsoft Entra ID and the email matches an existing local account, the accounts are linked automatically by populating the `entraOid` field on the existing user record.
- First lookup: find user by email where `entraOid` is null (pre-created local account)
- If found: update the record with the Entra Object ID to link the accounts
- Fallback: standard upsert by `entraOid` for net-new users
> **Reference:** `src/lib/auth.ts:110-144`
### 1.3 Role-Based Access Control
Four roles with granular permissions:
| Role | Key Permissions |
|------|----------------|
| **Admin** | Full access — users, clients, tasks, designations, templates, sync, reports, audit |
| **Manager** | Read users; read/write clients, tasks, templates; assign tasks; view reports |
| **Account Executive** | Read/write clients and tasks; read designations |
| **Claims** | Read clients; read/write tasks |
Permission categories: User Management, Client Management, Task Management, Designation Management, Template Management, Sync Operations, Reports, Audit.
Role resolution combines two sources:
- **Entra Group mappings**`EntraGroupRoleMapping` table maps Azure AD groups to application roles
- **Direct assignments**`UserRole` join table for explicit per-user role grants
> **Reference:** `src/lib/auth/roles.ts`, `src/lib/auth/permissions.ts`
### 1.4 Session Strategy
- JWT-based sessions (`strategy: 'jwt'`)
- Session callback enriches the token with: `id`, `entraOid`, `roles[]`, merged `permissions` object (union of all assigned role permissions)
---
## 2. Logging
### 2.1 Authentication Logging
| Event | Details |
|-------|---------|
| Sign-in success | Provider, user ID, timestamp |
| Sign-in failure | Provider, email attempted, failure reason |
| Account linking | User ID, linked Entra OID |
### 2.2 Action Logging (Audit)
All user-initiated mutations on entities are recorded in the `AuditLog` model:
| Field | Description |
|-------|-------------|
| `userId` | Actor who performed the action |
| `action` | Operation type (create, update, delete) |
| `entityType` | Target entity (Client, Policy, Task, etc.) |
| `entityId` | Target record ID |
| `oldValues` | JSON snapshot of previous state |
| `newValues` | JSON snapshot of new state |
| `ipAddress` | Request origin |
| `userAgent` | Client identifier |
| `createdAt` | Timestamp |
> **Reference:** `AuditLog` model in `prisma/schema.prisma`
### 2.3 Error Logging
- API route errors with request context
- Sync failures with stream identification and row-level detail
- Unhandled exceptions with stack traces
### 2.4 Info Logging
- Sync progress: rows fetched, processed, inserted, updated per stream
- Scheduled job execution: start, completion, next scheduled run
- System events: application startup, configuration changes
### 2.5 Alerts & Notifications
Alerts are delivered through the existing `Notification` model:
| Alert Type | Trigger |
|------------|---------|
| Overdue tasks | Task `dueDate` has passed with status not in COMPLETED/NA/CANCELLED |
| Sync failures | Any sync stream fails after retry exhaustion |
| System health | Scheduler down, database connectivity issues |
User notification preferences are stored in `NotificationPreference` with per-type toggles for: in-app, email, and Teams delivery channels.
> **Reference:** `Notification` and `NotificationPreference` models in `prisma/schema.prisma`
---
## 3. AMS360 Data Sync
### 3.1 Overview
Sync data from the AFW SQL Server database (AMS360 source of truth) into the local PostgreSQL database. The sync engine connects to AFW via a managed connection pool (max 10 connections, 60s request timeout).
> **Reference:** `src/lib/sync/afw-connection.ts`
### 3.2 Department Scope
| Item | Current State | MVP Target |
|------|---------------|------------|
| Departments synced | 5 departments (Dept1, Dept8, Dept9, Dept10, Dept12) | **All 13 departments** |
**MVP change:** Remove the hardcoded `ShortName IN (...)` filter in the policy sync query so all AFW departments are included.
> **Reference:** `src/lib/sync/afw-queries.ts:221` — current 5-department WHERE clause
### 3.3 Sync Streams
Three parallel streams execute concurrently via `Promise.all()`:
| Stream | Source (AFW) | Target (Local) | Key Mapping |
|--------|-------------|-----------------|-------------|
| **Employees → Users** | `AFW_Employee` (Status = 'A') | `User` | EmpCode, Name, Email, DefaultGLDeptCode → department |
| **Customers → Clients** | `AFW_Customer` (Active = 'Y') | `Client` | CustId → amsCustomerId, contact fields, producer code |
| **Policies → Policies** | `AFW_BasicPolInfo` + 20 joined lookup tables | `Policy` | Complex CTE with company, department, personnel lookups; up to 2 additional reps and 2 additional execs per policy |
> **Reference:** `src/lib/sync/sync-engine.ts`, `src/lib/sync/afw-queries.ts`, `src/lib/sync/mappers.ts`
### 3.4 Sync Modes
| Mode | Behavior |
|------|----------|
| **Incremental** (default) | Syncs records changed since last successful sync, using `ChangedDate` filtering where supported |
| **Full** | Re-syncs all records regardless of last sync timestamp |
Signature: `runSync(triggeredBy?: string, isIncremental: boolean = true)`
### 3.5 Scheduling & Triggers
| Mechanism | Details |
|-----------|---------|
| **Scheduled** | Configurable cron expression stored in `SyncConfig` table (default: `0 2 * * *` — daily at 2 AM) |
| **Manual** | `POST /api/sync` with optional date range selection; requires `sync.trigger` permission |
Configuration keys in `SyncConfig`:
- `sync_enabled` — master toggle
- `sync_schedule_cron` — cron expression
- `policy_start_date` / `policy_end_date` — date range for policy sync window
> **Reference:** `src/lib/sync/scheduler.ts`
### 3.6 Retry Logic
Each sync stream independently retries on failure:
- **Max retries:** 3
- **Backoff:** Exponential — 2s, 4s, 8s
### 3.7 Sync Logging
Every sync execution is recorded in the `SyncLog` model:
| Field | Description |
|-------|-------------|
| `syncType` | Which stream or overall sync |
| `startedAt` / `completedAt` | Timing |
| `status` | Success or failure |
| `rowsProcessed` | Total rows fetched from AFW |
| `rowsInserted` | New records created |
| `rowsUpdated` | Existing records updated |
| `errorMessage` | Failure details (if any) |
| `triggeredBy` | User ID or "scheduler" |
### 3.8 API Endpoints
| Method | Path | Purpose | Permission |
|--------|------|---------|------------|
| `POST` | `/api/sync` | Trigger manual sync | `sync.trigger` |
| `GET` | `/api/sync` | List recent sync logs | `sync.trigger` |
| `GET` | `/api/sync/status` | Scheduler status | `sync.trigger` |
---
## 4. Task Management & Renewal Workflow
### 4.1 Task Templates
Templates define repeatable task patterns for renewal workflows:
| Field | Description |
|-------|-------------|
| `name` | Template display name |
| `description` | Detailed instructions |
| `department` | PERSONAL_LINES, COMMERCIAL_LINES, CLAIMS, BENEFITS, OTHER |
| `timing` | PRE_RENEWAL or POST_RENEWAL |
| `daysOffset` | Signed integer — number of days before (negative) or after (positive) policy expiration |
| `defaultPriority` | LOW, MEDIUM, HIGH, or URGENT |
| `designationId` | Optional — restrict template to clients with a specific designation |
| `displayOrder` | Presentation ordering |
| `isActive` | Soft-disable toggle |
Designation-based rules: When a template has a `designationId`, it only generates tasks for clients whose primary or secondary designation matches.
> **Reference:** `TaskTemplate` model in `prisma/schema.prisma`
### 4.2 Task Auto-Generation
Tasks are generated from templates based on policy expiration dates:
1. Identify policies approaching expiration within the configured window
2. Match applicable templates by department and (optionally) client designation
3. Calculate due date: `policy.expirationDate + template.daysOffset`
4. Create task records linked to the client, policy, and source template
### 4.3 Task Statuses
| Status | Description |
|--------|-------------|
| `NOT_STARTED` | Default state on creation |
| `IN_PROGRESS` | Work underway |
| `COMPLETED` | Finished — captures `completedAt` timestamp and `completedBy` user |
| `BLOCKED` | Cannot proceed — requires intervention |
| `NA` | Not applicable — **requires `naReason`** documentation |
| `CANCELLED` | Voided — **requires `cancelledReason`** documentation |
### 4.4 Priority Levels
| Priority | Usage |
|----------|-------|
| `LOW` | Routine, no urgency |
| `MEDIUM` | Standard renewal tasks |
| `HIGH` | Approaching deadline or important client |
| `URGENT` | Immediate attention required |
### 4.5 Timing & Day Offsets
Tasks are classified as either:
- **PRE_RENEWAL** — due before the policy expiration date (negative `daysOffset`)
- **POST_RENEWAL** — due after the policy expiration date (positive `daysOffset`)
The `daysOffset` value is configurable per template, allowing precise scheduling of each step in the renewal workflow.
### 4.6 Task Assignment
- Tasks support multi-user assignment via the `TaskAssignment` join table
- Workload visibility: `GET /api/dashboard/workload` provides manager-facing metrics on task distribution across team members
- Dashboard displays per-user statistics: overdue, due today, upcoming
### 4.7 N/A Marking
When a task is marked as `NA`, the `naReason` field is required. This ensures accountability and auditability for skipped tasks. Similarly, `CANCELLED` status requires `cancelledReason`.
### 4.8 API Endpoints
| Method | Path | Purpose | Permission |
|--------|------|---------|------------|
| `GET` | `/api/tasks` | List tasks with filtering (status, clientId, assignedToMe, pagination) | `tasks.read` |
| `POST` | `/api/tasks` | Create task | `tasks.write` |
Query parameters: `status`, `clientId`, `assignedToMe`, `page`, `limit` (default 50).
---
## 5. Renewal Grouping & Policy Exclusion
> **Status: NEW — not yet implemented.** This section defines net-new functionality for the MVP.
### 5.1 Problem Statement
A single client may have multiple policies with the same expiration date. Currently, there is no mechanism to control how renewal tasks are generated across those policies — whether they share a single task set or need separate ones. Additionally, some policies (being non-renewed, rewritten, or cancelled) should be excluded from task generation entirely.
### 5.2 Default Behavior: Client-Level Task Sets
When no explicit grouping exists, the system generates **one set of renewal tasks per client** based on the client's policies and their expiration dates. This preserves backward compatibility with the existing workflow.
### 5.3 Renewal Groups
A new `RenewalGroup` entity enables manual control over how policies are grouped for task generation:
**RenewalGroup model (new):**
| Field | Type | Description |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `name` | String | User-provided label (e.g., "Main BOP + Auto bundle") |
| `clientId` | FK → Client | Owning client |
| `createdBy` | FK → User | Who created the group |
| `createdAt` | DateTime | Timestamp |
| `updatedAt` | DateTime | Timestamp |
**RenewalGroupPolicy join table (new):**
| Field | Type | Description |
|-------|------|-------------|
| `renewalGroupId` | FK → RenewalGroup | Group membership |
| `policyId` | FK → Policy | Included policy |
### 5.4 Manual Grouping
Users can create explicit renewal groups by selecting which policies should share a single task set:
- Select a client
- Choose one or more policies from that client
- Name the group
- Task generation uses the group rather than the full client policy set
**Use case:** A client has 5 policies but 3 of them are bundled and should be renewed together. Create one group with those 3 policies — they get one shared task set. The remaining 2 policies can be in separate groups or fall through to default behavior.
### 5.5 Splitting
When a client's policies need separate renewal workflows, users can split them into distinct renewal groups:
- Each group gets its own independent set of renewal tasks
- Groups can contain one or many policies
- Ungrouped policies fall back to default client-level behavior
### 5.6 Policy Exclusion
Individual policies can be marked as excluded from task generation:
**Policy model addition (new field):**
| Field | Type | Description |
|-------|------|-------------|
| `isExcludedFromRenewal` | Boolean (default: false) | Excludes policy from task generation |
| `exclusionReason` | String (nullable) | Required when excluded — documents why |
**Use cases for exclusion:**
- Policy is being non-renewed
- Policy is being rewritten under a new policy number
- Policy is being moved to a different carrier outside the normal renewal flow
- Client has requested cancellation
Excluded policies are skipped during task auto-generation but remain visible in the client's policy list with a visual indicator.
### 5.7 Task Generation Logic (Updated)
With renewal grouping and exclusion in place, task auto-generation follows this precedence:
1. **Exclude** any policy where `isExcludedFromRenewal = true`
2. **Grouped policies**: For each `RenewalGroup`, generate one task set using the group's policies
3. **Ungrouped policies**: For remaining policies not in any group, generate one task set per client (default behavior)
---
## Appendix
### A. Technology Stack
| Layer | Technology |
|-------|-----------|
| Frontend | React, TypeScript, Next.js 16 (App Router), Tailwind CSS, shadcn/ui |
| Backend | Next.js API Routes, NextAuth.js 4.x (JWT) |
| Database | PostgreSQL via Prisma ORM 7.x |
| Source DB | SQL Server via mssql (AFW/AMS360) |
| Scheduling | node-cron |
| Deployment | Docker |
### B. Data Model Index
| Model | Purpose | Status |
|-------|---------|--------|
| User | Application users synced from AFW employees | Existing |
| Client | Customers synced from AFW | Existing |
| Policy | Insurance policies synced from AFW | Existing |
| Task | Renewal workflow tasks | Existing |
| TaskTemplate | Reusable task definitions | Existing |
| TaskAssignment | Multi-user task assignment | Existing |
| Designation | Client shape/classification | Existing |
| AuditLog | Action audit trail | Existing |
| Notification | User-facing alerts | Existing |
| NotificationPreference | Per-user delivery prefs | Existing |
| SyncLog | Sync execution history | Existing |
| SyncConfig | Sync configuration key-value store | Existing |
| EntraGroupRoleMapping | Azure AD group → role mapping | Existing |
| UserRole | Direct user → role assignment | Existing |
| **RenewalGroup** | **Policy grouping for shared task sets** | **New** |
| **RenewalGroupPolicy** | **Group ↔ Policy join table** | **New** |
### C. Related Documents
- [PRD — OnDeck Policy Renewal](./prd-ondeck-policy-renewal.md)
- [Tasks — PRD OnDeck Policy Renewal](./tasks-prd-ondeck-policy-renewal.md)

View file

@ -0,0 +1,564 @@
# PRD: OnDeck - Policy Renewal Workflow Management System
## 1. Introduction/Overview
### 1.1 Problem Statement
Insurance brokerages managing large policy portfolios face significant challenges coordinating renewal activities across departments:
- **Fragmented Data:** Client and policy data lives in AMS360 (AFW) with no custom workflow layer
- **Manual Coordination:** Renewal tasks are tracked manually or in disconnected systems
- **No Classification System:** No systematic way to assign internal designations or classifications to clients
- **Limited Visibility:** No insight into workload distribution or deadline compliance across teams
- **Decentralized Personnel Management:** Personnel assignments to clients aren't centrally managed
### 1.2 Solution
**OnDeck** is a unified web application that:
- Syncs client and policy data from the AFW database
- Adds custom metadata layers (Shape designations, personnel assignments)
- Provides renewal-based task management with auto-generation from templates
- Delivers dashboards for workload visibility and deadline compliance
### 1.3 Goal
Create a streamlined, centralized policy renewal workflow system that reduces missed deadlines, improves team coordination, and provides management visibility into renewal operations across all departments.
---
## 2. Goals
### 2.1 Primary Goals
| Goal | Metric | Target |
|------|--------|--------|
| Eliminate missed renewal deadlines | % of tasks completed on time | 95% within 6 months |
| Reduce manual coordination effort | User-reported time savings | 40% reduction |
| Provide workload visibility | Manager dashboard adoption | 100% of managers using weekly |
| Centralize client classification | Clients with Shape assignments | 90% within 90 days |
### 2.2 Secondary Goals
- Enable extensible client designation system (Shape, Shape2, future designations)
- Provide comprehensive audit trails for compliance
- Support 50 users with 10 concurrent without performance degradation
- Integrate seamlessly with existing AFW database (read-only)
---
## 3. User Stories
### 3.1 Account Executive Stories
| ID | Story | Acceptance Criteria |
|----|-------|---------------------|
| AE-1 | As an Account Executive, I want to see all my upcoming renewal tasks in one dashboard so that I can prioritize my work effectively | Dashboard shows tasks sorted by due date with overdue items highlighted |
| AE-2 | As an Account Executive, I want tasks to auto-generate based on renewal dates so that I don't have to manually create routine tasks | Tasks appear automatically when policy enters renewal window |
| AE-3 | As an Account Executive, I want to mark tasks as N/A with required notes so that I can document why certain tasks don't apply | N/A status requires notes field; task is removed from active list |
| AE-4 | As an Account Executive, I want to assign Shape designations to my clients so that I can categorize them for targeted service | Shape dropdown available on client detail; changes logged |
| AE-5 | As an Account Executive, I want to view my clients' policy details and renewal dates so that I can prepare for upcoming renewals | Client detail shows all policies with days-until-renewal |
### 3.2 Manager Stories
| ID | Story | Acceptance Criteria |
|----|-------|---------------------|
| MG-1 | As a Manager, I want to view workload distribution across my team so that I can balance assignments | Dashboard shows task count per team member with visual chart |
| MG-2 | As a Manager, I want to see completion rates and overdue tasks by user so that I can identify issues | Metrics table with drill-down to individual tasks |
| MG-3 | As a Manager, I want to reassign tasks between team members so that I can handle absences | Bulk reassignment UI with audit logging |
| MG-4 | As a Manager, I want to configure department task templates so that our workflows are standardized | Template CRUD interface per department |
| MG-5 | As a Manager, I want to see SLA compliance metrics so that I can report on team performance | % on-time completion displayed prominently |
### 3.3 Admin Stories
| ID | Story | Acceptance Criteria |
|----|-------|---------------------|
| AD-1 | As an Admin, I want to configure sync schedule via UI so that I can adjust timing without code changes | Settings page with time picker; changes take effect next cycle |
| AD-2 | As an Admin, I want to manage Shape definitions with descriptions and rules so that designations are consistent | Shape CRUD with name, description, color, rules, active status |
| AD-3 | As an Admin, I want to map Entra groups to application roles so that access is controlled | Mapping UI showing groups → roles with add/remove |
| AD-4 | As an Admin, I want to monitor sync health and view logs so that I can troubleshoot issues | Sync dashboard with last run, status, row counts, error log |
| AD-5 | As an Admin, I want to configure notification channels (in-app, Teams, Email) so that users receive alerts appropriately | Settings page with channel toggles per notification type |
### 3.4 Claims Department Stories
| ID | Story | Acceptance Criteria |
|----|-------|---------------------|
| CL-1 | As a Claims Specialist, I want to view assigned clients and their renewal dates so that I can proactively address coverage needs | Filtered client list with renewal timeline |
| CL-2 | As a Claims Specialist, I want to create claims-related tasks tied to renewals so that claims considerations are included | Task creation with Claims department assignment |
---
## 4. Functional Requirements
### 4.1 Authentication & Authorization
| ID | Requirement | Priority |
|----|-------------|----------|
| AUTH-1 | The system must authenticate users via Microsoft Entra ID using SSO (MSAL.js) | P0 |
| AUTH-2 | The system must extract group claims from Entra tokens for role mapping | P0 |
| AUTH-3 | The system must support configurable Entra Group → Role mappings via Admin UI | P0 |
| AUTH-4 | The system must enforce role-based access control at the API layer | P0 |
| AUTH-5 | The system must leverage existing Entra MFA policies (no additional MFA implementation) | P0 |
| AUTH-6 | The system must support configurable session timeout (default 8 hours) | P1 |
| AUTH-7 | The system must maintain audit logs of all permission changes | P1 |
**Roles:**
- **Admin:** Full system access, user management, sync configuration
- **Manager:** Department data access, task assignment, team dashboards
- **Account Executive:** Assigned client access, personal tasks, client updates
- **Claims:** Assigned client access, claims-related tasks
### 4.2 AFW Data Sync Engine
| ID | Requirement | Priority |
|----|-------------|----------|
| SYNC-1 | The system must perform automated daily sync at admin-configurable time (default 2 AM) | P0 |
| SYNC-2 | The system must connect to AFW SQL Server database (read-only) | P0 |
| SYNC-3 | The system must sync policies with expiration dates within current calendar year + 24 months | P0 |
| SYNC-4 | The system must perform incremental sync based on ModifiedDate/ChangedDate fields | P0 |
| SYNC-5 | The system must sync: Clients (AFW_Customer), Policies (AFW_BasicPolInfo), Employees (AFW_Employee), Departments (AFW_GeneralLedgerDepartment) | P0 |
| SYNC-6 | The system must log all sync runs with: start time, end time, rows processed, rows inserted, rows updated, errors | P0 |
| SYNC-7 | The system must allow manual sync trigger by Admin users | P1 |
| SYNC-8 | The system must never delete local records (mark inactive if removed from AFW) | P0 |
| SYNC-9 | The system must provide Admin UI for configuring sync schedule | P1 |
| SYNC-10 | The system must implement retry logic (3 attempts with exponential backoff) on sync failure | P1 |
**AFW → Local Data Mapping:**
```
AFW_Customer → clients
CustId → ams_customer_id
FirmNameCust → name
CustNo → customer_number
Addr1, Addr2, City, State, ZipCode → address fields
EMail → email
BusPhone → phone
Prod1Code → producer_code
CsrCode → csr_code
GLDeptCode → department_code
AFW_BasicPolInfo → policies
PolId → ams_policy_id
CustId → client_id (FK)
PolNo → policy_number
PolEffDate → effective_date
PolExpDate → expiration_date (RENEWAL DATE)
PolTypeLOB → policy_type
CoCode → parent_company_code
WritingCoCode → writing_company_code
ExecCode → executive_code
CsrCode → csr_code
RenewalRptFlag → status (via AFW_PRCode lookup)
FullTermPremium → premium_amount
GLDeptCode → department_code
```
### 4.3 Client Management
| ID | Requirement | Priority |
|----|-------------|----------|
| CLI-1 | The system must display all synced clients in a searchable, filterable list | P0 |
| CLI-2 | The system must support Shape designation assignment (primary) | P0 |
| CLI-3 | The system must support Shape2 designation assignment (secondary) | P0 |
| CLI-4 | The system must support primary personnel assignment from Entra users | P0 |
| CLI-5 | The system must support additional personnel assignments (many-to-many) | P1 |
| CLI-6 | The system must provide client notes field for internal communications | P1 |
| CLI-7 | The system must support extensible custom fields via JSONB storage | P2 |
| CLI-8 | The system must maintain audit trail of all client modifications | P0 |
| CLI-9 | The system must filter client access based on user role and assignments | P0 |
### 4.4 Shape/Designation Management
| ID | Requirement | Priority |
|----|-------------|----------|
| SHP-1 | The system must support Admin-managed Shape definitions | P0 |
| SHP-2 | Each Shape must have: id, name, description, color (hex), display_order, is_active | P0 |
| SHP-3 | The system must support deactivating Shapes (preserve historical data, hide from new assignments) | P0 |
| SHP-4 | The system must support rules/criteria field for Shape definitions (text description) | P1 |
| SHP-5 | The UI must be designed to support additional designation types beyond Shape/Shape2 in future | P1 |
| SHP-6 | The system must display Shape color coding in client lists and details | P0 |
### 4.5 Task Management
| ID | Requirement | Priority |
|----|-------------|----------|
| TSK-1 | The system must support task creation with: title, description, department, timing, days_offset, priority | P0 |
| TSK-2 | The system must calculate due_date as: policy.expiration_date + days_offset | P0 |
| TSK-3 | The system must support task statuses: NOT_STARTED, IN_PROGRESS, COMPLETED, BLOCKED, N/A, CANCELLED | P0 |
| TSK-4 | The system must require notes when setting status to N/A | P0 |
| TSK-5 | The system must support task priorities: LOW, MEDIUM, HIGH, URGENT | P0 |
| TSK-6 | The system must support task assignment to one or more users | P0 |
| TSK-7 | The system must track: created_by, created_at, completed_by, completed_at, updated_at | P0 |
| TSK-8 | The system must support task filtering by: status, assignee, due date range, client, department | P0 |
| TSK-9 | The system must support bulk task operations (status update, reassignment) | P1 |
| TSK-10 | The system must require cancellation_reason when setting status to CANCELLED | P1 |
### 4.6 Task Templates & Auto-Generation
| ID | Requirement | Priority |
|----|-------------|----------|
| TPL-1 | The system must support department-based task templates | P0 |
| TPL-2 | Templates must define: name, description, department, timing (PRE/POST_RENEWAL), days_offset, default_priority | P0 |
| TPL-3 | The system must auto-generate tasks from templates when policy enters renewal window | P0 |
| TPL-4 | The system must assign auto-generated tasks to client's primary personnel by default | P0 |
| TPL-5 | The system must support template activation/deactivation | P1 |
| TPL-6 | The system must prevent duplicate task generation for same policy/template combination | P0 |
| TPL-7 | Admin/Manager must be able to configure renewal window trigger (e.g., 90 days before expiration) | P1 |
**Example Template Structure:**
```
Department: Commercial Lines
Template: "Standard Commercial Renewal"
Tasks:
1. Review coverage limits (PRE_RENEWAL, -60 days, HIGH)
2. Contact client for updates (PRE_RENEWAL, -45 days, MEDIUM)
3. Request renewal quotes (PRE_RENEWAL, -30 days, HIGH)
4. Present renewal options (PRE_RENEWAL, -21 days, HIGH)
5. Bind coverage (PRE_RENEWAL, -7 days, URGENT)
6. Send policy documents (POST_RENEWAL, +5 days, MEDIUM)
```
### 4.7 Dashboards & Reporting
| ID | Requirement | Priority |
|----|-------------|----------|
| DSH-1 | The system must provide Personal Dashboard for Account Executives and Claims users | P0 |
| DSH-2 | Personal Dashboard must show: My Tasks (overdue, due today, due this week, upcoming 30 days) | P0 |
| DSH-3 | Personal Dashboard must show: My Clients quick access list | P0 |
| DSH-4 | Personal Dashboard must show: Quick stats (completed this week, overdue count, upcoming renewals) | P0 |
| DSH-5 | The system must provide Manager Dashboard with team overview | P0 |
| DSH-6 | Manager Dashboard must show: Workload distribution (tasks per team member) | P0 |
| DSH-7 | Manager Dashboard must show: Completion rates by user | P0 |
| DSH-8 | Manager Dashboard must show: Overdue tasks by user with drill-down | P0 |
| DSH-9 | Manager Dashboard must show: Department metrics (tasks by status, renewal timeline, SLA compliance) | P1 |
| DSH-10 | The system must provide Admin Dashboard with system health and cross-department views | P1 |
| DSH-11 | Admin Dashboard must show: Last sync time, status, row counts, error summary | P0 |
| DSH-12 | All dashboards must load within 2 seconds | P0 |
**KPIs to Track:**
| KPI | Calculation | Visualization |
|-----|-------------|---------------|
| Tasks Completed | Count by period | Line chart (trend) |
| Tasks Overdue | due_date < today AND status NOT IN (COMPLETED, N/A, CANCELLED) | Number + list |
| Upcoming Renewals | Policies expiring in next 30/60/90 days | Count + calendar |
| Workload per Person | Active tasks assigned per user | Bar chart |
| On-Time Completion Rate | (Completed on/before due_date) / Total completed | Percentage |
| N/A Rate | Tasks marked N/A / Total tasks | Percentage (monitor for abuse) |
### 4.8 Notifications
| ID | Requirement | Priority |
|----|-------------|----------|
| NOT-1 | The system must support in-app notifications for task assignments and overdue alerts | P0 |
| NOT-2 | The system must provide Admin UI to configure notification channels per notification type | P1 |
| NOT-3 | The system must support future integration with Microsoft Teams notifications | P2 |
| NOT-4 | The system must support future integration with Email notifications | P2 |
| NOT-5 | Users must be able to configure personal notification preferences | P2 |
---
## 5. Non-Goals (Out of Scope)
### 5.1 Phase 1 Exclusions
- **Mobile native app** - Responsive web only; mobile app is future phase
- **Email/Teams notifications** - In-app only for MVP; channels configurable for future
- **Document management** - No file attachments or document storage
- **Policy binding/issuance** - Read-only integration with AFW
- **Carrier portal integration** - No direct carrier connections
- **Commission tracking** - No compensation or commission management
- **Client self-service portal** - Internal users only
- **Multi-tenant support** - Single brokerage deployment
- **Advanced analytics/BI** - Basic KPIs only; advanced reporting future phase
- **Workflow automation beyond task generation** - No complex conditional logic
### 5.2 Explicitly Deferred
- API for third-party integrations
- Custom report builder
- Calendar view for renewals
- Bulk import/export tools
- Integration with other AMS systems
---
## 6. Design Considerations
### 6.1 Technology Stack
| Layer | Technology | Rationale |
|-------|------------|-----------|
| **Frontend** | React + TypeScript + Next.js | Modern, type-safe, SSR capable |
| **UI Framework** | Tailwind CSS + shadcn/ui | Per user requirement; accessible, customizable |
| **State Management** | TanStack Query | Server state caching, optimistic updates |
| **Backend** | Next.js API Routes | Unified codebase, serverless-ready |
| **ORM** | Prisma | Type-safe database access, migrations |
| **Database** | PostgreSQL | Robust, JSONB support, deployed in Docker |
| **Auth** | NextAuth.js + Azure AD provider | Native Entra integration |
| **Sync Engine** | Node.js + mssql package | SQL Server connectivity for AFW |
| **Scheduler** | node-cron | In-process scheduling for sync |
| **Deployment** | Docker containers | Per user requirement; on-premise |
### 6.2 UI/UX Guidelines
- **Design System:** shadcn/ui components with Tailwind CSS
- **Color Scheme:** Professional, accessible color palette with Shape color accents
- **Layout:** Sidebar navigation, responsive breakpoints for tablet/desktop
- **Data Tables:** Sortable, filterable, paginated (default 50 rows)
- **Forms:** Inline validation, clear error messages
- **Loading States:** Skeleton loaders, optimistic updates where appropriate
- **Accessibility:** WCAG 2.1 AA compliance
### 6.3 Key UI Components
1. **Dashboard Cards** - KPI display with trend indicators
2. **Task List** - Filterable table with status badges, priority indicators
3. **Client Detail** - Tabbed interface (Overview, Policies, Tasks, Notes, History)
4. **Shape Selector** - Dropdown with color swatches
5. **Personnel Picker** - Searchable Entra user selector
6. **Sync Status Widget** - Real-time sync health indicator
7. **Notification Center** - Bell icon with unread count, dropdown list
---
## 7. Technical Considerations
### 7.1 Database Schema
```sql
-- Core tables (see full schema in prd-input document Section 4.1)
-- Key additions based on requirements:
-- Task status enum (updated)
CREATE TYPE task_status AS ENUM (
'NOT_STARTED',
'IN_PROGRESS',
'COMPLETED',
'BLOCKED',
'NA', -- Added: Not Applicable
'CANCELLED'
);
-- Tasks table (updated)
CREATE TABLE tasks (
-- ... existing fields ...
na_reason TEXT, -- Required when status = 'NA'
cancelled_reason TEXT, -- Required when status = 'CANCELLED'
-- ...
);
-- Sync configuration table (new)
CREATE TABLE sync_config (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
sync_time TIME NOT NULL DEFAULT '02:00:00',
is_enabled BOOLEAN DEFAULT true,
retention_months INTEGER DEFAULT 24,
updated_by UUID REFERENCES users(id),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Notification preferences (new)
CREATE TABLE notification_preferences (
user_id UUID REFERENCES users(id) PRIMARY KEY,
in_app_enabled BOOLEAN DEFAULT true,
email_enabled BOOLEAN DEFAULT false,
teams_enabled BOOLEAN DEFAULT false,
overdue_alerts BOOLEAN DEFAULT true,
assignment_alerts BOOLEAN DEFAULT true,
updated_at TIMESTAMP DEFAULT NOW()
);
-- Shape rules field (added to shapes table)
ALTER TABLE shapes ADD COLUMN rules TEXT;
```
### 7.2 AFW Database Connection
- **Server:** 63.89.3.224:1433
- **Database:** A1100080D1
- **Connection:** Read-only service account
- **Key Tables:** AFW_Customer, AFW_BasicPolInfo, AFW_Employee, AFW_GeneralLedgerDepartment, AFW_Company, AFW_PRCode, AFW_PolicyPersonnel
### 7.3 Performance Requirements
| Metric | Target |
|--------|--------|
| Dashboard load time | < 2 seconds |
| List page load time | < 1 second |
| Sync duration (daily) | < 30 minutes |
| Concurrent users | 10 |
| Total users | 50 |
| Database size (estimated) | < 10 GB |
### 7.4 Docker Deployment
```yaml
# docker-compose.yml structure
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://...
- AZURE_AD_CLIENT_ID=...
- AFW_CONNECTION_STRING=...
depends_on:
- db
db:
image: postgres:17
volumes:
- pgdata:/var/lib/postgresql/data
environment:
- POSTGRES_DB=ondeck
- POSTGRES_USER=ondeck_user
- POSTGRES_PASSWORD=...
```
### 7.5 Security Considerations
- All traffic over HTTPS (TLS 1.2+)
- Database credentials in environment variables
- Read-only AFW database connection
- Parameterized queries (Prisma handles this)
- Input validation on all endpoints
- RBAC enforced at API middleware layer
- Audit logging for sensitive operations
- Session tokens with secure flags
---
## 8. Success Metrics
### 8.1 Adoption Metrics (30/60/90 day targets)
| Metric | 30 Days | 60 Days | 90 Days |
|--------|---------|---------|---------|
| Active users (weekly login) | 60% | 75% | 85% |
| Clients with Shape assigned | 30% | 60% | 90% |
| Tasks created via templates | 50% | 70% | 85% |
| Manager dashboard usage | 50% | 80% | 100% |
### 8.2 Efficiency Metrics
| Metric | Baseline | 6-Month Target |
|--------|----------|----------------|
| On-time task completion | TBD | 95% |
| Missed renewal deadlines | TBD | < 1% |
| Manual coordination time | TBD | -40% |
| Task completion time (avg) | TBD | -25% |
### 8.3 System Health Metrics
| Metric | Target |
|--------|--------|
| Sync success rate | 99% |
| System uptime (business hours) | 99.5% |
| Dashboard response time | < 2 sec (p95) |
| Error rate | < 0.1% |
---
## 9. Open Questions
### 9.1 Resolved (from clarifying questions)
| Question | Resolution |
|----------|------------|
| Priority departments | All departments (phased rollout acceptable) |
| Task auto-generation | Auto-generate; users mark status including N/A with notes |
| Shape extensibility | Start with Shape/Shape2; UI designed for future expansion |
| Sync schedule | 2 AM default; Admin-configurable via UI |
| Historical data | Current calendar year + 24 months |
| Notifications | In-app MVP; Teams/Email configurable for future |
| Mobile | Responsive web; native app future phase |
| Hosting | On-premise Docker deployment |
| User volume | 50 users, 10 concurrent |
### 9.2 Remaining Questions
1. **Entra Configuration:** What are the Entra Group names/IDs for role mapping?
2. **AFW Credentials:** Who provides the read-only service account for AFW database?
3. **Shape Definitions:** What are the initial Shape values to seed? (names, descriptions, colors)
4. **Department Templates:** What are the specific task templates per department?
5. **Renewal Window:** How many days before expiration should tasks auto-generate? (suggest 90)
6. **Backup Strategy:** What is the backup/recovery requirement for the PostgreSQL database?
7. **SSL Certificates:** Who provides/manages SSL certificates for HTTPS?
---
## 10. Implementation Phases
### Phase 1 - MVP (8-10 weeks)
**Sprint 1-2: Foundation**
- [ ] Project setup (Next.js, Prisma, Docker, shadcn/ui)
- [ ] Database schema implementation
- [ ] Entra ID authentication integration
- [ ] Basic role-based access control
**Sprint 3-4: Data Layer**
- [ ] AFW sync engine (clients, policies)
- [ ] Sync scheduling with Admin UI
- [ ] Sync logging and monitoring
- [ ] Client list with search/filter
**Sprint 5-6: Core Features**
- [ ] Client detail page with Shape assignment
- [ ] Personnel assignment (primary)
- [ ] Shape management Admin UI
- [ ] Task CRUD operations
**Sprint 7-8: Task Automation**
- [ ] Task templates per department
- [ ] Auto-generation engine
- [ ] Task status workflow (including N/A with notes)
- [ ] Personal dashboard
**Sprint 9-10: Polish & Deploy**
- [ ] Manager dashboard
- [ ] Admin dashboard (sync health)
- [ ] In-app notifications
- [ ] Testing, bug fixes, deployment
### Phase 2 - Enhancement (6-8 weeks)
- [ ] Additional personnel assignments
- [ ] Bulk task operations
- [ ] Advanced filtering and search
- [ ] Teams/Email notification integration
- [ ] Extended reporting
### Phase 3 - Advanced (8-10 weeks)
- [ ] Calendar view for renewals
- [ ] Custom fields beyond Shape/Shape2
- [ ] API for external integrations
- [ ] Mobile native application
- [ ] Advanced analytics
---
*Document Version: 1.0*
*Created: January 2026*
*Last Updated: January 2026*
*Author: AI Assistant based on stakeholder input*
---
## Appendix A: AFW Database Reference
See `/opt/projects/OnDeck/dev/DATABASE_REFERENCE.md` for complete AFW table schemas, relationships, and query patterns.
## Appendix B: Local Database Connection
```
Host: localhost
Port: 5432
Database: ondeck
User: ondeck_user
Password: ondeck_password_2026!
```
See `/opt/projects/OnDeck/dev/.postgres` for connection strings.

View file

@ -0,0 +1,262 @@
# Tasks: OnDeck Policy Renewal Workflow Management System
> Generated from: `prd-ondeck-policy-renewal.md`
## Relevant Files
- `package.json` - Project dependencies and scripts
- `docker-compose.yml` - Docker configuration for app and PostgreSQL
- `Dockerfile` - Container build configuration
- `.env.example` - Environment variable template
- `prisma/schema.prisma` - Database schema definition
- `prisma/migrations/` - Database migration files
- `prisma/seed.ts` - Database seeding script
- `src/app/layout.tsx` - Root layout with providers
- `src/app/page.tsx` - Landing/redirect page
- `src/app/api/auth/[...nextauth]/route.ts` - NextAuth.js API route for Entra ID
- `src/app/api/auth/[...nextauth]/route.test.ts` - Tests for auth route
- `src/lib/auth.ts` - NextAuth configuration and helpers
- `src/lib/auth.test.ts` - Tests for auth helpers
- `src/middleware.ts` - Auth and RBAC middleware
- `src/middleware.test.ts` - Tests for middleware
- `src/app/api/sync/route.ts` - Manual sync trigger endpoint
- `src/app/api/sync/route.test.ts` - Tests for sync endpoint
- `src/lib/sync/sync-engine.ts` - AFW sync logic
- `src/lib/sync/sync-engine.test.ts` - Tests for sync engine
- `src/lib/sync/scheduler.ts` - Cron-based sync scheduler
- `src/lib/sync/afw-connection.ts` - SQL Server connection to AFW
- `src/lib/sync/afw-connection.test.ts` - Tests for AFW connection
- `src/lib/sync/mappers.ts` - AFW to local data mappers
- `src/lib/sync/mappers.test.ts` - Tests for data mappers
- `src/app/(dashboard)/layout.tsx` - Dashboard layout with sidebar
- `src/app/(dashboard)/dashboard/page.tsx` - Personal dashboard
- `src/app/(dashboard)/dashboard/page.test.tsx` - Tests for personal dashboard
- `src/app/(dashboard)/clients/page.tsx` - Client list page
- `src/app/(dashboard)/clients/page.test.tsx` - Tests for client list
- `src/app/(dashboard)/clients/[id]/page.tsx` - Client detail page
- `src/app/(dashboard)/clients/[id]/page.test.tsx` - Tests for client detail
- `src/app/(dashboard)/tasks/page.tsx` - Task list page
- `src/app/(dashboard)/tasks/page.test.tsx` - Tests for task list
- `src/app/(dashboard)/manager/page.tsx` - Manager dashboard
- `src/app/(dashboard)/manager/page.test.tsx` - Tests for manager dashboard
- `src/app/(dashboard)/admin/page.tsx` - Admin dashboard
- `src/app/(dashboard)/admin/shapes/page.tsx` - Shape management page
- `src/app/(dashboard)/admin/templates/page.tsx` - Task template management
- `src/app/(dashboard)/admin/sync/page.tsx` - Sync configuration page
- `src/app/(dashboard)/admin/users/page.tsx` - User/role management page
- `src/app/api/clients/route.ts` - Clients API endpoints
- `src/app/api/clients/route.test.ts` - Tests for clients API
- `src/app/api/clients/[id]/route.ts` - Single client API
- `src/app/api/tasks/route.ts` - Tasks API endpoints
- `src/app/api/tasks/route.test.ts` - Tests for tasks API
- `src/app/api/tasks/[id]/route.ts` - Single task API
- `src/app/api/shapes/route.ts` - Shapes API endpoints
- `src/app/api/shapes/route.test.ts` - Tests for shapes API
- `src/app/api/templates/route.ts` - Task templates API
- `src/app/api/templates/route.test.ts` - Tests for templates API
- `src/app/api/notifications/route.ts` - Notifications API
- `src/app/api/admin/sync-config/route.ts` - Sync configuration API
- `src/app/api/admin/roles/route.ts` - Role mapping API
- `src/components/ui/` - shadcn/ui components directory
- `src/components/layout/sidebar.tsx` - Navigation sidebar component
- `src/components/layout/header.tsx` - Header with user menu
- `src/components/clients/client-list.tsx` - Client list component
- `src/components/clients/client-detail.tsx` - Client detail component
- `src/components/clients/shape-selector.tsx` - Shape dropdown component
- `src/components/clients/personnel-picker.tsx` - Entra user picker
- `src/components/tasks/task-list.tsx` - Task list component
- `src/components/tasks/task-card.tsx` - Individual task card
- `src/components/tasks/task-form.tsx` - Task create/edit form
- `src/components/tasks/status-select.tsx` - Status dropdown with N/A notes
- `src/components/dashboard/kpi-card.tsx` - KPI display card
- `src/components/dashboard/task-summary.tsx` - Task summary widget
- `src/components/dashboard/workload-chart.tsx` - Workload distribution chart
- `src/components/notifications/notification-bell.tsx` - Notification icon/dropdown
- `src/components/admin/shape-form.tsx` - Shape create/edit form
- `src/components/admin/template-form.tsx` - Template create/edit form
- `src/components/admin/sync-status.tsx` - Sync health widget
- `src/lib/db.ts` - Prisma client singleton
- `src/lib/utils.ts` - Utility functions
- `src/types/index.ts` - TypeScript type definitions
- `src/types/enums.ts` - Enum definitions matching Prisma
- `tailwind.config.ts` - Tailwind CSS configuration
- `jest.config.js` - Jest test configuration
- `jest.setup.js` - Jest setup file
### Notes
- Unit tests should typically be placed alongside the code files they are testing (e.g., `MyComponent.tsx` and `MyComponent.test.tsx` in the same directory).
- Use `npx jest [optional/path/to/test/file]` to run tests. Running without a path executes all tests found by the Jest configuration.
- This project uses Next.js App Router with server components by default.
- shadcn/ui components are installed via `npx shadcn-ui@latest add [component-name]`.
- Environment variables should never be committed; use `.env.example` as a template.
## Tasks
- [x] 1.0 Project Setup & Infrastructure
- [x] 1.1 Initialize Next.js project with TypeScript (`npx create-next-app@latest ondeck --typescript --tailwind --eslint --app --src-dir`)
- [x] 1.2 Install and configure shadcn/ui (`npx shadcn-ui@latest init`)
- [x] 1.3 Install core shadcn/ui components (button, card, input, select, table, dialog, dropdown-menu, tabs, badge, toast, avatar, skeleton)
- [x] 1.4 Create `docker-compose.yml` with app service and PostgreSQL service (use ondeck database credentials)
- [x] 1.5 Create `Dockerfile` for Next.js production build
- [x] 1.6 Create `.env.example` with all required environment variables (DATABASE_URL, NEXTAUTH_*, AZURE_AD_*, AFW_*)
- [x] 1.7 Configure Tailwind with custom theme colors for Shape designations
- [x] 1.8 Set up Jest testing framework with React Testing Library
- [x] 1.9 Create base project folder structure (`src/app`, `src/components`, `src/lib`, `src/types`)
- [x] 1.10 Create `src/lib/utils.ts` with common utility functions (cn, formatDate, etc.)
- [x] 2.0 Authentication & Authorization (Entra ID)
- [x] 2.1 Install NextAuth.js and Azure AD provider (`npm install next-auth @azure/msal-node`)
- [x] 2.2 Create NextAuth configuration in `src/lib/auth.ts` with Azure AD provider
- [x] 2.3 Configure Azure AD provider to request group claims in token
- [x] 2.4 Create `src/app/api/auth/[...nextauth]/route.ts` API route
- [x] 2.5 Create auth session provider wrapper component
- [x] 2.6 Implement user upsert on first login (create user record from Entra token)
- [x] 2.7 Create role resolution logic (map Entra groups to app roles from entra_group_role_mappings table)
- [x] 2.8 Create `src/middleware.ts` for route protection and RBAC enforcement
- [x] 2.9 Define permission sets per role (Admin, Manager, Account Executive, Claims) in constants
- [x] 2.10 Create `useSession` and `usePermissions` custom hooks for client components
- [x] 2.11 Create higher-order component or wrapper for role-based UI rendering
- [x] 2.12 Write unit tests for auth helpers and role resolution logic
- [x] 3.0 Database Schema & ORM Setup
- [x] 3.1 Install Prisma (`npm install prisma @prisma/client`)
- [x] 3.2 Initialize Prisma with PostgreSQL (`npx prisma init --datasource-provider postgresql`)
- [x] 3.3 Define User model with Entra fields (entra_oid, email, display_name, department, is_active, last_login_at)
- [x] 3.4 Define Role model with permissions JSONB field
- [x] 3.5 Define EntraGroupRoleMapping model for group-to-role configuration
- [x] 3.6 Define UserRole junction table for direct role assignments
- [x] 3.7 Define Shape model with name, description, color, rules, display_order, is_active
- [x] 3.8 Define Client model with AMS sync fields and custom fields (shape_id, shape2_id, primary_personnel_id, notes, custom_fields JSONB)
- [x] 3.9 Define ClientPersonnel junction table for additional personnel assignments
- [x] 3.10 Define Policy model with AMS sync fields and expiration_date index
- [x] 3.11 Define TaskStatus and TaskPriority enums (include NA status)
- [x] 3.12 Define TaskTemplate model with department, timing, days_offset, default_priority
- [x] 3.13 Define Task model with all fields including na_reason, cancelled_reason
- [x] 3.14 Define TaskAssignment junction table for multi-user assignment
- [x] 3.15 Define SyncLog model for sync run tracking
- [x] 3.16 Define SyncConfig model for admin-configurable sync settings
- [x] 3.17 Define AuditLog model for change tracking
- [x] 3.18 Define Notification model for in-app notifications
- [x] 3.19 Define NotificationPreference model for user notification settings
- [x] 3.20 Create initial migration (`npx prisma migrate dev --name init`)
- [x] 3.21 Create `src/lib/db.ts` Prisma client singleton
- [x] 3.22 Create `prisma/seed.ts` with default roles, initial shapes, and sample task templates
- [x] 3.23 Run seed script (`npx prisma db seed`)
- [x] 4.0 AFW Data Sync Engine
- [x] 4.1 Install SQL Server driver (`npm install mssql`)
- [x] 4.2 Create `src/lib/sync/afw-connection.ts` with connection pool management
- [x] 4.3 Create AFW query functions for: AFW_Customer, AFW_BasicPolInfo, AFW_Employee, AFW_GeneralLedgerDepartment, AFW_Company, AFW_PRCode
- [x] 4.4 Implement date filter for policies (current year + 24 months expiration)
- [x] 4.5 Create `src/lib/sync/mappers.ts` with AFW-to-local data transformation functions
- [x] 4.6 Create `src/lib/sync/sync-engine.ts` with main sync orchestration logic
- [x] 4.7 Implement incremental sync based on ChangedDate/ModifiedDate fields
- [x] 4.8 Implement upsert logic (insert new, update existing based on ams_*_id)
- [x] 4.9 Implement soft-delete handling (mark inactive if removed from AFW, never hard delete)
- [x] 4.10 Create SyncLog entries for each sync run (start, end, counts, errors)
- [x] 4.11 Implement retry logic with exponential backoff (3 attempts)
- [x] 4.12 Create `src/lib/sync/scheduler.ts` using node-cron for scheduled sync
- [x] 4.13 Read sync schedule from SyncConfig table (default 2 AM)
- [x] 4.14 Create `src/app/api/sync/route.ts` POST endpoint for manual sync trigger (Admin only)
- [x] 4.15 Create `src/app/api/sync/status/route.ts` GET endpoint for sync status
- [x] 4.16 Write unit tests for mappers and sync logic (mock AFW connection)
- [x] 5.0 Client Management Module
- [x] 5.1 Create `src/app/api/clients/route.ts` with GET (list with pagination, filtering) and search
- [x] 5.2 Implement client list filters: department, shape, personnel, search term
- [x] 5.3 Create `src/app/api/clients/[id]/route.ts` with GET (detail), PATCH (update custom fields)
- [x] 5.4 Create `src/app/api/clients/[id]/personnel/route.ts` for managing additional personnel
- [x] 5.5 Implement RBAC filtering (users see only assigned clients unless Manager/Admin)
- [x] 5.6 Create `src/components/clients/client-list.tsx` with data table, sorting, filtering
- [x] 5.7 Create `src/components/clients/client-card.tsx` for list item display with Shape color badge
- [x] 5.8 Create `src/app/(dashboard)/clients/page.tsx` client list page
- [x] 5.9 Create `src/app/(dashboard)/clients/[id]/page.tsx` client detail page
- [x] 5.10 Create `src/components/clients/client-detail.tsx` with tabs for policies, tasks, personnel
- [x] 5.11 Create `src/components/clients/shape-selector.tsx` dropdown with color swatches
- [x] 5.12 Create `src/components/clients/personnel-picker.tsx` searchable Entra user selector
- [x] 5.13 Implement audit logging for client modifications
- [x] 5.14 Create policies sub-section showing all client policies with days-until-renewal
- [x] 5.15 Write unit tests for client components and API routes
- [x] 6.0 Shape/Designation Management
- [x] 6.1 Create `src/app/api/shapes/route.ts` with GET (list) and POST (create) - Admin only
- [x] 6.2 Create `src/app/api/shapes/[id]/route.ts` with GET, PATCH (update), DELETE (soft delete/deactivate)
- [x] 6.3 Create `src/components/admin/shape-form.tsx` with fields: name, description, color picker, rules, display_order, is_active
- [x] 6.4 Create `src/components/admin/shape-list.tsx` with drag-and-drop reordering
- [x] 6.5 Create `src/app/(dashboard)/admin/shapes/page.tsx` Shape management page
- [x] 6.6 Implement color picker component for Shape color selection
- [x] 6.7 Add validation to prevent deleting Shapes that are in use (only deactivate)
- [x] 6.8 Design UI to be extensible for future designation types (abstract designation pattern)
- [x] 6.9 Write unit tests for Shape API and components
- [x] 7.0 Task Management & Templates
- [x] 7.1 Create `src/app/api/templates/route.ts` with GET (list by department) and POST (create) - Admin/Manager
- [x] 7.2 Create `src/app/api/templates/[id]/route.ts` with GET, PATCH, DELETE
- [x] 7.3 Create `src/components/admin/template-form.tsx` with fields: name, description, department, timing, days_offset, default_priority
- [x] 7.4 Create `src/app/(dashboard)/admin/templates/page.tsx` template management page grouped by department
- [x] 7.5 Create `src/app/api/tasks/route.ts` with GET (list with filters) and POST (create)
- [x] 7.6 Create `src/app/api/tasks/[id]/route.ts` with GET, PATCH (update status, reassign), DELETE
- [x] 7.7 Create `src/app/api/tasks/bulk/route.ts` for bulk status update and reassignment
- [x] 7.8 Implement task due_date calculation: policy.expiration_date + days_offset
- [x] 7.9 Create `src/components/tasks/status-select.tsx` with N/A option that shows notes modal
- [x] 7.10 Implement N/A status validation (require na_reason when status = NA)
- [x] 7.11 Implement CANCELLED status validation (require cancelled_reason)
- [x] 7.12 Create `src/components/tasks/task-list.tsx` with filtering, sorting, status badges
- [x] 7.13 Create `src/components/tasks/task-card.tsx` with priority indicator, due date, assignees
- [x] 7.14 Create `src/components/tasks/task-form.tsx` for create/edit with client/policy selection
- [x] 7.15 Create `src/app/(dashboard)/tasks/page.tsx` task list page
- [x] 7.16 Create `src/lib/tasks/auto-generate.ts` task auto-generation logic from templates
- [x] 7.17 Implement renewal window detection (configurable days before expiration, default 90)
- [x] 7.18 Implement duplicate prevention (check existing tasks for same policy/template)
- [x] 7.19 Auto-assign generated tasks to client's primary_personnel_id
- [x] 7.20 Create cron job or trigger for daily task auto-generation check
- [x] 7.21 Implement audit logging for task changes
- [x] 7.22 Write unit tests for task API, auto-generation, and components
- [x] 8.0 Dashboards & Reporting
- [x] 8.1 Create `src/components/dashboard/kpi-card.tsx` reusable KPI display component
- [x] 8.2 Create `src/components/dashboard/task-summary.tsx` showing overdue, due today, due this week, upcoming
- [x] 8.3 Create `src/components/dashboard/renewal-calendar.tsx` mini calendar showing upcoming renewals
- [x] 8.4 Create `src/app/api/dashboard/personal/route.ts` aggregating personal KPIs
- [x] 8.5 Create `src/app/(dashboard)/dashboard/page.tsx` personal dashboard with My Tasks, My Clients, Quick Stats
- [x] 8.6 Create `src/components/dashboard/workload-chart.tsx` bar chart for tasks per team member
- [x] 8.7 Create `src/components/dashboard/completion-chart.tsx` line chart for completion trends
- [x] 8.8 Create `src/components/dashboard/status-pie-chart.tsx` pie chart for task status distribution
- [x] 8.9 Create `src/app/api/dashboard/manager/route.ts` aggregating team KPIs
- [x] 8.10 Create `src/app/(dashboard)/manager/page.tsx` manager dashboard with team overview, department metrics
- [x] 8.11 Implement drill-down from aggregate metrics to individual user/task lists
- [x] 8.12 Create `src/components/admin/sync-status.tsx` widget showing last sync, status, row counts
- [x] 8.13 Create `src/app/api/dashboard/admin/route.ts` aggregating system health and cross-department metrics
- [x] 8.14 Create `src/app/(dashboard)/admin/page.tsx` admin dashboard with system health, sync status, user activity
- [x] 8.15 Implement dashboard data caching for <2 second load times
- [x] 8.16 Install charting library (recharts or chart.js) for visualizations
- [x] 8.17 Write unit tests for dashboard components and API routes
- [x] 9.0 Notifications System
- [x] 9.1 Create `src/app/api/notifications/route.ts` with GET (list user notifications) and PATCH (mark read)
- [x] 9.2 Create `src/app/api/notifications/[id]/route.ts` for individual notification actions
- [x] 9.3 Create Notification model entries for: task_assigned, task_overdue, task_completed, sync_failed
- [x] 9.4 Create `src/components/notifications/notification-bell.tsx` with unread count badge
- [x] 9.5 Create `src/components/notifications/notification-dropdown.tsx` showing recent notifications
- [x] 9.6 Create `src/components/notifications/notification-item.tsx` individual notification display
- [x] 9.7 Implement notification creation triggers (on task assignment, status change, overdue detection)
- [x] 9.8 Create daily job to generate overdue task notifications
- [x] 9.9 Create `src/app/api/notifications/preferences/route.ts` for user notification settings
- [x] 9.10 Create notification preferences UI in user settings
- [x] 9.11 Design notification system to support future Teams/Email channels (abstract notification sender)
- [x] 9.12 Write unit tests for notification components and API
- [x] 10.0 Admin Configuration & System Health
- [x] 10.1 Create `src/app/api/admin/sync-config/route.ts` GET and PATCH for sync settings
- [x] 10.2 Create `src/app/(dashboard)/admin/sync/page.tsx` with sync time picker, enable/disable toggle, manual trigger button
- [x] 10.3 Create `src/app/api/admin/sync-logs/route.ts` GET for sync history with pagination
- [x] 10.4 Display sync log history with status, duration, row counts, errors
- [x] 10.5 Create `src/app/api/admin/roles/route.ts` for Entra group-to-role mapping CRUD
- [x] 10.6 Create `src/app/(dashboard)/admin/users/page.tsx` showing users, their roles, last login
- [x] 10.7 Create UI for managing Entra Group → Role mappings
- [x] 10.8 Create `src/app/api/admin/audit-logs/route.ts` GET for audit log viewing
- [x] 10.9 Create audit log viewer with filtering by user, entity type, date range
- [x] 10.10 Implement audit log creation middleware/helper for sensitive operations
- [x] 10.11 Implement system health checks (DB connection, AFW connection, last sync status)
- [x] 10.12 Write unit tests for admin API routes and components