Skip to content

Purchase Orders

A Purchase Order (PO) is a commitment to a vendor for a specific Resource on a specific Lot at a specific price.

At a glance

  • POs are the highest-volume table in the system — 2,432,418 rows on Test (2026-06-02).
  • Each PO traces back to one EstimateActivity row (only Type='y' activities ever generate POs).
  • Lifecycle: estimate runs → PO generated → BC creates a real PO → trade sees it in Trade Portal → builder approves → BC turns it into an approved bill → BC pays → payment syncs back.
  • “No-dollar” POs (Lot.AllowNoDollarPOs) get a PO number so the work shows up in the schedule but never become bills.
  • Set Lot.RecalcPO = 1 to regenerate POs on the next pass — the standard fix when an option or vendor bid changed late.

The first six steps happen automatically when a lot is set up for production. Each step is essentially a row showing up in a different table.

1Lot ratifies → Estimate runs.
2PO Generate reads EstimateActivity + active VendorBid rows.
3PO rows are inserted into PurchaseOrder with one row per resource per lot.
4TransmissionPOGenerate queues an outbound message to Business Central.
5BC Worker processes the queue every 5 minutes; on success, BC’s PO number is written back.
6Trade sees the PO in the Trade Portal (order.aspx, quick-view.aspx).

The remaining steps happen as the build progresses — builder approves work, vendor uploads waiver, BC pays, variance posts if amounts differ.

7Builder approves the work in the Builder Portal (WorkApproval.aspxspProcessPaymentReview).
8TransmissionPOApprove queues the approval; BC turns the PO into an approved bill.
9Vendor uploads lien waiver in the Trade Portal.
10BC pays the vendor; payment status syncs back via TransmissionPaymentStatus.
11Variance if the actual differs from the PO — see Variances.

The PO subsystem is PurchaseOrder in the middle, surrounded by lookup views, transmission queues, and audit logs.

Full PO table reference
TableWhat
PurchaseOrderHeaders and lines.
vwLookupPONumberPO number lookup.
UnpaidPurchaseOrder, vwUnpaidPurchaseOrderOpen POs (not yet billed/paid).
vwLoadWorkPOProcessUsed during PO generation.
TransmissionPOGenerate, TransmissionPOApprove, TransmissionPOCancelOutbound queues to Business Central.
vwTransmissionPurchaseOrderErrorPOs that failed to transmit.
BuilderPortalWorkOrderApprovalLogAudit log of every Builder Portal approval.
vwGroupRecalcPOUsed when bulk-recalculating POs.
PermanentOrderLogHistory of permanent-order overrides.

Some POs are issued for activities that have no monetary commitment (e.g. internal QA visits) — controlled by Lot.AllowNoDollarPOs. These still get a PO number so the work appears in the Trade Portal schedule but never become bills.

AppWhere
SMARTProject Management → PO Management
SMART 2.0production/, accounting/
Builder PortalPurchaseOrders.aspx, WorkOrders.aspx, WorkApproval.aspx
Trade Portalorder.aspx, quick-view.aspx, viewPOfromSchedule.aspx, work-orders.aspx, work-order-search.aspx
Open POs for a project, by trade
SELECT v.VendorName, COUNT(*) AS OpenPOs, SUM(po.Amount) AS OpenAmount
FROM dbo.PurchaseOrder po
JOIN dbo.Vendor v ON v.VendorID = po.VendorID
WHERE po.ProjectID = @ProjectID
AND po.Status IN ('O','A') -- Open / Approved
GROUP BY v.VendorName
ORDER BY OpenAmount DESC;