PalmStat ERP · Operations
Palm Stationery Manufacturers (Pty) Ltd · Cape Town
12 Industria Crescent, Epping 2, Cape Town, 7460
Tel +27 21 534 0000 · ops@palmstat.co.za

Goods Received Note · Standard Operating Procedure

Step 1 of 8 · Receive-to-Pay lifecycle · raw-material intake at the dock
APPROVED
SOP-GRN-001
v1.0 · Last reviewed 2026-05-08
← Back to SOP index · Next: Material Requisition →
Lifecycle step
Step 1 of 8
Module owner
Warehouse Receiving
Trigger event
Supplier delivery at dock
Approval matrix
Storeman + QC + Supplier rep

1. Purpose

The Goods Received Note (GRN) is the legal record of raw-material entering the PalmStat factory. Whenever a supplier truck arrives at the receiving dock with paper, ink, board, thread, glue, mech, plastic film or any other RM line, the storeman generates a GRN to confirm exactly what was unloaded, accepted and rejected. The GRN closes the supplier's delivery note, opens the supplier-invoice three-way match (PO ↔ GRN ↔ invoice), and posts the on-hand quantity into the warehouse via an inventory_transactions row of type RECEIPT.

The PalmStat GRN matches the Sage X3 "Goods Receipt", Syspro "Receipt" / "Inspection & Receipt", SAP S/4HANA MIGO 101 goods-movement, and NetSuite "Item Receipt". It is the upstream document that every later production-paper trail (Material Requisition, Job Card, FGRN) ultimately ties back to via lot number and supplier reference.

Without a captured GRN, no RM is visible in the v_inventory_summary view, so no batch can validate against stock. This makes the GRN a blocking step for the entire production lifecycle.

2. When to use

3. Data sources

The GrnDoc spec (frontend/js/erp-templates/grn-doc.js) is built from the following endpoints + DB fields. Each row below is wired into a real column — not boilerplate.

Field on documentAPI endpointDB table.columnExample value
GRN Ref No.gen.previewRef('GRN')documents.grn_no / generatedGRN-2026-0001
GRN datereq.body.dateinventory_transactions.txn_date2026-05-08
Supplier namePOST /api/inventory/transactionsinventory_transactions.notes → parsedMondi Paper SA
Delivery note no.req.body.reference_noinventory_transactions.reference_noDN-MOND-44218
P.O. refreq.body.reference_nodocuments.po_noPO-2026-0142
Item codeGET /api/items?id=:iditems.codeMONDI 1200
Item descriptionGET /api/itemsitems.descriptionMondi 1200mm reel 80gsm offset
UoMmaster dataitems.uomKG / REEL / EA
Qty receivedreq.body.qtyinventory_transactions.qty2 540.00
Qty acceptedderived (recv − rej)computed in GrnDoc.build()2 510.00
Qty rejectedreq.body.qty_rejectedcaptured on row notes30.00
Lot numberreq.body.lot_numberinventory_transactions.lot_numberLOT-MND-260508
Unit costreq.body.unit_costinventory_transactions.unit_costR 18.4500
WarehouseGET /api/warehouseswarehouses.code via to_warehouse_idPSTAT
Bin locationGET /api/inventory/lotswarehouse_locations.bin_codeRM-A12-03
Captured byreq.userusers.email (FK user_id)warehouse@palmstat.co.za
Reason codereq.body.reason_codeinventory_transactions.reason_codeDELIVERY
Document attachment (delivery note PDF)POST /api/documentsdocuments.s3_key · document_linkss3://…/grn-2026-0001.pdf

