# Analysis: Dealer Claim & Unified Request Architecture This document analyzes the current architecture and proposes an efficient approach to unify Dealer Claims and Custom Requests while supporting specialized data capture and versioning. ## Current State Both **Custom Requests** and **Dealer Claims** are already "unified" at the base level: - **Primary Collection**: `workflow_requests` stores the core data (id, requestNumber, initiator, status, currentLevel). - **Secondary Collection**: `dealer_claims` stores the business-specific metadata (proposal, expenses, invoices, etc.) and is linked via `requestId`. This architecture naturally supports showing both in the same list. ## Proposed Efficient Approach To make these two paths truly "inline" and handle specialized steps efficiently, we recommend a **Metadata-Driven Activity System**. ### 1. Unified Listing The UI should continue to use the existing `listWorkflows` endpoints. The backend already returns `templateType`, which the frontend can use to decide which icon or detail view to render. ### 2. Specialized Step Identification (Dual-Tag System) To handle dynamic level shifts and accurately recognize the purpose of each step, we use two categories of tags on each `ApprovalLevel`. #### Category A: Action Tags (`stepAction`) Defines **what** special behavior is required in this step. - `DEALER_PROPOSAL`: Show proposal submission form. - `EXPENSE_CAPTURE`: Show expense document upload form. - `PROPOSAL_EVALUATION`: Show evaluation tools for the initiator/manager. - `NONE`: Standard approve/reject UI. #### Category B: Persona Tags (`stepPersona`) Defines **who** is acting in this step (role-based logic). - `INITIATOR`: Used when the initiator acts as an approver (e.g., evaluating a dealer proposal). - `DEPARTMENT_LEAD`: Standard leadership approval. - `ADDITIONAL_APPROVER`: Distinguishes steps added manually from the template. #### How it works together: | Level | Level Name | `stepAction` | `stepPersona` | UI Behavior | | :--- | :--- | :--- | :--- | :--- | | **1** | Dealer Proposal | `DEALER_PROPOSAL` | `DEALER` | Full Proposal Form | | **2** | Initiator Review | `PROPOSAL_EVALUATION` | `INITIATOR` | Inline evaluation checklist | | **3** | Lead Approval | `NONE` | `DEPARTMENT_LEAD` | Simple Approve/Reject | | **3b** | Extra Check | `NONE` | `ADDITIONAL_APPROVER` | Manual Approval UI | - **Dynamic Insertions**: If `Extra Check` is added, the following levels shift, but their `stepAction` tags remain, so the UI NEVER breaks. - **Resubmission**: Rejection logic targets the latest completed level with `stepAction: 'DEALER_PROPOSAL'`. ### 3. Versioning & Iterations The user's requirement to track previous proposals during resubmission is handled via the **Snapshotted Revisions** pattern: - **The Main Store**: `DealerClaim.proposal` and `DealerClaim.completion` always hold the **active/latest** values. - **The Revision Store**: `DealerClaim.revisions[]` acts as an append-only audit trail. **Resubmission Flow:** 1. Request is rejected at Level 2/3/5. 2. Workflow moves back to Level 1 or 4 (Dealer). 3. Dealer edits the data. 4. **On Submit**: - Backend takes the *current* `proposal` or `completion` data. - Pushes it into `revisions` with a timestamp and `triggeredBy: 'SYSTEM_VERSION_SNAPSHOT'`. - Overwrites the main object with the *new* data. - Advances the workflow. ### 4. KPI & Deep Filtering Strategy (Hybrid Approach) To support complex KPIs and high-performance filtering across thousands of requests, we use a **Referential Flat Pattern**: - **Workflow Index (Speed)**: `WorkflowRequest` remains light. It handles high-frequency queries like "My Pending Tasks" or "Recent Activity". - **Business Index (Depth)**: `DealerClaim` holds the "Deep Data". We apply Mongoose/MongoDB indexes on fields like: - `dealer.region`, `dealer.state` (for Geospatial/Regional KPIs). - `budgetTracking.utilizedBudget` (for Financial KPIs). - `completion.expenses.category` (for operational analysis). **The "Hybrid" Advantage:** 1. **Performance**: We don't bloat the main `workflow_requests` collection with hundreds of dealer-specific fields. This keeps "Total Request" counts and general listing extremely fast. 2. **Scalability**: For deep filters (e.g., "Show all claims in South Region with expenses > 50k"), we query the `dealer_claims` collection first to get the `requestId`s, then fetch the workflow status. This is much faster than a massive `$lookup` on a single bloated collection. 3. **Clean KPIs**: KPIs like "Budget vs Actual" are calculated directly from `DealerClaim` without interfering with generic workflow TAT metrics. ### 5. Ad-Hoc & Additional Approver Handling When a user manually adds an approver (Ad-hoc) to a Dealer Claim or Custom Flow: - **Tag Assignment**: The new level is automatically tagged with `stepAction: 'NONE'` and `stepPersona: 'ADDITIONAL_APPROVER'`. - **UI Consistency**: The frontend sees `stepAction: 'NONE'` and renders the standard approval interface (comments + buttons). - **Rejection Intelligence**: - If an *Additional Approver* rejects, the system looks back for the nearest **anchor step** (e.g., `stepAction: 'DEALER_PROPOSAL'`). - This prevents the workflow from getting "stuck" between two manually added levels if the business rule requires a return to the initiator or dealer. ### 6. Impact on Custom Flows & Compatibility **Zero Breaking Changes**: - Existing Custom Flows will default to `stepAction: 'NONE'`. The UI behavior remains identical to the current state. - The `WorkflowRequest` collection structure is not being modified; we are only adding two optional metadata fields to the `ApprovalLevel` sub-documents. **Future-Proofing**: - Custom Flows can now "unlock" specialized steps (like `PROPOSAL_EVALUATION`) simply by updating their template metadata, without any backend code changes. ### 7. Implementation Strategy | Feature | Custom Request Path | Dealer Claim Path | | :--- | :--- | :--- | | **Listing** | Unified `listWorkflows` | Unified `listWorkflows` | | **Details View** | Standard UI | Enhanced UI (tabs for Expenses/Proposal) | | **Logic** | Generic `approveRequest` | `approveRequest` + `DealerClaimService` hook | | **Versioning** | Activity Logs only | Snapshotted Revisions for re-submissions | --- ### Key Advantage This approach avoids creating "two separate systems". It treats a Dealer Claim as a "Custom Request with a specific metadata payload". The UI remains cohesive, and the backend logic for TAT, notifications, and status transitions stays shared.