# Implementation Plan: Request Update to Quote Auto-Recalculation

This plan establishes a dual-execution pure calculation engine that synchronizes **Request updates** with linked **Quotations** headlessly in the backend without requiring UI interaction, while keeping real-time interactive calculations 100% client-side in the frontend (preventing chatty API calls on discount/value changes).

---

## 1. System Overview & Realtime Schema Values

### Current Flow vs Target Architecture

```mermaid
sequenceDiagram
    autonumber
    participant UI as Frontend Quote / Request UI
    participant RS as Request Service (Backend)
    participant CE as Quote Calculation Engine
    participant QS as Quotation Service (Backend)
    participant DB as MongoDB Database

    Note over UI,CE: Flow 1: Interactive Frontend Quote Creation (0ms Latency)
    UI->>CE: Local in-memory calculation on every keystroke (mathjs)
    UI->>QS: Save Quote with Commercial Snapshot (summaryType, discount, tax, deposit)
    QS->>DB: Persist Quotation & CostBreakdowns

    Note over RS,DB: Flow 2: Headless Request Update (No UI Interaction)
    UI->>RS: PUT /api/v2/request/updaterequest/:requestId (Area/Products/Labor changed)
    RS->>DB: Update Request document
    RS->>QS: Trigger syncLinkedQuotations(updatedRequest)
    QS->>DB: Find active/draft Quotation for requestId
    QS->>CE: Recalculate costBreakdowns, subTotal, tax, discount & totals using Quote's saved commercial rules
    QS->>DB: Save updated Quotation & sync Invoice deposit if applicable
    RS-->>UI: Return updated Request & sync summary
```

---

### Real-Time Database Schemas Involved

#### 1. `RequestSchema` (`models/MVP@2/request-model.js`)
* **`requestId`**: Unique identifier (e.g., `R_0001`).
* **`selectedService[]`**:
  * `serviceId`: ObjectId referencing `Service`.
  * `unitType`: `"area"` | `"quantity"` | `"time"` | `"none"`.
  * `areaInputType`: `"dimension"` | `"manual"`.
  * `length`, `width`, `area`, `units`: Dimensional measurements.
  * `marginType`: `"percentage"` | `"amount"`.
  * `marginValue`: Number.
  * `selectedProductOptions[]`:
    * `productId`: String.
    * `productData`: Object (contains price, name, etc.).
    * `fields`: Map/Object of formula parameters (e.g. `{ "area": "500", "depth": "3" }`).
  * `selectedEquipment[]`:
    * `equipmentId`: String / ObjectId.
    * `equipmentData`: Object (cost, rate, hours, quantity).
  * `selectedLabor[]`:
    * `laborId`: ObjectId.
    * `laborData`: Object (payment/rate, hours, quantity).
  * `siteVisitStatus`: `"Completed"` | `"Scheduled"` | `"InProgress"` | `"NoSiteVisit"` | `"NotScheduled"`.

#### 2. `QuotationSchema` (`models/EvergreenQuotation/EverGreenQuotation.js`)
* **`requestId`**: String linking to Request.
* **`quotationNumber`**: String (e.g., `Q_0001`).
* **`status`**: `"drafted"` | `"waiting for approval"` | `"created"` | `"accepted"` | `"inProgress"` | `"completed"`.
* **Commercial Policy Rules**:
  * `IsBaseprice`: Boolean (`true` = Base Price Summary, `false` = Actual Total Summary).
  * `discountType`: `"percentage"` | `"amount"`.
  * `discountAmount`: Number.
  * `excludeTax`: Boolean (`true` = tax exempt / excluded, `false` = standard tax).
  * `depositType`: `"percentage"` | `"amount"`.
  * `depositPercentage`: Number.
  * `requiredDeposit`: Number.
  * `miscellaneousCosts[]`: `[{ service: ObjectId, cost: Number, remarks: String }]`.
* **Dynamic Totals**:
  * `subTotal`, `actualSubTotal`: Number.
  * `taxAmount`, `actualTaxAmount`: Number.
  * `total`, `actualTotal`: Number.
  * `costBreakdowns[]`: Array of `costBreakdownSchema` with per-service products, labor, equipment, and margin rollups.

---

## 2. User Review Required

> [!IMPORTANT]
> **Zero Keystroke API Calls Maintained**
> In the frontend (`useNewQuotation.tsx` and `NewQuotationPage.tsx`), all real-time calculations on discount changes, tax toggles, and radio selections remain **100% local in-memory execution** via `mathjs`. No API requests will be triggered on input typing or discount adjustment.

