# Estimating Extension Design **Date:** 2026-03-13 **Related workbook:** `samples/CGIBreakdown_Template/Template_CGI-Breakdown+Calc_25Dez_V0.976_251212_beta_LCR-Update.xlsx` **Purpose:** Canonical design, field mapping, and implementation plan for a browser-based estimating system in Planarchy. ## Executive Summary The workbook is not a simple calculator. It is a full estimating and pricing system with: - project and commercial assumptions - scope breakdown for shots and assets - roster and rate lookups - phased effort and cost calculations - management summaries - downstream export sheets Planarchy can support this, but not by copying Excel cell logic into the browser. The right implementation is a dedicated estimating bounded context with: - a wizard for first-pass estimate creation - a workspace for iterative revisions - a typed calculation pipeline - live linkage to Planarchy resources and roles - immutable snapshots for auditability ## Design Principles ### 1. Do not emulate Excel The workbook contains very large formula surfaces, including roughly 823k formula cells in `CALC_AUX` alone. Rebuilding that as browser spreadsheet emulation would preserve the current maintenance problem instead of solving it. The replacement should be: - typed - stage-based - versioned - testable - explainable ### 2. Reuse the current platform where it already fits Useful existing Planarchy primitives: - `Resource` for roster, rates, skills, availability, and dynamic metadata - `Project` for schedule, budget, and project linkage - `Role` for assignment and capability alignment - blueprint-driven fields for temporary bridge data where first-class models do not yet exist ### 3. Keep estimating separate from operational staffing Estimating answers: - what work is assumed - what rates and policies apply - what cost, price, and margin result Operational planning answers: - who is actually assigned - when capacity is consumed - how delivery is staffed in reality `DemandRequirement` and `Assignment` are downstream execution data, not the primary estimating store. ## Product Shape ### Estimate Wizard The wizard should generate the first complete draft through structured steps: 1. Opportunity and project shell 2. Scope breakdown 3. Commercial assumptions 4. Staffing strategy 5. Rate and resource matching 6. Financial review 7. Export and approval ### Estimate Workspace After the wizard, the user should move into a workspace with tabs: - `Overview` - `Scope Breakdown` - `Assumptions` - `Rates & Resources` - `Staffing / Phasing` - `Financials` - `Exports` - `Version Compare` This replaces the giant spreadsheet with a clearer domain-oriented UI. ## Workbook Domains The analyzed workbook combines several distinct domains: - input and assumption sheets such as `ProjectInfo`, `Shots&Assets_Breakdown`, `ratesBreakdown`, and `Ressource Roster MASTER` - reference catalogs such as `ExperienceAdjust`, `Packages`, `IT Rate card`, `machine_rates`, `FX`, and `Rates ACN` - derived engine sheets such as `Calculation`, `CALC_AUX`, `4Dispo`, `SAP Phasing`, and `MMP Import` - management and reporting views such as `Overview_*`, `Cockpit`, `Analytics`, and `Per Year` That mix is exactly why the app needs separated models for assumptions, scope, demand, rates, snapshots, outputs, and exports. ## Proposed Domain Model ### New bounded context: `Estimating` | Model | Purpose | |---|---| | `Estimate` | Top-level estimate container tied to a project or opportunity | | `EstimateVersion` | Versioning, options, baselines, approvals, and locked commercial states | | `EstimateAssumption` | Structured commercial, tax, pricing, and scenario inputs | | `ScopeItem` | Scope rows imported or authored from the breakdown sheet | | `ScopeEffortRule` | Rules that turn scope into discipline effort | | `EstimateDemandLine` | Normalized effort lines with phasing and pricing attributes | | `RateCard` | Versioned pricing and cost catalog | | `RateCardLine` | Attribute-based rate resolution entries | | `ResourceCostSnapshot` | Immutable copy of roster/rate facts used by one estimate version | | `EstimateMetric` | Persisted derived totals for fast reads and auditability | | `EstimateExport` | Stored export artifacts and serializer metadata | ### Reuse strategy | Existing model | Reuse level | How it fits | |---|---|---| | `Project` | `Direct` | Parent linkage, timeline context, budget bridge | | `Resource` | `Direct` | Roster, chapter, role, LCR/UCR, skill and availability context | | `Role` | `Direct` | Demand-line role alignment and staffing suggestions | | `DemandRequirement` / `Assignment` | `Downstream` | Planning handoff target after estimate approval | | `dynamicFields` / blueprints | `Bridge only` | Short-term bridge for unmigrated metadata, not core estimate storage | ## Mapping Strategy ### Mapping legend - `Direct`: already maps to an existing first-class Planarchy field - `Bridge`: can be bridged short-term, but should move to estimating models - `Derived`: calculate it, do not persist it as manual source data - `New Model`: requires estimating schema ### Project and commercial inputs | Workbook field | Current target | Status | Recommended target | |---|---|---|---| | Project Name | `Project.name` | `Direct` | keep on `Project`, mirror into `Estimate.name` | | Opportunity ID | project dynamic field | `Bridge` | `Estimate.opportunityId` | | Timeframe From / To | `Project.startDate` / `Project.endDate` | `Direct` | default estimate context from project | | Currency | project/resource bridge only | `Bridge` | `Estimate.baseCurrency` | | Contract Owner / Business Unit / Service Group | none | `New Model` | `EstimateAssumption.*` | | Pricing Structure | partly `Project.orderType` | `Bridge` | `EstimateAssumption.pricingStructure` | | Revenue Timing / Recognition | none | `New Model` | `EstimateAssumption.*` | | Sales Tax / Billing Arrears / Payment Terms | none | `New Model` | `EstimateAssumption.*` | | Contingency / Capital Charge / Mgmt Fee policies | none | `New Model` | `EstimateAssumption.*` | ### Scope breakdown inputs | Workbook field | Current target | Status | Recommended target | |---|---|---|---| | Row sequence, type, package | none | `New Model` | `ScopeItem.sequenceNo`, `scopeType`, `packageCode` | | Description, scene, page, location | coarse project notes only | `New Model` | `ScopeItem.*` | | Assumptions / comments | none | `New Model` | `ScopeItem.assumptionCategory`, `internalComments` | | Resolution / FPS / aspect / shot length | project dynamic fields only | `Bridge` | `ScopeItem.technicalSpec` JSON | | Frame count / count / unit mode | limited bridge only | `Bridge` | `ScopeItem.frameCount`, `count`, `unitMode` | | Discipline effort columns | none | `New Model` | generated `EstimateDemandLine` rows | | Total costs on the breakdown sheet | none | `Derived` | `EstimateMetric` | ### Resource, rate, and lookup data | Workbook field | Current target | Status | Recommended target | |---|---|---|---| | Roster employee/name | `Resource.displayName` / `eid` | `Bridge` | link to `Resource` plus snapshot source text | | UCR / LCR | `Resource.ucrCents` / `lcrCents` | `Direct` | direct reuse plus snapshot | | FTE | indirect only | `Bridge` | `ResourceCostSnapshot.fte` | | Level / work type / area | dynamic fields only | `Bridge` | normalize later, snapshot now | | Location / country | dynamic bridge only | `Bridge` | snapshot + demand-line attributes | | Rates ACN / rate breakdown / machine / FX | none | `New Model` | `RateCard`, `RateCardLine`, FX/rule tables | | Experience adjustments | none | `New Model` | rate adjustment rules | ### Calculation, phasing, and exports | Workbook field group | Current target | Status | Recommended target | |---|---|---|---| | Calculation line items | none | `New Model` | `EstimateDemandLine` | | Named resource references | `Assignment.resourceId` via planning handoff | `Direct` | linked demand line + resource snapshot | | Dates, hours, bill code, org unit, economic profile | none | `New Model` | `EstimateDemandLine.*` | | Monthly spread | none | `New Model` | `EstimateDemandLine.monthlySpread` | | Weekly phasing (`4Dispo`) | none | `Derived` | generated projection view | | `CALC_AUX` transformed outputs | none | `Derived` | derived from demand lines and snapshots | | `MMP Import` / external export sheets | none | `New Model` | serializer output + `EstimateExport` | | Cockpit / analytics totals | none | `Derived` | persisted `EstimateMetric` rows | ## Browser Architecture ### Calculation engine Implement a typed calculation pipeline in `packages/engine`: 1. validate assumptions and scope 2. resolve effort rules into demand lines 3. resolve roster/rate snapshots 4. calculate phased costs, prices, and metrics 5. materialize outputs for UI and export This should be deterministic and test-first. Manual overrides must be explicit and traceable. ### Resource-connected behavior The browser system can stay dynamic and resource-connected if it uses two data modes at once: - live links to `Resource` and `Role` for current matching and suggestion UX - immutable snapshots on `EstimateVersion` for pricing, auditability, and approval history That prevents old approved estimates from changing when roster rates or metadata are edited later. ## Implementation Plan ### Phase 1. Schema and contracts - add `Estimate`, `EstimateVersion`, `EstimateAssumption`, `ScopeItem`, `EstimateDemandLine`, `RateCard`, `RateCardLine`, `ResourceCostSnapshot`, `EstimateMetric`, and `EstimateExport` - define DTOs and use cases in `packages/application` - create engine contracts and test fixtures ### Phase 2. Wizard and workspace - build the estimate wizard - add estimate workspace routes and tabs - support import from workbook-derived source data where useful ### Phase 3. Calculation and pricing - implement rule engine for scope-to-effort conversion - add rate resolution and cost/price calculations - persist metrics and audit trail ### Phase 4. Resource linkage and planning handoff - connect demand lines to resources, roles, and availability - add staffing suggestions from current Planarchy data - support conversion from approved estimate demand into downstream planning entities ### Phase 5. Exports and approvals - generate external export formats - add version compare, lock, approval, and audit views ## Current Status This is no longer design-only. Implemented baseline in the current codebase: - estimating Prisma schema and enums - shared estimate types and validation schemas - engine-level summary metric helper - application-layer estimate creation and retrieval use-cases - estimate API router registration - estimates list route and first estimate creation wizard - estimate workspace detail route with overview, assumptions, scope, staffing, versions, and exports tabs - working-draft editor for overview, assumptions, scope, and staffing - version submit, approve, and locked revision-cloning actions - export artifact scaffolding with stored serializer metadata records - format-specific export generation with stored payloads for JSON, CSV, XLSX, SAP, and MMP - live resource-linked staffing rows that can sync current Planarchy rates and persist estimate-version snapshots - explicit live-vs-manual rate mode metadata on demand lines, with server-side recalculation before metrics are persisted - read-only and draft workspace visibility for manual overrides versus live resource snapshots - project snapshot persistence on estimate versions - approved-version planning handoff into downstream `DemandRequirement` and `Assignment` records, with estimate lineage metadata - scope import from XLSX in the estimate wizard - financials tab in the estimate workspace with summary cards, cost-to-price bridge, chapter breakdown, and monthly phasing - rate cards with per-client association and client filter in the admin UI Still open: - estimate templates and cloning for recurring project types - richer version comparison (side-by-side diff of demand lines and metrics) - approval email notifications - scope-to-effort rule engine (currently manual demand lines only) - rate adjustment rules and experience multipliers ## Planning Handoff Model The demand/assignment persistence split is complete. The legacy `Allocation` table has been dropped. ### Current behavior Approved estimate versions hand off like this: 1. one `DemandRequirement` is created per normalized estimate demand line 2. if a linked resource is valid, an `Assignment` is created linked to that demand 3. if no valid resource is available, the demand stays open with the suggested resource stored in metadata 4. estimate provenance is preserved on both records through `estimateHandoff` metadata ### Estimate-to-planning mapping | Estimate source | DemandRequirement target | Assignment target | Notes | |---|---|---|---| | `Estimate.projectId` + approved version | `projectId` | `projectId` | direct | | `EstimateDemandLine.id` | `metadata.estimateHandoff.estimateDemandLineId` | same | provenance | | `EstimateDemandLine.name` | `role` or demand title | copied display metadata | readable context | | `EstimateDemandLine.roleId` | `roleId` | optional copied roleId | direct when present | | `EstimateDemandLine.resourceId` | `metadata.suggestedResourceId` when open | `resourceId` when assigned | demand vs assignment split eliminates nullable-resource ambiguity | | `EstimateDemandLine.hours` + project window | `hoursPerDay`, `percentage`, `headcount` | `hoursPerDay`, `percentage` | reused derivation logic | | `EstimateDemandLine.fte` | `headcount` | not needed | demand owns quantity | | rate and price totals | metadata snapshot | metadata snapshot | preserve auditability | | staffing attributes / monthly spread | metadata | metadata | direct carry-over | The workbook mapping is feasible. The estimating product covers wizard creation, workspace editing, version management, export generation, and planning handoff. Remaining work focuses on templates, richer comparison, and the scope-to-effort rule engine.