109 lines
6.4 KiB
Markdown
109 lines
6.4 KiB
Markdown
# 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.
|