Bill of Quantities (BOQ)¶
The BOQ is the structured spec for what a project will deliver: every item the client is paying for, broken down into sections and line items, with quantities and rates. From there it drives the rest of the project lifecycle — procurement, allocation, delivery, installation, returns, invoicing, and close-out.
Accessing BOQ¶
- Go to Projects → [Project Name].
- Click the BOQ tab in the project detail page.
A project may have multiple BOQ versions. The version selector at the top of the BOQ page shows the active version; older versions are marked Archived.
BOQ statuses¶
| Status | What it means |
|---|---|
| Draft | Being prepared. Items can be added, edited, deleted. |
| Pending Approval | Submitted to the approval workflow. Edits are blocked while in this state. |
| Approved | All approval levels passed. The BOQ is automatically locked at this point — edits and deletes require an admin to unlock first. |
| Locked | Same as approved with an explicit lock applied. No edits allowed. |
| Completed | Terminal positive state. Reached only after every item is fully invoiced or returned, every linked PO is closed, and any retention has been released. |
| Archived | A prior version superseded by a newer revision. |
Tabs¶
The BOQ page is organised into the following tabs:
| Tab | Purpose |
|---|---|
| Tree | Hierarchical view of sections and items. Add / edit / move / approve / promote to inventory from the row dropdown. |
| List | Flat tabular view across all items, with bulk selection and an action bar (e.g. create QC checklist from selected items). |
| Analytics | Cost breakdown, variance, and progress charts. Visible only to users with cost-visibility permission. |
| Allocation | Per-item view of required vs. reserved vs. available stock. Allocate, top up, or release reservations. |
| Delivery | Delivery Challans (DCs) and Site Returns (SRs) tied to this BOQ. |
| Installation | Material Issues (MIs) recording on-site consumption. |
| Invoices | Billable summary, issued invoices, retention status, generate-invoice action. |
| Change Requests | Internal revisions / additions / deletions / rate changes raised against the BOQ. |
| History | Chronological audit trail of all lifecycle events — submission, approval, lock, dispatch, install, return, invoice, completion. |
| Compare | Diff two versions of the BOQ. |
A BOQ-level Approval Card appears above the tabs while status is Draft or Pending Approval. A Completion Card appears once the BOQ is Approved, Locked, or Completed.
Building the BOQ¶
Sections¶
Sections group items hierarchically (A, A.1, A.1.1, …). Add sections from
the Tree tab. Each section has a code and a name; nested sections are
supported.
Items¶
Each line item carries:
- Item number (e.g.
A.1.5) and a description. - Quantity + unit (bag, m², m³, nos, etc.).
- Unit rate (which can be split into material / labor / equipment rates).
- Wastage % to derive the adjusted quantity used for downstream caps.
- Source type — how the item was added (see below).
- Optional inventory link to a catalog SKU.
Source type¶
Each item carries a source-type badge:
| Source | Behaviour |
|---|---|
| Inventory | Item was picked from the inventory catalog. Inventory link is set; downstream PO / DC flows can reference the SKU directly. |
| Custom (ad-hoc) | Free-text item not yet in the catalog. Shown with an amber "Ad-hoc" hint in the item picker. Promoted to the inventory catalog when a PO or reservation is raised, or manually via Promote to Inventory in the row dropdown. |
| Template | Imported from a BOQ template. |
| BOM | Sourced from a Bill of Materials. |
| Import | Loaded from an external file. |
| Change Request | Added via an approved change request. |
Ad-hoc items can be used freely in a draft BOQ. Promotion to the inventory
catalog assigns them a SKU (ADHOC-{boq_number}-{item_number} by default,
auto-disambiguated on collision) and links the BOQ item to the new inventory
row with quantity_available = 0.
Inventory item picker¶
When adding an item, the picker searches the inventory catalog as you type. If your search matches a catalog row, selecting it links the BOQ item to that SKU. If you type free text that doesn't match anything, an "Ad-hoc — not in catalog" hint appears below the input; the item is saved as a custom entry and promoted later.
Versioning¶
Once a BOQ is approved (or otherwise locked), creating a new revision via the
version selector copies all sections and items into a new draft version with
version + 1. The prior version is marked Archived.
Each item in the new revision keeps a stable lineage link back to its parent in the prior revision, so the Compare tab can pair items even when they're renumbered or reordered between revisions.
Compare tab¶
Pick any two versions in the dropdowns. The diff shows:
- Items added in the target.
- Items removed from the target.
- Items modified (description, quantity, rate, etc., grouped by field).
- Items unchanged.
- Cost impact summary at the top.
Toggle Group by Section to cluster changes per section, or flatten the list. Toggle Show / Hide Unchanged to focus on changes only.
Approval¶
Approval is workflow-driven. Each tenant has a default BOQ approval workflow seeded out of the box; admins can configure additional ones in Settings → Workflow Engine → Approval Workflows. Workflows can have multiple levels and condition-based routing (e.g. "BOQs over ₹500,000 also need director approval").
Submitting¶
While the BOQ is in Draft:
- Open the Approval Card that appears above the tabs.
- Optionally add notes for approvers.
- Click Submit for Approval.
- The BOQ flips to Pending Approval and routes to level 1 of the matched workflow.
You cannot submit an empty BOQ — the system requires at least one item.
Approving / Rejecting¶
When the BOQ is at your approval level:
- The Approval Card shows a level-by-level progress stepper.
- You'll also see it in the global Approvals queue (
/approvals). - Approve advances to the next level (or finalises if you're the last level). Reject sends the BOQ back to Draft with the reason recorded.
A user cannot approve a BOQ they created or submitted.
Auto-lock on final approval¶
When the final level approves, the BOQ is automatically locked:
is_locked = true,locked_at = now,locked_by = approver.- Item-level edit / delete / move actions are disabled in the UI.
- Section management is disabled.
To make changes after approval, an admin must unlock the BOQ from the actions menu (or raise a Change Request — see below).
Approval workflow page¶
Settings → Workflow Engine → Approval Workflows lets admins:
- Create new workflows scoped to
entity_type = "boq". - Add levels (each tied to a role).
- Add condition rules so that high-value BOQs route through extra levels.
Change Requests¶
Once approved, structural changes go through Change Requests:
- Addition — add a new item.
- Modification — change description, quantity, rate, etc.
- Deletion — remove an item.
- Rate Change — bulk rate update (often produced by Refresh Rates; see below).
Each CR goes through draft → submitted → approved → implemented; on implementation, the underlying BOQ items are mutated.
Rate management¶
Refreshing rates from inventory¶
For projects whose execution lags behind the BOQ — and inventory unit_cost has drifted — use Refresh Rates in the BOQ header (visible on approved BOQs):
- Click Refresh Rates.
- The dialog shows every linked item with
current_rate → proposed_rate, variance percentage, and per-line cost impact. - Pre-checked rows are those with a non-zero variance. Adjust the selection if needed.
- Click Create Rate-Change CR.
- A
rate_changeChange Request is drafted; submit it from the Change Requests tab. Once approved + implemented, the BOQ rates are updated.
Inventory price changes are tracked in an audit table (inventory_price_history)
that records every unit_cost / selling_price change with source (created,
manual, import, etc.).
Escalation index¶
A BOQ can carry an optional escalation index percentage (e.g. 8.5 for
+8.5%). When set, the Refresh Rates preview applies it on top of the
current inventory cost — useful for contracts with index-linked clauses.
Rate freeze¶
When a refresh CR is created, the BOQ's rate_frozen_at timestamp is stamped.
This is informational; the actual rate-flip happens when the CR is approved
and implemented.
Allocation (reservation)¶
The Allocation tab is the materials desk's view: per-item required vs. reserved vs. available, with a shortfall column.
Reserving stock¶
For each item linked to inventory:
- Click Allocate to reserve up to the BOQ item's required quantity.
- If part of the requirement was already reserved, the button reads Top Up.
- If you ask for more than is available, the system partial-reserves up to free stock and reports the shortfall — it never fails outright as long as some stock is free.
Reserving moves quantity from quantity_available to quantity_reserved on
the inventory row; both columns are updated atomically under a row-level
lock so concurrent reservers can't double-allocate the same stock.
Releasing (unallocating)¶
Click Details on a row to see the reservations it holds. Each active
reservation has a Release button. Releasing returns the quantity to
quantity_available.
Reservation lifecycle¶
| Status | Meaning |
|---|---|
| Active | Stock is held aside; counts toward quantity_reserved. |
| Released | Manually unallocated; quantity restored. |
| Consumed | Drained by a Delivery Challan dispatch (the reservation has been used up). |
| Expired | Auto-released by the cron sweep when the optional expires_at passes. |
Reservations on a BOQ's items are auto-released when the BOQ is Completed.
Procurement (Purchase Requisitions)¶
The materials desk consolidates buy lists across projects via Purchase Requisitions.
Generating a Requisition from a BOQ¶
On an approved BOQ, click Generate Requisition in the BOQ header. The
system snapshots every item with a shortfall (adjusted_quantity −
quantity_ordered > 0) into a new draft PR:
- The PR is project-scoped (linked to this BOQ).
- Each PR line links back to its BOQ item.
- The PR starts in Draft state.
The Purchase Requisitions page¶
Procurement → Purchase Requisitions lists all PRs:
- Filter by project (or leave it unset to see the full tenant-wide buy list).
- Filter by status (
Draft,Pending Approval,Approved,Partially Ordered,Ordered,Cancelled). - Click into any PR for line detail.
PR lifecycle¶
| Status | Meaning |
|---|---|
| Draft | Being filled in. |
| Pending Approval | Submitted to the PR approval workflow. |
| Approved | Ready for conversion to PO(s). |
| Partially Ordered | Some lines have been turned into POs; others remain. |
| Ordered | All lines fully sourced. |
| Cancelled | Abandoned. |
A default PR approval workflow is seeded per tenant (one level → project manager). Admins can configure more in the same Approval Workflows page.
Convert to PO¶
From an approved (or partially-ordered) PR, the Create PO per Vendor action lets you select a vendor + a subset of lines and convert them to a purchase order:
- Multiple POs per PR are supported (run convert-to-PO once per vendor).
- Ad-hoc BOQ lines auto-promote to the inventory catalog at this point so the resulting PO carries an inventory link.
BOQItem.quantity_orderedis incremented atomically for every line.- The PR's per-line
quantity_orderedis also incremented; the PR status flips to Partially Ordered or Ordered based on remaining qty.
Direct PO from BOQ¶
For quick-buys that don't need the full PR cycle, Generate PO from BOQ
remains available — it bypasses the PR layer and creates a PO directly. The
BOQ-side quantity_ordered writeback still happens.
Delivery (Delivery Challans)¶
Physical shipments from inventory to the project site are recorded as Delivery Challans on the Delivery tab.
Creating a DC¶
- Click New Delivery Challan.
- Pick items + quantities from the dialog (only items with remaining deliverable qty are shown).
- Optionally enter vehicle no, driver, notes.
- Click Create Draft DC.
The DC is created in Draft; inventory is not yet mutated.
Dispatch caps¶
When you create a DC, two caps are validated:
- Against the BOQ total:
this_dc_qty + already_delivered − already_returned ≤ adjusted_quantity. - Against inventory headroom:
this_dc_qty ≤ free_available + reservation_held_for_this_BOQ_item.
If either fails, the line is rejected up-front so you don't have to find out at dispatch time.
Dispatching¶
From the DC list, click Dispatch on a draft. The system:
- Drains the BOQ item's reservation first (oldest reservation, partial consumption allowed) before touching free stock.
- Decrements
quantity_reservedandquantity_availableaccordingly. - Increments
BOQItem.quantity_delivered. - Writes a stock-movement ledger entry (
type=out,reference_type=delivery_challan). - Writes a BOQ progress audit row.
Dispatch runs under a row-level lock per inventory item to keep concurrent DCs safe. If a line's combined reservation + available is insufficient, the whole dispatch transaction rolls back — partial dispatches don't sneak through.
Receiving¶
Once the truck arrives at site, click Mark Received on a dispatched DC. This is the site acknowledgement step:
- Optional signature URL and photo URLs (uploaded via the standard presigned-URL flow).
- Optional notes appended to the DC.
- DC status flips to Received.
There are no further inventory side effects — that all happened at dispatch.
Cancelling¶
Only Draft DCs can be cancelled. Once dispatched, use a Site Return to reverse the inventory side.
Installation (Material Issues)¶
A Material Issue records on-site consumption of already-delivered stock. It
drives BOQItem.quantity_installed but has no inventory side-effect —
the stock left inventory at delivery.
Recording an installation¶
From the Installation tab:
- Click Record Installation.
- Pick items + quantities. The dialog only shows items with positive
"headroom" (
delivered − returned − installed > 0). - Optionally pick a section / task to attribute the install to.
- Click Issue.
The MI is created and immediately issued — no separate review step. The
system increments quantity_installed and writes a BOQProgress(installed)
audit row.
Cap¶
new_installed_total + already_installed ≤ delivered − returned (i.e. you
can only install what's actually on site and not been returned).
Cancelling an issued MI¶
Issued MIs can be cancelled — quantity_installed is decremented by the
cancelled quantity, and a reversal audit row is written.
Site Returns¶
Stock coming back from a project site is recorded as a Site Return on the Delivery tab.
Per-line condition¶
Each line on an SR carries a condition:
| Condition | Behaviour on receive |
|---|---|
| Usable | Quantity restocked into quantity_available; BOQItem.quantity_returned incremented. |
| Defective | No inventory side-effect; quantity_returned still incremented (so the cap math stays consistent). |
| Scrap | Same as defective — terminal write-off. |
Cap¶
SR_qty ≤ delivered − already_returned − installed — you cannot return what
is installed or already returned.
Lifecycle¶
- Draft — line items entered with their conditions.
- Received — terminal positive state. Usable lines have run through
restock, all lines have bumped
quantity_returned, audit rows written. - Cancelled — only valid from Draft.
Invoicing¶
The Invoices tab drives client billing.
Billable summary¶
Top of the tab shows the BOQ-level monetary summary: invoiceable now, invoiced to date, paid, outstanding, credit notes, net billed.
The per-item table shows:
| Column | Meaning |
|---|---|
| Required | adjusted_quantity (the contractual amount). |
| Invoiced | quantity_invoiced to date. |
| Billable now | Required − Invoiced. Zero means fully billed. |
| Rate | The unit rate. |
| Billable value | Billable now × Rate. |
Generate Invoice¶
Click Generate Invoice to draft a milestone invoice. Default behaviour:
- Pre-selects all items with
Billable now > 0, qty defaulting to remaining. - Cap enforced:
qty_invoiced + this_invoice_qty ≤ adjusted_quantityper item. The qty cap is unit-based; credit notes do not unlock additional quantity. - Creates an
Invoice+ line items. - Writes back
BOQItem.quantity_invoiced.
Retention / holdback¶
If the BOQ has retention_percent set (typical 5–10% for construction
contracts), every invoice generated against it holds back that percentage of
the pre-tax subtotal:
retention_amount = subtotal × retention_percent / 100.- The invoice's
amount_dueis reduced by the retention amount (the client is billed net of retention). retention_held_to_datesnapshots the cumulative still-held value at issue time.
A retention banner appears at the top of the Invoices tab whenever
retention_percent > 0 or any retention is currently held. It shows the
percentage, the amount currently held, and the configured release terms (free
text on the BOQ).
Releasing retention¶
When contractual conditions are met (practical completion, defects-liability expiry, etc.), click Release Retention:
- Optionally enter a partial amount (leaves blank = release everything held).
- Optionally add notes.
- Click Release.
A "release invoice" is drafted with a positive total_amount and a
negative retention_amount so the running sum gives the current still-held
value naturally. Issuing this invoice bills the client for the released
portion.
Credit notes¶
Credit notes (created from the standard Invoice module) are netted at the
invoice level (monetary). They reduce total_outstanding_value and
net_billed_value in the summary but do not unlock additional invoiceable
quantity on the BOQ — the qty cap stays Required − Invoiced.
Completion¶
A BOQ reaches Completed when:
- Every item is accounted for:
invoiced + returned ≥ adjusted_quantity(within a 0.01 tolerance for decimal drift). - All linked POs are closed: status is
receivedorcancelled. - Retention is released or zero: the running sum of
Invoice.retention_amountis at most 0.01.
The Completion Card above the tabs reports readiness:
- Not Yet Completable — lists each blocker with a description.
- Ready to Complete — shows a green button that, on a two-click confirm, flips the BOQ to Completed.
On completion:
- Status →
Completed,completed_atandcompleted_bystamped. - Any active reservations on linked items are auto-released so they don't sit forever.
- The BOQ stays locked.
Reopening¶
Admins can reopen a Completed BOQ from the same Completion Card. Status goes
back to Approved and completed_* are cleared. This is for accounting
corrections (e.g. issuing a credit note + new invoice for already-released
retention) and should not be used routinely.
History¶
The History tab shows a chronological audit trail. Events captured include:
- BOQ submitted / approved / rejected / locked.
- Change request created / approved / implemented.
- Delivery Challan dispatched / received / cancelled.
- Material Issue issued / cancelled.
- Site Return received.
- Purchase Requisition converted to PO.
- BOQ status changes (including completion).
Each entry shows actor, timestamp, and a descriptive note.
Permissions¶
| Permission | Grants |
|---|---|
boq.read |
View BOQs and their tabs. |
boq.create |
Create new BOQs and items. |
boq.update |
Edit BOQs (only while not locked). |
boq.delete |
Delete BOQs and items. |
boq.approve |
Approve / reject BOQs and Change Requests. |
boq.reserve |
Reserve / release inventory for BOQ items. |
boq.dispatch |
Create / dispatch / cancel DCs and MIs. |
boq.return |
Create / receive / cancel Site Returns. |
boq.invoice |
Generate invoices and release retention. |
boq.complete |
Mark BOQ complete; reopen completed BOQs. |
purchase_requisition.read / .create / .update / .approve |
Purchase Requisition lifecycle. |
Default role grants out of the box:
| Role | BOQ permissions |
|---|---|
| Admin / Super Admin | All |
| Project Manager | All |
| Store Supervisor | read, reserve, dispatch, return; PR read/create/update |
| Accountant | read, invoice, complete; PR read |
| Site Engineer | read; PR read |
Approval alerts¶
When BOQs need your attention:
- Home Dashboard — A red Pending Approvals card appears.
- Projects Dashboard — Replaces the Budget Utilization card when approvals are pending.
- Project Detail — A red alert banner shows below the quick stats bar.
- All alerts link to the Approvals page.