> [!WARNING]
> **Quotation State Locking Policy on Request Update**
> When a Request is updated:
> 1. **Draft/Pending Quotes** (`drafted`, `created`, `waiting for approval`): Will be **automatically recalculated and saved**.
> 2. **Approved Quotes** (`accepted`, `completed`): Will **NOT** be automatically altered to protect legal/billing contract integrity; instead, an audit record will log that the underlying Request changed.

---

## 3. Proposed Changes

### Component 1: Shared Pure Calculation Engine

#### [NEW] [`quoteCalculationEngine.js`](file:///c:/thriveni/folder%20f/POS/EGF_POS/evergreen_pos_be/src/utils/quoteCalculationEngine.js)
A pure mathematical calculation module in Node.js (utilizing `mathjs`) that mirrors the frontend logic:
- `calculateProductQuantityAndCost(service, productOption, productCatalog)`: Evaluates formula using `mathjs` against fields (e.g. `(area * depth) / 324`).
- `calculateResourceCosts(service, laborMap, assetMap)`: Calculates labor and equipment totals.
- `getServiceMarginAmount(service, subtotal)`: Computes percentage or flat amount margin.
- `calculateQuotationFromRequest(request, existingQuotation, catalogData)`:
  - Computes `basePriceSubtotal` and `actualTotalSubtotal`.
  - Determines active subtotal based on `existingQuotation.IsBaseprice`.
  - Applies `discountType` and `discount` rate.
  - Applies `taxPercentage` (or $0$ if `excludeTax === true`).
  - Computes `finalTotal`, `requiredDeposit`, and updates `costBreakdowns[]`.

---

### Component 2: Backend Request & Quotation Services

#### [MODIFY] [`request.service.js`](file:///c:/thriveni/folder%20f/POS/EGF_POS/evergreen_pos_be/src/services/nursery/request.service.js)
- In `exports.updateRequest`:
  - After `Request.findByIdAndUpdate` saves the updated request, add a hook call to `quotationService.syncQuotationsForRequest(dbName, updatedRequest, id)`.
  - Ensures changes to area, dimensions, selected products, labor, and equipment immediately cascade to linked non-finalized quotations.

#### [MODIFY] [`quotation.service.js`](file:///c:/thriveni/folder%20f/POS/EGF_POS/evergreen_pos_be/src/services/quotation.service.js)
- Implement `exports.syncQuotationsForRequest(dbName, requestDoc, userId)`:
  - Finds all non-finalized quotations where `requestId === requestDoc.requestId` and `isDeleted !== true`.
  - Resolves required Service, Product, Asset, and Labor catalogs for the new service items.
  - Calls `calculateQuotationFromRequest(...)`.
  - Writes new totals (`subTotal`, `taxAmount`, `total`, `actualTotal`, `costBreakdowns`) to the quotation.
  - Appends an audit entry in `actionHistory` stating: `"Quotation automatically recalculated due to Request update"`.
  - If linked invoice exists (`invoiceId`), calls `persistInvoiceWithDepositSync`.

---

### Component 3: Frontend Quotation Persistence & Local Engine Alignment

#### [MODIFY] [`NewQuotationPage.tsx`](file:///c:/thriveni/folder%20f/POS/EGF_POS/evergreen_pos_fe/src/pages/Quotes/createQuote/NewQuotationPage.tsx)
- Ensure the payload sent to `/Quotation/create-quotation` or `/Quotation/update-quotation` explicitly saves the full commercial snapshot:
  - `IsBaseprice: summaryType === 'basePrice'`
  - `discountType`: `"percentage"` | `"amount"`
  - `discount`: numeric value
  - `excludeTax`: boolean
  - `depositType`: `"percentage"` | `"amount"`
  - `depositPercentage`: numeric value
  - `miscellaneousCosts`: array of service misc items
- Keep the in-memory `mathjs` calculation reactive in React state with zero latency.

---

## 4. Verification Plan

### Automated / Manual Verification
1. **Formula & Calculation Verification**:
   - Create a Request with Service unit `area = 500 sqft`, Product with formula `(area * depth) / 324` with `depth = 3`.
   - Create a Quote with 10% discount and 8% tax.
2. **Headless Request Update Test**:
   - Update the Request area from `500` to `1000 sqft` via `PUT /api/v2/request/updaterequest/:requestId`.
   - Fetch the Quotation via `GET /api/v1/Quotation/getQuotationById/:id` without touching the UI.
   - Verify that:
     - Product quantity doubled in `costBreakdowns[0].products[0].quantity`.
     - `subTotal`, `discountAmount`, `taxAmount`, and `total` are accurately updated.
     - `actionHistory` contains the automatic recalculation entry.
3. **Frontend UI Interaction Test**:
   - Open the Quote creation page and type discount values (`1`, `5`, `10`, `15`).
   - Monitor Network DevTools tab: Ensure **0 network API requests** are fired while typing.
