Docs/Procurement

Procurement

BOM-shortfall driven quotes, vendor selection, grouped POs, and delivery -> inventory credit

Last updated: 2026-05-27

Procurement in S3Suite starts from a real production need - a lot in manufacturing that has a BOM-line shortfall - and walks you through the smallest workflow that gets parts ordered and credited: collect quotes from up to three vendors, pick a winner per line, group winning lines into one PO per vendor, mark delivered when parts arrive. Delivery automatically credits the inventory pool.

There is no separate "Procurement project" or RFP system. Procurement is anchored to a lot and only surfaces parts whose required quantity for that lot exceeds current inventory.


Why anchor procurement to a lot

A generic "let's buy some parts" flow drifts into a mini-ERP. Anchoring to a lot keeps it answering one question: what does this lot need that we do not have?

  • The procurement plan is computed from (BOM quantity x lot units) - inventory on hand
  • Only lines with shortfall > 0 appear
  • The result is a focused worklist, not a parts catalog
  • When the PO arrives, the credit lands in the same inventory pool any future lot will draw from
If you need parts that no lot is calling for, use a manual inventory adjustment instead.

Concepts

TermWhat it means
Procurement planThe per-lot shortfall list: BOM line + required qty + current inventory + shortage.
QuoteA single vendor's price + lead time for one BOM line on one lot. Max 3 quotes per line.
WinnerThe selected quote for a line. Only one winner per line.
Purchase Order (PO)A grouped order, one per vendor, with one or more winning lines.
PO statusissued -> partial -> delivered, or cancelled.
Per-line CASMark-delivered writes per-line atomically; concurrent operators get a 409 instead of double-crediting.

Quick start (5 minutes)

1. Open the procurement plan for a lot

  1. Open the project: Projects -> your project -> Manufacturing -> Production Variants
  2. Open the variant, then the lot that needs parts
  3. Click Procurement in the lot view
  4. The shortfall plan loads. Each row is a BOM line needing parts.

2. Add quotes (up to 3 per line)

  1. On a shortfall row, click Add quote
  2. Fill in vendor name, unit price, currency, lead time (days), and an optional note
  3. Save. The quote appears under the line.
  4. Repeat for up to 3 vendors per line.

3. Pick a winner

  1. Compare quotes by price + lead time + your sourcing notes
  2. Click Mark winner on the chosen quote
  3. The other quotes for that line stay visible but are flagged as not selected

4. Create grouped POs

  1. Once every required line has a winner, click Create POs
  2. The system groups winning lines by vendor and creates one PO per vendor
  3. Each PO gets a generated PO number (PO-YYYYMMDD-NNN)
  4. POs land under Procurement -> Purchase Orders for the project

5. Mark delivered when parts arrive

  1. Open the PO detail page
  2. For each line, enter the received quantity (can be partial or full)
  3. Click Mark delivered for that line
  4. Per line: the receivedQty advances atomically (Compare-And-Set), an inventory ledger row is written with source po-delivered, and the PO's overall status auto-rolls between partial and delivered
Tip: Partial deliveries are first-class. Receive 80 of 100 today, the remaining 20 next week; each receipt writes its own ledger row.

Workflow: cancelling a PO

A vendor missed delivery, or a lot got scrapped.

  1. Open the PO detail page
  2. Click Cancel PO
  3. Enter a reason (required)
  4. Confirm
The PO status flips to cancelled. Any lines already partially received stay credited (you have those parts in hand); no further deliveries can be recorded against this PO.

Workflow: re-quoting after a winner is wrong

You picked the winner, then realized vendor A is on backorder.

  1. Go back to the procurement plan
  2. On the line, click Unselect winner (or Mark winner on a different quote)
  3. The line returns to "needs winner". The PO that was about to include this line is not yet created until you click Create POs again.
If a PO is already created with this line, you must cancel the PO first, then re-quote.

Reference

Concurrency safety

  • Mark-delivered uses per-line CAS. Each line's receivedQty is updated with a $elemMatch: { bomItemIndex, receivedQty: snapshotBefore } predicate. If another operator wrote first, the update misses and the API returns 409 CONCURRENT_UPDATE telling the user to refresh.
  • Inventory credits fire only on successful CAS. Double-receive of the same line never double-credits inventory.
  • PO number generation retries up to 5 times on duplicate-key collisions, so two operators creating POs at the same date will not blow up.

Project scoping

  • Every quote / PO / line operation filters by (organizationId, projectId, lotId). Project A users cannot operate on Project B's lots even within the same org.

Permissions

  • Read: any authenticated org member with project access
  • Quote / Winner / Create PO / Mark delivered / Cancel: project writer roles
  • All mutations write audit log rows (action prefixes procurement_quote_, procurement_po_)

Module gate

  • Procurement is gated by the massProduction module. Enable it in Project settings -> Suites if the lot view does not show a Procurement tab.

Common pitfalls

  • "Plan is empty even though we need parts." The plan only surfaces lines where (BOM qty x lot units) - inventory > 0. If inventory was over-counted, the shortfall is hidden. Recount stock; the plan will refresh.
  • "Cannot mark delivered." Some other operator already advanced this line. Refresh the PO page to see the current receivedQty.
  • "Created PO grouped lines from the wrong vendors." PO grouping uses the winning quote's vendor for each line. Re-select winners on the procurement plan to re-group.
  • "Currency mismatch in a single PO." Each line carries its own currency from the winning quote. Mixed-currency POs are allowed but flagged in the UI; convert at receipt time if needed.

Related docs