Ashtech Stoneworks – Odidor ERP Implementation
Live implementation tracker and specification for the Estimation Module and subsequent phases
Odidor has been selected as the ERP platform for Ashtech Stoneworks. This page serves as the main communication interface between Ashtech, Odidor, and Xappert (implementation partner).
For Ashtech
Overview
Client-friendly summary of the Odidor ERP implementation
Problem
Ashtech Stoneworks currently relies on complex, manually-maintained Excel files to estimate multi-unit stone fabrication and installation projects.
This creates several challenges:
- Time-consuming to update for each new project.
- High risk of formula errors or broken links.
- Difficult for new staff to learn.
- No direct integration with CRM, Procurement, or Project delivery.
Solution
The Odidor Estimation Module transforms this manual process into a structured, ERP-native workflow.
Key Capabilities
- Centralized project setup (unit mix + amenities).
- Smart catalog of materials, labour rates, edges, and sinks.
- Automated SQFT, wastage, and cost calculations.
- Reusable templates for standard kitchen and vanity packages.
- Approval workflow and professional, branded client quotes.
- Integration with CRM (Opportunities & Quotes) and future modules.
Benefits for Ashtech
Faster Estimates
- From hours of spreadsheet work → minutes in Odidor.
- Templates let estimators reuse common configurations across projects.
Fewer Errors
- Formulas live in a controlled calculation engine, not scattered across cells.
- Role-based approvals ensure review before quotes go out.
Better Visibility
- Clear breakdown of:
- Material cost.
- Labour cost.
- Edges, sinks, and extras.
- Consistent pricing standards across all projects.
Integration-Ready
- Estimates will feed:
- Future procurement planning (slabs, sinks, accessories).
- Future production and job scheduling.
How It Fits in the Overall ERP
The Estimation Module is the front door of the operational workflow:
Detailed Implementation Plan (Phase 1 & 2)
- Ashtech Stoneworks – ERP Implementation Tracker (Phase 1 & 2 Focus)
Project Window: 18 Nov 2025 → 12 Jan 2026
Platforms: Odidor ERP (recommended)
Overall Goal: CRM + Estimation + Procurement + Inventory fully functional by Jan 12
PHASE 1 — CRM + Sales + Estimation
Timeline: Nov 18 → Dec 22 (5 weeks)
Goal: Fully functional CRM pipeline, quotation flow, estimation workflow, material + labour logic
Week 1 (Nov 18–24) – Project Kickoff & Business Requirements
Deliverables:
- Kickoff meeting + scope confirmation
Finalize detailed workflows for:
-
Lead → Opportunity → Quotation
-
Estimation inputs (material, labour, wastage, markup, commission)
-
Map Ashtech’s existing Excel (estimation) → Odidor fields
Data structures:
-
Customer master fields
-
Product categories (Slabs, Quartz, Granite, Services)
-
Installation service line items
-
Prepare import templates for CRM + Products
Technical setup:
-
Odidor environment provisioning
-
User roles / permissions defined
-
Access provisioning
Week 2 (Nov 25–Dec 1) – CRM Pipeline Build
Deliverables:
Configure CRM stages:
-
New Lead → Qualified → On-Site → Estimation → Review → Won/Lost
-
Lead capture forms + assignment rules
-
Customer master creation (fields, tags, segmentation)
-
Setup communication logs & meeting notes
Import:
-
Sample customers
-
Sample leads
-
Demo + Adjustments round 1
Week 3 (Dec 2–Dec 8) – Quotation + Estimation Engine (Core)
Deliverables:
Build quotation template:
-
Header + job site details
-
Material selection
-
Edge types, sink cutouts, extras
-
Fabrication labour
-
Installation labour
Configure estimation logic:
-
Slab cost per sqft
-
Wastage factor rule
-
Fabrication labour multiplier
-
Installation labour tiers
-
Optional add-ons logic
-
Tax rules (GST/PST)
-
Price list setup + overrides
Week 4 (Dec 9–Dec 15) – Approval Workflow + Document Templates
Deliverables:
Set up approval flow:
- Estimator → Manager → Final Quote
Build document templates:
-
Quotation PDF
-
Work Order (Export for Factory)
-
Customer Approval document
-
Add automated email dispatch
-
Add notifications & reminders
-
Demo + Adjustments round 2
Week 5 (Dec 16–Dec 22) – Phase 1 UAT + Go-Live
Deliverables:
-
Full UAT with Ashtech
-
Fixes + polish
-
Staff training (CRM + Estimation)
Create:
-
Quick reference guide
-
Training videos (short clips optional)
-
Phase 1 Go-Live → Dec 22
PHASE 2 — Procurement + Inventory
Timeline: Dec 23 → Jan 12 (3 weeks)
Goal: Purchase orders, supplier workflows, slab & stock tracking, factory receiving, job-site allocation
Week 6 (Dec 23–Dec 29) – Procurement Framework
Deliverables:
- Vendor master creation
Purchase workflow:
- Requisition → PO → Receipt → Bill
Configure cost centres for:
-
Factory
-
Job sites
Setup product variants:
-
2cm / 3cm slabs
-
Colours
-
Finishes
-
Link estimation → procurement items
Week 7 (Dec 30–Jan 5) – Inventory + Factory Logistics
Deliverables:
- Warehouse/factory location setup
Map physical movements:
-
Supplier → Factory
-
Factory → Job site
Slab tracking model:
-
Batch/Lot
-
Dimensions
-
Remnant logic (optional)
-
Create receiving workflow
-
Create stock availability reports
-
Alerts for low stock / reserved slabs
Week 8 (Jan 6–Jan 12) – Phase 2 UAT + Go-Live
Deliverables:
-
Procurement + Inventory UAT
-
Fixes + improvements
-
Staff training
-
Factory team workflow onboarding
-
Phase 2 Go-Live → Jan 12
For Odidor Engineering
Architecture
System architecture and data flow diagrams
Context & Goals
Ashtech Stoneworks currently uses complex Excel workbooks to estimate multi-unit stone projects.
The Odidor Estimation Module replaces this with a structured ERP-native engine.
Goals:
- Consistent calculations
- Versioning + approvals
- Project/unit/amenity configuration
- CRM integration
- Future feed into Procurement & Projects
High-Level Architecture
Core Backend Services
Project Service
- CRUD projects
- Manage unit types + amenities
Estimation Service
- Manage estimate headers & versions
- Handle status transitions
- Coordinate calculation + CRM sync
Estimation Line Service
- CRUD estimate lines
- Supports unit-based + amenity-based logic
Calculation Engine
- Stateless computation engine
- Applies core formulas for SQFT, wastage, material, labour, edges, sinks
- Writes totals back to DB
PDF Service
- Generates branded client quote
- Based on HTML template
CRM Integration Service
- Updates opportunity status:
- Approved → Quoted
- Accepted → Won
Data Layer
Main tables:
projectsunit_typesamenitiesmaterialslabour_ratesedge_profilessink_typesestimatesestimate_lines
Estimate lines store snapshots of pricing + wastage.
Data Flow & Sequence
Integration Points
CRM
- Estimate status drives Opportunity stage.
Procurement (Future)
- Aggregate required slab SQFT & sink/accessory counts.
Projects & Field Service (Future)
- Accepted estimates become:
- Job records
- Baseline budgets
Design Considerations
- Calculation engine must be idempotent and consistent.
- Store rate snapshots on each line.
- Handle large projects (100+ unit types, 500+ lines).
- Clear audit logs for approvals and rate overrides.
Project Timeline
Timeline & Project Tracker
Phase 1 (CRM + Estimation) and Phase 2 (Procurement + Inventory) delivery schedule
Note: This timeline tracks Phase 1 (CRM + Estimation) and Phase 2 (Procurement + Inventory), aligned to Ashtech's required dates (Phase 1 ~ Dec 22, Phase 2 ~ Jan 12).
| Week | Dates | Milestone |
|---|---|---|
| 1 | Nov 18 – Nov 24 | Project & requirements finalization |
| 2 | Nov 25 – Dec 1 | Data model & master data configuration |
| 3 | Dec 2 – Dec 8 | Estimation engine backend + basic UI |
| 4 | Dec 9 – Dec 15 | Templates, unit/amenity logic, and calculations |
| 5 | Dec 16 – Dec 22 | Approvals, PDF quotes, internal testing |
| 6 | Dec 23 – Dec 29 | UAT prep + Veritas-style project replication |
| 7 | Dec 30 – Jan 5 | UAT with Ashtech, fixes, refinements |
| 8 | Jan 6 – Jan 12 | Training, documentation, sign-off |
Detailed Breakdown
For Ashtech & Odidor
Requirements
Functional, non-functional, and validation requirements for Phase 1
Goals
The Estimation Builder UI should enable estimators to:
- Configure projects (unit mix + amenities).
- Build and edit estimation lines quickly.
- See totals update in real time.
- Move estimates through approvals confidently.
Screen Overview
2.1 Project Detail Screen
Tabs:
Layout & Sections
Content loading...
For Odidor Engineering
Technical Details
Database schema, APIs, and calculation engine specifications
Overview
The Estimation Module is a subdomain with the following main aggregates:
ProjectUnitTypeAmenityEstimateEstimateLine- Reference data:
Material,LabourRate,EdgeProfile,SinkType,WastageRule.
All endpoints should be namespaced, e.g., /api/estimation/... or /api/projects/... per Odidor conventions.
Data Model
2.1 Project
| Field | Type | Notes | |----------------|----------|-------------------------------------| | id | UUID | Primary key | | name | string | Project name | | client_id | UUID | FK to Customer | | address | string | Optional | | estimator_id | UUID | FK to User | | status | enum | draft, active, completed, archived | | crm_opportunity_id | UUID | Optional link | | created_at | datetime | | | updated_at | datetime | |
2.2 UnitType
| Field | Type | Notes | |--------------|--------|--------------------------------| | id | UUID | PK | | project_id | UUID | FK → Project | | label | string | e.g., "A1" | | description | string | Optional | | count | int | Number of such units | | avg_area_sqft| float | Optional, informational only |
2.3 Amenity
| Field | Type | Notes | |--------------------|--------|-----------------------| | id | UUID | PK | | project_id | UUID | FK → Project | | name | string | e.g., "Lobby" | | area_sqft | float | Required | | material_profile_id| UUID | Optional FK |
2.4 Material
| Field | Type | Notes | |---------------|--------|------------------------------| | id | UUID | PK | | name | string | | | category | string | quartz, granite, porcelain… | | thickness_mm | float | | | rate_sqft | float | Default price per sqft | | wastage_pct | float | Default | | uom | enum | sqft, lf, ea | | active | bool | |
2.5 LabourRate
| Field | Type | Notes | |---------|--------|----------------------------| | id | UUID | PK | | name | string | | | rate | float | | | uom | enum | sqft, lf, ea, day | | category| string | install, fabrication, etc. | | active | bool | |
2.6 Estimate
| Field | Type | Notes | |--------------------|----------|----------------------------------------| | id | UUID | PK | | project_id | UUID | FK → Project | | version_no | int | Starts at 1 | | status | enum | draft, in_review, approved, sent, accepted, rejected, cancelled | | valid_until | date | Optional | | discount_pct | float | Optional | | total_material_cost| float | Calculated | | total_labour_cost | float | Calculated | | total_extra_cost | float | Calculated (edges + sinks + extras) | | total_before_tax | float | Calculated | | tax_amount | float | Calculated | | grand_total | float | Calculated | | created_by | UUID | FK → User | | approved_by | UUID | FK → User, nullable | | created_at | datetime | | | updated_at | datetime | |
2.7 EstimateLine
| Field | Type | Notes | |-----------------|----------|--------------------------------------------| | id | UUID | PK | | estimate_id | UUID | FK → Estimate | | line_type | string | kitchen, island, vanity, amenity, edge… | | category | string | kitchen, vanity, amenity, other | | unit_type_id | UUID | FK → UnitType, nullable | | amenity_id | UUID | FK → Amenity, nullable | | description | string | | | quantity_units | float | e.g., number of units | | length | float | | | width | float | | | area_sqft | float | stored or recalculated | | wastage_pct | float | per-line override | | material_id | UUID | FK → Material | | material_rate | float | snapshot of rate | | labour_rate_id | UUID | FK → LabourRate | | labour_rate | float | snapshot | | edge_profile_id | UUID | FK → EdgeProfile, nullable | | edge_lf | float | linear feet | | edge_rate | float | snapshot | | sink_type_id | UUID | FK → SinkType, nullable | | sink_count | float | | | sink_rate_total | float | snapshot combined rate per sink | | extra_cost | float | manual extras | | material_cost | float | calculated | | labour_cost | float | calculated | | edge_cost | float | calculated | | sink_cost | float | calculated | | line_total | float | calculated | | source | string | manual/template/imported |
API Design
Suggest RESTish JSON APIs. Examples:
3.1 Project APIs
POST /api/projectsGET /api/projects/:idPATCH /api/projects/:id
3.2 Unit Types / Amenities
POST /api/projects/:projectId/unit-typesPATCH /api/unit-types/:idPOST /api/projects/:projectId/amenities
3.3 Estimate APIs
POST /api/projects/:projectId/estimatesGET /api/estimates/:idPOST /api/estimates/:id/version– clone estimate and increment version_noPATCH /api/estimates/:id/status
3.4 Estimate Lines APIs
POST /api/estimates/:estimateId/linesPATCH /api/estimate-lines/:idDELETE /api/estimate-lines/:id
3.5 Calculation API
POST /api/estimates/:id/recalculate- Triggers full recompute of all lines and header totals.
Calculation Engine
Pseudo-logic:
function recalculateEstimate(estimateId: string) {
const estimate = loadEstimate(estimateId);
const lines = loadEstimateLines(estimateId);
let totalMaterial = 0;
let totalLabour = 0;
let totalEdge = 0;
let totalSink = 0;
let totalExtra = 0;
for (const line of lines) {
const quantity = line.quantity_units ?? 1;
const areaSqft = line.length * line.width;
const netSqft = areaSqft * quantity;
const wastageSqft = netSqft * (line.wastage_pct / 100);
const totalSqft = netSqft + wastageSqft;
const materialCost = totalSqft * line.material_rate;
const labourCost = totalSqft * line.labour_rate;
const edgeCost = (line.edge_lf ?? 0) * (line.edge_rate ?? 0);
const sinkCost = (line.sink_count ?? 0) * (line.sink_rate_total ?? 0);
const extraCost = line.extra_cost ?? 0;
const lineTotal = materialCost + labourCost + edgeCost + sinkCost + extraCost;
// accumulate
totalMaterial += materialCost;
totalLabour += labourCost;
totalEdge += edgeCost;
totalSink += sinkCost;
totalExtra += extraCost;
// update line
updateLine(line.id, {
area_sqft: areaSqft,
material_cost: materialCost,
labour_cost: labourCost,
edge_cost: edgeCost,
sink_cost: sinkCost,
line_total: lineTotal,
});
}
const totalBeforeTax = totalMaterial + totalLabour + totalEdge + totalSink + totalExtra;
const taxAmount = computeTax(totalBeforeTax, estimate);
const grandTotal = totalBeforeTax + taxAmount;
updateEstimate(estimateId, {
total_material_cost: totalMaterial,
total_labour_cost: totalLabour,
total_extra_cost: totalEdge + totalSink + totalExtra,
total_before_tax: totalBeforeTax,
tax_amount: taxAmount,
grand_total: grandTotal,
});
}
Status & Workflow Logic
State machine:
draft → in_review → approved → sent → accepted/rejected
in_review → draft (rejected back)
On approved:
Lock estimate lines from editing.
Snap totals for reference.
On accepted:
Trigger integration event:
estimate.accepted → used by CRM and, in future, Projects/Procurement.
PDF & Templates
Templating engine: HTML-based (Handlebars, etc.).
Data needed:
Project header.
Estimate header.
Grouped lines by category.
Single endpoint:
GET /api/estimates/:id/pdf
Validation & Error Handling
Business rules enforced at API layer:
No transition to in_review if:
No lines present.
Required fields missing.
No negative numeric values.
Unit-based lines must have unit_type_id.
Amenity-based lines must have amenity_id.
Return structured errors:
code, message, field (if applicable).
Payment & Engagement
Ready to Proceed?
Once you've reviewed the proposal, choose a phase and purchase implementation hours via Stripe. You can start with Phase 1 and add more hours as we go.
Once you've reviewed the proposal, choose a phase and purchase implementation hours via Stripe.
You can start with Phase 1 and add more hours as we go.