Chapter 1 · Inventory ledger, lots and status
The ledger is the truth
A stock count in a spreadsheet is a number someone typed. A stock count in this module is a sum of everything that ever happened to the stock, so you can always ask why it is what it is. This chapter says what the module builds, what it leaves to accounting, and how the ledger, the balances and the statuses fit together.
30 min11 capabilities12 transaction types7 stock statuses
By the end of this chapter you can
- Say what the module replaces and which work it leaves to the accounting system and to other modules.
- Explain why every movement is an append-only transaction, balances are derived, and a mistake is corrected by a reversal.
- Read stock by lot, location and status, and say which statuses count as available.
What the module does
Purchasing and inventory replaces the stock, material-planning and purchasing parts of a manufacturing ERP. The specification names Epicor Kinetic, Plex, NetSuite Manufacturing, Acumatica, SAP Business One, Odoo MRP, Katana, MRPeasy, Fishbowl, ECI JobBOSS2 and E2, and ProShop. Tools such as MRPeasy list the same core: MRP, lot tracking, routings and costing [5].
The module keeps an exact stock record by item, lot, serial number, location and status. It plans material with MRP (material requirements planning: working out what to buy or make, and when, from what is needed). It runs sales orders and purchasing through receipt, and it hands the invoice match status to accounting. The general ledger, payment of suppliers, collections and tax stay in the accounting system.
The eleven capabilities
| Capability | What it does | Tier |
|---|---|---|
| Inventory ledger | Every movement an immutable transaction with a reason code; balances derived; reversals, not edits | MVP |
| Lot, serial and status | Quantity by lot, serial, location and status; holds from quality enforced | MVP |
| Costing | Standard, moving average and FIFO layers; roll-up from the bill of materials; variances | STD |
| Planning parameters | Per item and site: method, lot-sizing rule, multiples, safety stock, lead time, ABC class | MVP |
| Demand | Sales orders with available-to-promise, forecasts, master production schedule | STD |
| MRP run | Explosion, gross-to-net, lead-time offset, pegging, planned orders, exception messages | MVP |
| Purchasing | Supplier prices and lead times, requisitions, orders with approval thresholds, changes | MVP |
| Receiving | Receipt against order lines, lot capture, inspection routing, return to vendor | MVP |
| Invoice match hand-off | Two- and three-way match status with variance flags, exported to accounting | STD |
| Subcontracting | Outside processing with material sent to suppliers | BIC |
| Inventory analytics | Turns, days on hand, excess and obsolete, stock-outs, forecast accuracy, supplier reliability | STD |
Standards behind it
| Standard | Use in this module |
|---|---|
| ASCM/APICS CPIM body of knowledge | MRP logic, lot-sizing rules, safety stock, master production schedule |
| US GAAP ASC 330 and IAS 2 | How inventory is measured and costed [2] |
| ISA-95 Parts 2 and 5, B2MML | Exchange of schedules, material lots and performance between ERP and MES [1] |
| OAGIS, UBL 2.x, ANSI X12 850, 855, 856, 810 | Business documents for purchase orders, acknowledgements, ship notices and invoices |
| SOX IT general controls (where they apply) | Different people approve and receive a purchase order |
Every movement is a transaction
The table inv_inventory_transaction is the ledger. One row is one movement of one item (and lot, and serial unit where tracked) from a location and status to another. Nothing else changes a quantity.
| txn_type | What happened |
|---|---|
| po_receipt | Goods arrived from a supplier against a purchase order line |
| production_issue / production_receipt | Material used by production; finished goods booked in |
| transfer_out / transfer_in | Stock left one location and arrived at another |
| adjustment | A quantity corrected, always with a reason code |
| scrap | Stock written off as unusable |
| shipment / customer_return | Goods left for a customer; goods came back |
| vendor_return | Goods sent back to a supplier |
| cycle_count | The difference found by a count |
| status_change | Stock moved between statuses, such as available to hold |
- Quantity is always above zero. The direction comes from
from_location_idandto_location_id, never from a negative number. - The ledger refuses edits. A database trigger (a rule the database runs on every change) raises an error on any update or delete of a ledger row, whatever the application does [4].
- Rules the database checks. A unique
txn_no, allowed values for the type, and a unique key that stops one request from posting twice [3]. - Balances are derived.
inv_inventory_balanceholds the current quantity by item, site, location, lot, serial unit and status. It is the sum of the ledger, kept up to date by the one route that posts.
The fifteen tables
Your agent builds the module's tables from this list in Session 2. Every table also has the standard columns id, tenant_id, created_at, created_by, updated_at, updated_by, row_version, archived_at and ext. An arrow (→) names the table a column points at; qty is a quantity, money an amount, ts a date and time, json structured data. Where a column lists its values, no other value is allowed. The specification also describes inv_cost_record and inv_demand_forecast, which this course does not build.
| Table | Columns: type, req = required |
|---|---|
| inv_inventory_transaction (append-only ledger) | txn_no text req, unique; txn_type req: po_receipt, production_issue, production_receipt, transfer_out, transfer_in, adjustment, scrap, shipment, customer_return, vendor_return, cycle_count or status_change; item_id → core_item req; lot_id → core_lot; serial_unit_id → core_serial_unit; from_location_id → core_storage_location; to_location_id → core_storage_location; from_status text; to_status text; qty qty req; uom_id → core_uom req; unit_cost money; ref_type text; ref_id uuid; reason_code_id → core_reason_code; txn_at ts req; posted_by → core_person; reversal_of_id → inv_inventory_transaction |
| inv_inventory_balance (derived from the ledger) | item_id → core_item req; site_id → core_site req; storage_location_id → core_storage_location req; lot_id → core_lot; serial_unit_id → core_serial_unit; status req: available, quarantine, hold, allocated, in_transit, consigned or damaged; qty_on_hand qty req; uom_id → core_uom req; last_txn_at ts |
| inv_item_site_plan | item_id → core_item req; site_id → core_site req; planning_method req: mrp, reorder_point, min_max, kanban or none; lot_size_rule req: l4l, foq, eoq, poq or min_max; fixed_qty qty; min_qty qty; max_qty qty; order_multiple qty; safety_stock qty; lead_time_days int; abc_class: a, b or c; planner_id → core_person; buyer_id → core_person; make_buy req: make, buy or transfer |
| inv_bom_simple | parent_item_id → core_item req; component_item_id → core_item req; qty_per qty req; uom_id → core_uom req; scrap_pct num; effective_from date; effective_to date |
| inv_supplier_item | supplier_party_id → core_party req; item_id → core_item req; supplier_part_no text; unit_price money; currency text; moq qty; lead_time_days int; preferred bool req; valid_from date; valid_to date |
| inv_purchase_requisition | req_no text req, unique; requested_by → core_person req; item_id → core_item; description text; qty qty req; uom_id → core_uom; need_by date; planned_order_id → inv_planned_order; cost_center_id → core_cost_center; status req: draft, submitted, approved, rejected or converted |
| inv_purchase_order | po_no text req, unique; supplier_party_id → core_party req; order_date date req; status req: draft, pending_approval, approved, sent, acknowledged, partially_received, received, closed or cancelled; currency text req; payment_terms text; incoterm text; ship_to_site_id → core_site; buyer_id → core_person; total money; approved_signature_id → core_e_signature |
| inv_purchase_order_line | purchase_order_id → inv_purchase_order req; line_no int req; item_id → core_item; description text; qty qty req; uom_id → core_uom req; unit_price money req; need_by date; qty_received qty; qty_invoiced qty; account_hint text; requisition_id → inv_purchase_requisition; project_ref → prj_project (a soft link) |
| inv_goods_receipt | receipt_no text req, unique; purchase_order_line_id → inv_purchase_order_line req; qty qty req; lot_id → core_lot; storage_location_id → core_storage_location; received_at ts req; received_by → core_person; inspection_required bool req; inventory_transaction_id → inv_inventory_transaction |
| inv_invoice_match | purchase_order_line_id → inv_purchase_order_line req; supplier_invoice_no text req; invoice_qty qty; invoice_amount money; match_status req: pending, matched, price_variance, qty_variance or rejected; exported_at ts |
| inv_mrp_run | run_no text req, unique; site_id → core_site; run_at ts req; horizon_days int req; parameters json; status req: running, complete or failed; triggered_by → core_person |
| inv_planned_order | mrp_run_id → inv_mrp_run req; item_id → core_item req; site_id → core_site req; order_type req: make, buy or transfer; qty qty req; due_at date req; release_at date req; status req: planned, firmed, released or cancelled; pegging json |
| inv_mrp_exception | mrp_run_id → inv_mrp_run req; item_id → core_item req; exception_type req: expedite, defer, cancel, past_due, below_safety_stock, no_source or lead_time_violation; ref_type text; ref_id uuid; message text req; suggested_date date; status req: open, actioned or ignored |
| inv_sales_order | so_no text req, unique; customer_party_id → core_party req; order_date date req; requested_at date; promised_at date; status req: draft, confirmed, in_production, partially_shipped, shipped, invoiced, closed or cancelled; currency text req; ship_to_address_id → core_address; crm_opportunity_ref → crm_opportunity (a soft link); quote_ref → crm_quote (a soft link); customer_po text |
| inv_sales_order_line | sales_order_id → inv_sales_order req; line_no int req; item_id → core_item req; qty qty req; uom_id → core_uom req; unit_price money req; requested_at date; promised_at date; qty_shipped qty; status req: open, allocated, in_production, shipped or cancelled |
The module also listens for events from other modules. This course builds only one of them, qms.hold.placed from the quality module. The others the specification lists (material consumed and lots produced in production, a quote accepted in CRM, a shipment shipped from the warehouse, an engineering change implemented), and its master production schedule, forecast and request-for-quote features, are out of scope here.
Screens and routes
| Screen or route | Who uses it | What it does |
|---|---|---|
| /inventory/receive | Receiver, on the phone | Receive order lines with lot and quantity; return to vendor |
| /inventory/stock | Stock user, on the phone | Issue, transfer, hold and count |
| /inventory/approvals | Approver | Approve requisitions and purchase orders with an e-signature |
| /inventory/purchasing | Buyer | Supplier prices, purchase orders, change orders and the invoice match |
| /inventory/planning | Planner | Planning parameters, MRP runs, planned orders and the exception queue |
| /inventory/board | Board, read-only | Three tiles: on hand by status, open exceptions by age, open purchase orders |
| /api/inventory/post | Stock user, receiver, planner, loader | The one route that posts to the ledger and changes balances |
| /api/inventory/receive | Receiver | Receipts and returns against an order line |
| /api/inventory/po | Stock user, planner, buyer | Requisitions and purchase orders, numbered and totalled on the server |
| /api/inventory/mrp | Planner | Runs MRP and writes planned orders and exception messages |
| /api/inventory/match | Buyer | Writes the invoice match status |
| /api/inventory/import | Loader, once | Loads the old tool's data in Session 5; closed in Session 6 |
A mistake is a reversal
If a row is wrong, you do not fix it. You post a second row that undoes it: the same item and quantity with from and to swapped, reason REVERSAL, and reversal_of_id pointing at the original. History shows the mistake and its correction, and the balance at any past date can still be reproduced from the ledger.
Lots, serials and statuses
A lot is a quantity made or received together, so it can be traced. A serial unit is one individual item. The balance row also carries a status: available, quarantine, hold, allocated, in_transit, consigned or damaged. Only available stock can be promised to a customer or issued to production.
When the quality module places a hold on a lot, the module receives the event qms.hold.placed and the lot moves to status hold. It stays in the balances, so you can see it, but it is outside the view of available stock and of the available-to-promise answer, so no order can use it. Releasing a hold is a status_change back to available, and it needs the planner.
Knowledge check
A planner posted an adjustment by mistake. How is it corrected?
Knowledge check
Lot LOT-B-002 holds 40 units and 20 of them are on hold. How many are available?
References
- ISA: ISA-95 standard, enterprise-control system integration. https://www.isa.org/standards-and-publications/isa-standards/isa-95-standard
- IFRS Foundation: IAS 2 Inventories. https://www.ifrs.org/issued-standards/list-of-standards/ias-2-inventories/
- PostgreSQL documentation: constraints. https://www.postgresql.org/docs/current/ddl-constraints.html
- PostgreSQL documentation: trigger functions. https://www.postgresql.org/docs/current/plpgsql-trigger.html
- MRPeasy: features by plan (MRP II, routings, lot tracking, costing). https://www.madesmarter.uk/media/b5fpo5ai/mrpeasy_features_by_plan.pdf
- PostgreSQL documentation: explicit locking. https://www.postgresql.org/docs/current/explicit-locking.html
Chapter 2 · Planning parameters and MRP
Plan what to buy and when
MRP answers one question for every item: given what is needed, what is on hand and what is already on order, what must still be bought or made, and by when. This chapter sets the parameters that steer it and works one run through by hand, with numbers small enough to check on paper.
25 min5 planning methods5 lot-sizing rules7 exception types
By the end of this chapter you can
- Say what each planning parameter on inv_item_site_plan controls.
- Work gross-to-net, lot sizing and lead-time offset by hand for one item.
- Explain pegging, and read an exception message such as expedite.
Parameters per item and site
MRP does not decide by itself how an item is planned. Each item at each site has one row in inv_item_site_plan, and the MRP run reads it. The method and lot-sizing rule come from the CPIM body of knowledge [1]. Vendor tools such as MRPeasy and Katana offer the same ideas under their own names, with reorder points and lot traceability [2][3].
| Parameter | Allowed values | What it controls |
|---|---|---|
| planning_method | mrp, reorder_point, min_max, kanban, none | How the item is planned at all |
| lot_size_rule | l4l, foq, eoq, poq, min_max | How big each planned order is |
| fixed_qty, min_qty, max_qty, order_multiple | quantities | Inputs to the rule above |
| safety_stock | a quantity | The cushion projected stock must not fall below |
| lead_time_days | days | How long between release and arrival |
| abc_class | a, b, c | A ranking of items by importance |
| make_buy | make, buy, transfer | Where the item comes from |
| planner_id, buyer_id | people | Who acts on the messages |
| lot_size_rule | In plain words |
|---|---|
| l4l (lot for lot) | Order exactly what is short, no more |
| foq (fixed order quantity) | Order a fixed amount each time; a bigger shortfall is rounded up to a whole multiple |
| eoq (economic order quantity) | Order the amount that balances the cost of ordering against the cost of holding stock: the square root of (2 x annual demand x cost per order / holding cost per unit per year) |
| poq (period order quantity) | Order enough to cover a set number of periods of demand |
| min_max | When stock falls to the minimum, order up to the maximum |
The course seed has two bought items. A-100 is planned by MRP with a fixed order quantity of 40, safety stock 10 and a lead time of 14 days. B-100 is planned by reorder point, with its min_qty of 30 used as the reorder point, a fixed quantity of 100 and a lead time of 7 days. P-100 is made, and one bill of materials row says it needs 2 of A-100.
Demand
Demand comes from confirmed sales orders, from forecasts by period, and from the orders that consume components. A sales order line also gets an available-to-promise (ATP) answer: how many units can be promised for a date from available stock and scheduled receipts, less what is already committed. Held and quarantined stock is not in that answer.
Gross-to-net, step by step
- Explode. Turn each demand for a made item into demand for its components using the bill of materials.
- Gross requirements. List the need for the component by date.
- Net. Start from available stock and add scheduled receipts (open purchase order lines), firmed planned orders, and released planned orders whose requisition is not yet on an order line. Take away each need in date order. Wherever projected stock would fall below the safety stock, the shortfall is a net requirement.
- Size. Round the shortfall up with the lot-sizing rule.
- Offset. Subtract the lead time from the due date to find the release date.
- Peg. Store, with each planned order, the demands it covers.
The worked run for A-100
Available stock is 50. Another 10 are on hold in a second lot and are left out. One open purchase order brings 20 on 2026-11-09. Safety stock is 10 and the fixed order quantity is 40.
| Date | Gross need | Scheduled receipt | Planned receipt | Projected stock after |
|---|---|---|---|---|
| 2026-11-02 | 10 | 40 | ||
| 2026-11-09 | 20 | 60 | ||
| 2026-11-16 | 30 | 30 | ||
| 2026-11-30 | 40 | 40 | 30 | |
| 2026-12-14 | 24 | 40 | 46 |
Each shortfall is smaller than the fixed quantity, so each planned buy is the full 40. Then lead-time offsetting counts back 14 days from each due date.
Exception messages
The run also writes messages for the planner in inv_mrp_exception. Each has a type and a status of open, actioned or ignored.
| exception_type | Meaning |
|---|---|
| expedite | An open order arrives after the date it is needed: move it earlier |
| defer | An order arrives well before it is needed: move it later |
| cancel | An order is no longer needed |
| past_due | An order should already have arrived |
| below_safety_stock | Projected stock falls below the safety stock |
| no_source | Nothing says where the item can come from |
| lead_time_violation | The need date is nearer than the lead time allows |
You need: Your pilot item family from Session 1, your database, and your AI coding agent
Pick one bought item from your own pilot family that has a planning method of MRP, one sales or production demand, and one open purchase order. Work on paper first.
Outcome: A hand calculation for one real item that matches the module's planned orders, or a written list of every difference with its cause.
Knowledge check
Projected stock of A-100 would fall to −10 on 30 November. Safety stock is 10 and orders are in fixed quantities of 40. What does MRP plan?
Knowledge check
A planned buy is due on 2026-12-14 and the lead time is 14 days. When is it released?
References
- ASCM: CPIM certification (the body of knowledge for MRP, lot sizing and safety stock). https://www.ascm.org/learning-development/certifications-credentials/cpim/
- MRPeasy: MRPeasy vs Katana. https://www.mrpeasy.com/?p=7838
- Dupple: MRPeasy review (lot traceability, reorder points). https://dupple.com/reviews/mrpeasy
Chapter 3 · Purchasing, receiving and the invoice match
Buy it, receive it, match it
A purchase is a short chain: someone asks, someone approves, a supplier is told, goods arrive, an invoice comes. Each link is a person with a different job, and the module records every hand-over. This chapter follows an order for 100 units of B-100 from request to match.
25 min9 order statuses5 roles3-way match
By the end of this chapter you can
- Follow a purchase from requisition to purchase order, approval, receipt and invoice match status.
- Explain why the approver of an order must not be the person who receives against it.
- Say what a receipt, a return and a quarantine do to the ledger.
From need to order
A need becomes a requisition (inv_purchase_requisition): an internal request to buy, which may come from a person or from a released planned order. Its statuses are draft, submitted, approved, rejected and converted. Once approved, the buyer converts it to a purchase order.
The buyer does not type the price. inv_supplier_item holds each supplier's price, minimum order quantity (MOQ), lead time and a preferred flag, and the order takes supplier, price and lead time from the preferred row. The seed has Supplier One selling B-100 at 2.5000 with a minimum of 20 and a lead time of 7 days. Currency is a text code, such as the ISO 4217 codes [6]. The total is computed on the server, never taken from a browser.
Approval by threshold
Each business sets its own approval amount; the course gives none. At or under it, an order needs one approval step. Over it, two steps by two different approvers. When the buyer submits, the module creates the pending approval rows and the order becomes pending_approval. Each approver confirms their password and an e-signature is stored with a hash of the order header and lines, so any later change to the order is detectable. The last signature is kept on the order as approved_signature_id.
Keep the duties apart
Where SOX applies, approving and receiving an order must be different people. The same idea runs through security guidance as separation of duties: no one person can complete a sensitive process alone [1]. The module writes it as rules in the Role and Exposure Matrix.
Receiving
A goods receipt (inv_goods_receipt) is booked against one order line. The route creates the lot, inserts the receipt, posts a po_receipt to the ledger with the unit cost from the line, raises qty_received and moves the order to partially_received or received. It refuses a receipt that would take the line above the quantity ordered.
- Lot capture. Every receipt of a lot-tracked item names a lot, so the stock can be traced to the delivery.
- Inspection routing. If
inspection_requiredis true, the goods arrive in status quarantine. The planner releases them with astatus_changeonce they pass. - Return to vendor. The receiver posts a
vendor_returnwith a reason code through the receiving route. It takes stock out and lowersqty_received. It is a new transaction, not an edit of the receipt.
Invoice match hand-off
The supplier's invoice is compared with what was ordered and what was received. A two-way match compares order and invoice. A three-way match adds the receipt, so you pay only for goods that arrived. The result is stored in inv_invoice_match as pending, matched, price_variance, qty_variance or rejected.
Documents that cross the fence
Orders, acknowledgements, ship notices and invoices travel between businesses as standard documents. In ANSI X12 they are 850 (purchase order), 855 (purchase order acknowledgement), 856 (ship notice, also called an ASN) and 810 (invoice) [2]. OAGIS business object documents [4] and UBL 2.x [3] cover the same ground in XML. Inventory tools in this class tie purchasing, receiving and stock together in the same way [5]. The module sends nothing to suppliers by itself: the buyer sends the order the way the business already does and sets the status.
You need: Your module with demo sign-ins for buyer, two approvers, receiver, stock user and planner
Use the course seed so your numbers can be compared with this chapter. Use a different browser profile or private window for each person so you really are signed in as them.
Outcome: An order for 100 of B-100 approved by the right people, received in part with a return and two lots, and matched at 90 units and 225.0000, with the three refusals recorded.
Knowledge check
A person approved a purchase order. Can they also receive the goods against it?
Knowledge check
100 units were ordered and 90 received. The supplier invoices 100. What is the match status?
References
- NIST SP 800-53 Rev. 5: security and privacy controls (includes separation of duties). https://csrc.nist.gov/pubs/sp/800/53/r5/upd1/final
- X12: the standards body for ANSI X12 transaction sets. https://x12.org/
- OASIS: Universal Business Language (UBL) 2.1. https://docs.oasis-open.org/ubl/UBL-2.1.html
- OAGi: Open Applications Group, OAGIS. https://oagi.org/
- OneCart: manufacturing inventory management software. https://www.getonecart.com/manufacturing-inventory-management-software/
- ISO 4217: currency codes. https://www.iso.org/iso-4217-currency-codes.html
Chapter 4 · Costing, measures and migration
Cost it, measure it, cut over
Stock is also money on a balance sheet, and a replacement is only proved when its numbers match the old tool's. This chapter covers how stock is costed, the five measures the module reports, and the steps from the old tool's export to the day you cancel it.
20 min3 costing methods5 measures8 migration steps
By the end of this chapter you can
- Compare standard, moving average and FIFO costing on one issue.
- Calculate the five inventory measures from their definitions.
- Load an opening balance once, reconcile it to the old valuation report, and cut over.
Costing
Each stock movement carries a unit cost, and the specification provides for inv_cost_record, which would hold an item's cost by type and date, split into material, labor, overhead and outside processing. The specification provides for three methods; the six sessions of this course record the unit cost on each movement and do not build cost records, forecasts or the journal export. The stock balances can be rebuilt at any time by a database view over the ledger [3]. IAS 2 and US GAAP ASC 330 govern how inventory is measured, and your accountant owns the choice of method; the module records the unit cost it is given and does not choose the method [1].
| Method | How an issue is costed |
|---|---|
| Standard | One fixed cost per item. What was actually paid, above or below it, is a variance. |
| Moving average | The running average of what is on hand, recalculated at each receipt. |
| FIFO layers | First in, first out: each receipt is a layer, and issues use the oldest layer first. |
Cost roll-up works up the bill of materials: a made item's cost is its components plus labor, overhead and outside processing. Activity-based costing and alignment with GAAP are core CivOps work, so the specification's inv_cost_record and journal export follow those design bases. In this course the hand-off to accounting is a CSV file of invoice match status and amounts, not the journal export. Turns, forecast error and stock-out measures are standard planning measures [2][4].
Five measures
| Measure | Definition | Question it answers |
|---|---|---|
| Inventory accuracy | Locations where |system − counted| is within tolerance, divided by locations counted | Can people trust the count? |
| Inventory turns | Cost of goods sold ÷ average inventory value | How fast does stock sell? |
| Supplier on-time delivery | Receipts on or before need-by ÷ receipts | Do suppliers keep their dates? |
| Forecast accuracy (MAPE) | Mean absolute percentage error, by item family | How wrong is the forecast on average? |
| MRP exception backlog | Open exception messages, by age | Is the planner keeping up? |
Move in: the opening balance
Nothing in the old tool has to stay alive for its history. You load three things: the item planning parameters, the open purchase and sales orders, and the stock. Stock goes in as one dated opening transaction per item, lot and location, an adjustment with reason OPENING, posted through the same route as every other movement and never written into a balance directly. A counted quantity is better than the old tool's number.
The loader runs as a dry run first: it prints counts and every row it cannot match and writes nothing until it is run with --apply. The key of each opening row (item, lot, location) is its client reference, so running the loader twice leaves the stock the same.
opening row key = item + lot + location
run the loader -> 1 adjustment per key, reason OPENING, at the cut-off time
run it again -> the key is already used, nothing is added
new value = old value + (counted - old quantity) x unit costReconcile before you trust it
Compare quantity and value with the old tool's stock valuation report for the same date. For each item, the new value must equal the old value plus the counted difference times the unit cost, and the totals must agree. A difference that cannot be explained is an error to find, not a rounding to accept. Do the same for open orders: the count of lines and the value still to receive.
Run the old tool and the module side by side for at least one week, with the same people entering the same movements in both. At cutover, take a final export and set the old tool read-only. Close the loader by removing its row from the matrix and showing that an insert through it is now refused. Cancel only once the new way works, and write the saving as arithmetic from your own invoices.
You need: Your module with the seed or your loaded pilot data, a scratch database, and your AI coding agent
This is the check you will run before cutover, done on one item. Use a scratch copy of the database for step 4.
Outcome: A check that passes on real data and fails on a hand-edited balance, and one item whose new value equals its old value plus the counted difference times its unit cost.
Knowledge check
The loader is run twice by mistake. What should happen to the opening stock?
Knowledge check
You count ten locations with the system quantity hidden. Seven are within your tolerance. What is inventory accuracy?
References
- IFRS Foundation: IAS 2 Inventories. https://www.ifrs.org/issued-standards/list-of-standards/ias-2-inventories/
- ASCM: CPIM certification (inventory, planning and control body of knowledge). https://www.ascm.org/learning-development/certifications-credentials/cpim/
- PostgreSQL documentation: CREATE VIEW (balances recomputed from the ledger). https://www.postgresql.org/docs/current/sql-createview.html
- OneCart: manufacturing inventory management software. https://www.getonecart.com/manufacturing-inventory-management-software/
Chapter 5 · 12 questions · 80% passes
Final assessment
Twelve questions across the element. Score 80% (10 of 12) to pass. Your LMS records your score and each answer; you can review the chapters and try again.
15 min12 questions≈ 15 minutesRetake allowed
Your result
CivOps AI Academy
Purchasing and Inventory: Ledger, MRP and Purchasing on Your Own Platform
Element M12 complete · Learner
Your LMS records this completion. For the CivOps Foundation certificate, finish the Foundation Course at https://civops.io/learn.