The Finished Goods Receipt Note (FGRN) is the document that formally moves a completed production batch from work-in-progress into finished-goods inventory. Once the operator's tally is CONFIRMED and the QC inspector has stamped a PASS verdict, the storeman receives the pallets, the supervisor releases them, and finance authorises the cost roll-up. Posting the FGRN closes the production order in production_batches.status = 'COMPLETED' and creates a PROD_IN inventory transaction against the FG warehouse for each FG line.
This document mirrors Sage X3 "Manufacturing Receipt", Syspro "Job Receipt", SAP S/4HANA "Goods Receipt for Production Order" (MIGO 101 with mvt 101) and NetSuite "Work Order Completion". It is the document that turns RM cost + labour cost + machine cost into a finished-goods unit-cost on the GL.
Without an FGRN posted, no FG is visible in the v_warehouse_value view, no stock can be picked for dispatch, and no Sales Order can move to COMPLETE. Like the GRN, this is a blocking step — this time for the order-to-cash flow.
COMPLETED status — tally CONFIRMED + QC PASS.QUARANTINE warehouse, not the FG-MAIN aisle.The FgrnDoc spec (frontend/js/erp-templates/fgrn-doc.js) is built from the completed batch + tally sheet + FG inventory snapshot. Each row below is wired to a real column.
| Field on document | API endpoint | DB table.column | Example value |
|---|---|---|---|
| FGRN Ref No. | generated client-side · buildRef() | (stamped on print) | FGRN-2026-0481 |
| Receipt date | auto-stamped on complete | production_batches.completed_at | 2026-05-08 |
| Production order ref | derived from batch | production_batches.batch_ref | BATCH-2026-0481 |
| Batch ref | same source | production_batches.batch_ref | BATCH-2026-0481 |
| Tally ref | FK from upstream | tally_sheets.tally_ref WHERE batch_id matches | TALLY-260508-4218 |
| FG product code & name | GET /api/products | products.code & products.name | A4_72PG_FM · A4 72-page FM |
| UoM | master data | products.code → FG items.uom | EA / REAM |
| Lot / serial | derived | production_batches.batch_ref as lot | LOT-BATCH-2026-0481 |
| Planned qty | preserved | production_batches.planned_qty | 5 000 |
| Actual qty | posted on complete | production_batches.actual_qty (= tally_sheets.net_qty) | 4 940 |
| Yield % | computed | production_batches.yield_pct | 98.80 |
| Wastage qty | computed | (planned − actual) | 60 |
| Wastage % | computed | production_batches.wastage_pct | 1.20 |
| Scrap qty (from tally) | denormalised | tally_sheets.scrap_total | 40 |
| Unit cost | master data | items.std_cost for the FG item | R 8.4500 |
| Line value | computed | actual_qty × std_cost | R 41 743.00 |
| FG warehouse / bin | GET /api/warehouses?type=FG | warehouses.code + warehouse_locations.bin_code | FG-MAIN / FG-A1 |
| BOM consumption recap · std cost | derived | SUM(bom_lines.qty_per_unit × items.std_cost) × planned_qty | R 23 100.00 |
| BOM consumption recap · actual cost | derived from issues | SUM(inventory_transactions.qty × unit_cost) WHERE reference_type='production_batch' | R 23 380.00 |
| Cost variance % | derived | ((actual − std) / std) × 100 | +1.21 |
| QC verdict | captured manually | passed via tally_sheets.notes / batch fields | PASS / FAIL / REWORK |
| QC inspector | captured | cross-ref to employees.clock_no | QC-1101 |
| Storeman receiving | req.user | users.email via FK | fg-store@palmstat.co.za |
| Inventory posting | POST /api/inventory/transactions | inventory_transactions.txn_type='PROD_IN' | +4 940 EA into FG-MAIN |
CONFIRMED and the QC inspector has signed the Job Card checklist.POST /api/production-batches/:id/complete with actual_qty = tally_sheets.net_qty. The endpoint:
PROD_IN inventory transaction for the FG into the configured FG warehouse.yield_pct = actual / planned × 100, wastage_pct = (planned − actual) / planned × 100.completed_at = NOW() and flips status to COMPLETED.Print FGRN. Frontend calls FgrnDoc.build(batch, tally, fgInventory).print().barcode_scans row for traceability.v_warehouse_value view now reflects the new FG units & rand value. Sales Orders pegged to this FG can pick from the new stock.production + inventory realtime channels signal: WIP Tracking removes the batch tile, Finished Goods view adds it, dashboard counters tick over.POST /api/documents with kind=OTHER; document_links ties it to entity_type='production_batch'. Retained 7 years.| Action | Admin | Storeman / Warehouse | Supervisor | Finance | Operator |
|---|---|---|---|---|---|
| Generate this doc | ✓ | ✓ | ✓ | ✓ | – |
| Complete the batch (POST ·/complete) | ✓ | – | ✓ | – | – |
| Sign storeman line | ✓ | ✓ | – | – | – |
| Sign supervisor release | ✓ | – | ✓ | – | – |
| Authorise finance line | ✓ | – | – | ✓ | – |
| Reprint after archive | ✓ | ✓ | ✓ | ✓ | ✓ |
| Email externally | ✓ | ✓ | – | ✓ | – |
| Reverse / void (after post) | ✓ (with audit reason) | – | – | – | – |
Permission gate enforced by requireRole('admin','planner','supervisor') on POST /api/production-batches/:id/complete. Reversal requires admin role & audit reason.
Happy path: 4 940 units posted, yield 98.8%, BOM cost variance +1.2% (within tolerance). Storeman, supervisor, finance all sign within 4 hours. FG visible in v_warehouse_value, ready for dispatch.
Happy path: 200 units fail QC inspection (visual defect). FGRN is posted with two lines: 4 740 to FG-MAIN (verdict PASS), 200 to FG-QUARANTINE (verdict REWORK). Status reflects the split. Reworked stock either re-receives or is scrapped within 30 days.
Sad path: All 4 940 posted to FG-MAIN as PASS, defect noticed only after dispatch. Recovery: customer return, reverse FGRN line, post SCRAP txn, root-cause investigation.
Happy path: One BOM produces 2 000 of A4 + 1 500 of A5 from the same paper reel. FGRN carries 2 lines, each with its own qty, lot, unit cost, destination bin. The FGRN total reconciles to the planned BOM yield.
Happy path: Actual RM cost runs 7% over standard because supplier glue lot was off-spec and required higher dosage. Finance investigates, accepts the variance as a one-time event, signs. The variance is captured for next-month BOM review.
Sad path: Variance signed off without investigation. Trend obscured. Recovery: variance KPI dashboard auto-flags, monthly review forces back-investigation.
inventory_transactions rows of type PROD_INfg_stock_snapshots for month-end FG valuation
| Stage | Target | Owner | Escalation |
|---|---|---|---|
| Tally CONFIRMED → FGRN print | 15 min | Supervisor | Production Manager |
| Storeman receive & sign | 30 min after pallets land | FG Storeman | Warehouse Manager |
| Supervisor release | 30 min after storeman sign | Supervisor | Production Manager |
| Finance authorise | 24h | Finance Controller | CFO if cost variance > +5% |
| Reverse / void | Admin only · with audit reason | Admin | Operations Director sign-off |
actual_qty / planned_qty × 100. The "how much we made vs how much we said we'd make" KPI.(planned − actual) / planned × 100. Inverse of yield + scrap.