4. Step-by-step workflow

  1. Truck arrives at dock — security logs the truck reg + driver. Storeman cross-checks the supplier's delivery note against the open Purchase Order in PalmStat (documents.po_no).
  2. Open RM Intake page — navigate to /rm-intake. The view lists open POs with predicted line totals.
  3. Off-load & physical count — storeman + assistant count each pallet, weigh / measure as required (KG, REEL, EA).
  4. Capture transaction lines — for each RM line, record qty received, lot number, unit cost. The form posts to POST /api/inventory/transactions with txn_type=RECEIPT. Validation enforces to_warehouse_id mandatory and qty > 0.
  5. QC sample & quarantine flag — QC officer pulls a sample per the supplier QC matrix. If suspect, storeman flips the destination to a QUARANTINE warehouse and the line is recorded with status=BLOCKED in the inventory snapshot.
  6. Record exceptions — short delivery: enter accepted qty + rejected qty as separate notes on the line. Damaged stock: separate row with reason DAMAGE routed to QC quarantine.
  7. Generate GRN PDF — the front-end calls GrnDoc.openFromInventoryTxns(txns, opts), which builds a spec via GrnDoc.build() and dispatches to ErpDoc.print(). The browser opens a print preview using the same gradient-header template used everywhere in PalmStat.
  8. Three sign-offs — storeman signs first (in person on the printed GRN), then QC officer, then the supplier rep. Original PDF is uploaded back to POST /api/documents with kind=GRN · document_links tie it to the underlying inventory_transactions rows.
  9. Post to inventory — once all 3 signatures are captured, the GRN status becomes CONFIRMED and stock is visible in v_inventory_summary. A realtime broadcast on the inventory channel notifies any open BOM-validation pages.
  10. Archive & retention — original PDF + supplier delivery note + supplier invoice (when received) are bundled under the same document_links.entity_type = 'inventory_transaction' for the 7-year SARS / VAT retention window. documents.retention_until is auto-set 2033-05-08 for a 2026 GRN.

5. Roles & permissions

ActionAdminWarehousePlannerQC / SupervisorFinance
Generate this doc
Approve / sign off✓ (Storeman)✓ (QC line)
Edit before posting
Reprint after archive
Email externally
Delete / void✓ (with audit reason)

Permission gate enforced by requireRole('admin','warehouse','planner','supervisor','operator') on POST /api/inventory/transactions.

6. Common scenarios

Scenario A · Supplier delivers short

Happy path: Supplier delivers 2 540 KG of paper against an order for 2 600 KG. Storeman records qty_received = 2 540, qty_rejected = 0, and adds a note "60 KG short · supplier to credit". GRN posts; v_inventory_summary reflects 2 540 KG. Finance receives an alert via notifications channel and chases the credit-note.

Sad path: Storeman captures 2 600 KG by mistake. Stock count overstated. Recovery: admin voids the transaction (POST /api/inventory/transactions with txn_type=ADJUST and a balancing negative qty) and records the correct figure. Audit trail preserves both rows.

Scenario B · Damaged stock received

Happy path: 12 reels arrive; 1 reel has a torn outer wrap. Storeman captures 11 reels into PSTAT at AVAILABLE status, and 1 reel into PSTAT-QC at QUARANTINE status with reason DAMAGE. QC officer inspects within 48h, either releases or scraps via txn_type=SCRAP.

Sad path: Storeman lumps all 12 reels into AVAILABLE. Damaged reel makes it onto a Job Card, defective product is run, batch fails QC. Recovery requires a back-dated SCRAP transaction and root-cause investigation.

Scenario C · Wrong item code

Happy path: Driver brings TNPL 1200 instead of MONDI 1200. Storeman queries the open PO — if substitute is approved by Procurement, captures against the correct item code. If not, refuses delivery and adds a note on the source PO; no GRN is generated.

Sad path: Storeman captures against MONDI 1200 anyway. BOM validation later picks up zero MONDI 1200 stock once the wrong reels are issued, and a TNPL stockout shows as a hidden surplus. Recovery: ADJUST out of MONDI 1200, ADJUST into TNPL 1200, with linked audit reasons.

Scenario D · Lot expiry on inks / glues

Happy path: Adhesive lot has a manufacturer expiry of 2027-05-08. Storeman captures expiry_date on the inventory row. Inventory reservation FIFO honours the expiry, so older lot is consumed first.

Sad path: Expiry not captured. Stock ageing not visible in v_inventory_summary. Recovery: cycle-count event creates a fresh inventory row with expiry data; old row scrapped.

7. Related documents

Upstream  ·  Purchase Order (PO) documents.po_no
Upstream  ·  Supplier delivery note (third-party) documents.kind=SUPPLIER_DOC
   →  STEP 1: GRN · this document
Downstream  ·  STEP 2: Material Requisition (consumes the stock just received)
Downstream  ·  Supplier invoice 3-way match (PO ↔ GRN ↔ invoice)
Downstream  ·  Monthly RM Stock Snapshot (rm_stock_snapshots)

8. Approval signatures

Document Owner
Warehouse Manager — ____________
Signed: ____ / ____ / ______
Quality Lead
QC Inspector — ____________
Signed: ____ / ____ / ______
Operations Director
Ops Director — ____________
Signed: ____ / ____ / ______