FORGE/i — Manufacturing Resource Planning

SteelFrame X application operation manual  ·  ← back to Operation Manuals  ·  Sign On

FORGE/i is a discrete-manufacturing MRP core: an item master with a multi-level bill of materials, work orders that explode the BOM and allocate components, shop-floor material issue and completion receipt, an accumulating inventory ledger, a weekly MRP regeneration with reorder suggestions and ABC re-ranking, and a monthly close that rolls standard cost up through the BOM, values work-in-process, and posts a balanced feed into the general ledger. It runs on four job cycles — daily, weekly, monthly and annual — each a CL that chains a set of RPG/COBOL programs. This manual is the reference for the operator who runs the online inquiry screens and the periodic cycles, and for the developer maintaining the application. It is grounded entirely in the committed source (mrp-app/src/sources.mjs for library FORGE, src/seed.mjs, and the test/forge_*.mjs drivers).

Contents

A. Overview & Architecture ↑ top

A.1 What it does

FORGE/i plans and tracks the manufacture of discrete goods — a pump family built from sub-assemblies and raw parts:

A.2 Single-layer architecture: RPG/DDS over keyed physical files

Honest statement: FORGE/i is a classic RPG-over-DDS application — unlike LOANSVC/i it does not push its business logic down into a DB2 SQL-PL layer. The manufacturing rules (BOM explosion, scrap uplift, netting, cost roll-up) live in the RPG programs themselves, operating directly on keyed physical files. SQL appears in exactly two places, both deliberate:

Everything else — 12 further RPG programs, 3 display files, 1 printer file, 8 physical files and 2 logical files — is native RPG/DDS. The whole application lives in library FORGE; FGSETUP (CL) creates every object and compiles every program, and the four cycle CLs drive them. The tested jobs run with LIBL = QSYS QGPL FORGE QTEMP and CURLIB = FORGE.

A.3 Component & flow

  ONLINE                 DAILY (FGDAILY)        WEEKLY (FGWEEK)
  ------                 ---------------        ---------------
  FGMENU (5250)          FGWOREL  explode+alloc FGMRPGEN  net demand -> FGMRP
   1 -> FGITEMIQ         FGISSUE  draw material  FGABC     re-rank A/B/C by value
   2 -> FGWOIQ (subfile) FGRECPT  receive done   FGMRPPR   spool suggestion report

  MONTHLY (FGMONTH)                 ANNUAL (FGYEAR)
  -----------------                 ---------------
  FGCSTRL  roll std cost up BOM     FGPHYS   physical-count variance
  FGWIPVL  value work-in-process    FGCSTRL  re-roll cost year
  FGGLPST  post balanced GL feed    FGGLRPT  trial balance
  FGGLRPT  trial balance (COBOL)

                    +----------------------------------------------+
   FGITEM (item+BOM spine) <--reads/updates-- every program        |
     |   FGBOM / FGBOMLF (parent/component access paths)           |
     |   FGWO / FGWOLF <-- FGWOMAT (order material lines)          |
     +-> FGITRN (accumulating inventory ledger: I/R/A/V)  <--------+
         FGMRP (weekly plan rows)   FGCSTH (cost-change history)
         FGGLFEED (SQL GL feed)     FGWKCTR (work centres)

A single event — say a daily material issue — flows: FGISSUE reads each open FGWOMAT line → CHAINs the component in FGITEM, relieving ONHAND and ALLOC → writes one FGITRN issue row under a stable ledger key → flips the line to issued. No control table gates the run; idempotency comes from the ledger key (section F.3), so a re-submitted cycle re-derives the same key and is refused rather than double-posting.

A.4 Object inventory

ObjectTypeRole
FGITEMPFItem master — the spine of the whole system.
FGBOMPFBill of materials (parent→component, per-unit qty).
FGBOMLFLFBOM keyed by COMPNO — where-used access path.
FGWOPFWork-order header.
FGWOLFLFWork orders keyed by status.
FGWOMATPFWork-order material lines (the explosion result).
FGITRNPFInventory transaction ledger (durable audit trail).
FGMRPPFMRP planning results, one row per item per run.
FGCSTHPFStandard-cost change history.
FGWKCTRPFWork-centre master.
FGGLFEEDSQL tableGeneral-ledger feed the monthly close posts into.
FGITEMD / FGWOD / FGMENUDDSPFItem inquiry / work-order subfile / menu.
FGMRPPPRTFMRP suggestion report printer file.
FGREFLDRPGLESeeds reference data (items, BOM, work centres).
FGWORELRPGLERelease WOs: explode BOM + allocate.
FGISSUE / FGRECPTRPGLEDaily material issue / completion receipt.
FGMRPGEN / FGABC / FGMRPPRRPGLEWeekly MRP regen / ABC re-rank / report.
FGCSTRL / FGWIPVLRPGLECost roll-up / WIP valuation (monthly).
FGPHYSRPGLEAnnual physical-count variance.
FGGLPSTSQLRPGLEMonthly GL post (embedded SQL).
FGITEMIQ / FGWOIQ / FGMENURPGLEInteractive item / work-order / menu programs.
FGGLRPTCBLLEGL trial-balance report (ILE COBOL).
FGSETUPCLPCreate every object, compile every program.
FGDAILY / FGWEEK / FGMONTH / FGYEARCLPThe four job cycles.

The full catalogue is 8 PFs + 2 LFs + 1 SQL table, 3 DSPFs + 1 PRTF, 14 RPG programs (13 RPGLE + 1 SQLRPGLE), 1 COBOL program and 5 CL programs, all in library FORGE. Sections D and F expand each.

B. Online Transactions & Screens ↑ top

B.1 The command/entry line

FORGE/i has no CICS transaction identifiers and no menu-driven transid switch. On IBM i, each program is reached by name from a 5250 command-entry line (or a JOBQ/scheduler for the batch cycles). The operator equivalent of "type a transid and Enter" is "type a CALL command and Enter". Before invoking anything, the job's library list must include FORGE.

To do thisType on the command line
Open the main menu (routes to the two inquiries)CALL FORGE/FGMENU
Open item inquiry directlyCALL FORGE/FGITEMIQ
Open work-order inquiry (subfile) directlyCALL FORGE/FGWOIQ
Build/compile the whole applicationCALL FORGE/FGSETUP
Seed reference data (items, BOM, work centres)CALL FORGE/FGREFLD
Run the daily shop-floor cycleCALL FORGE/FGDAILY (or SBMJOB it)
Run the weekly planning cycleCALL FORGE/FGWEEK
Run the monthly closeCALL FORGE/FGMONTH
Run the annual inventory/cost-year rollCALL FORGE/FGYEAR

Every batch program takes no CALL parameters. There is no LOANSVC-style control table: processing dates are compiled constants in the source (for example the daily issue posts TDT = 20260801, MRP stamps RUNNO = 202631, the monthly GL batch is 202608). A scheduled submission is therefore a bare CALL. Only FGMENU, FGITEMIQ and FGWOIQ are interactive; the batch programs run to completion and DSPLY a one-line result.

B.2 The menu & inquiry screens

FORGE/i ships three interactive programs. FGMENU is the entry point; it CALLs the two inquiries program-to-program and returns to the menu when they exit.

FORGE/i Main Menu 1. Item Inquiry 2. Work Order Inquiry Option . . . . : _ F3=Exit Enter=Select

Key 1 or 2 and Enter; FGMENU CALLs FGITEMIQ or FGWOIQ. Any other non-blank option shows Invalid option. on the menu itself. F3 ends the program.

Item inquiry (FGITEMIQ / FGITEMD)

A plain (non-subfile) screen. Key an item number, press Enter; the program CHAINs FGITEM and renders the master record plus a derived available-to-promise figure (ONHAND − ALLOC). A miss shows Item not found. and clears the detail rather than leaving stale values.

Item Inquiry - FORGE/i Item number: RM300001 Description . : CAST IRON HOUSING Type . . . . . : R Std cost . . . : 42.5000 On hand . . . : 100.00 Allocated . . : 20.00 Available . . : 80.00 ABC class . . : A Item found. F3=Exit Enter=Inquire

The available figure is genuinely derived, not stored: with two released orders drawing 10 + 10 units of the housing, 100 on-hand − 20 allocated renders as 80.00. The packed 11P4 standard cost renders at full precision (42.5000).

Work-order inquiry (FGWOIQ / FGWOD)

The app's subfile screen (DDS record WSFL under control record WCTL, SFLPAG(5) per page, SFLSIZ(20), ROLLUP/ROLLDOWN paging). Key a work order, Enter; the header (item, ordered, completed) renders and the order's material lines load into the subfile.

Work Order Inquiry - FORGE/i Work order: WO900001 Item . . . . . : FG100001 Ordered . . . : 10.00 Completed . . : 0.00 Seq Component Required Issued S 1 RM300001 10.0000 0.0000 O 2 RM300002 10.2000 0.0000 O 3 SA200001 10.0000 0.0000 O 4 RM300004 20.0000 0.0000 O Work order found. F3=Exit Roll=Page Enter=Inquire
The subfile is a classic load-then-display loop that clears and reloads after the EXFMT that read the operator key — never before it. A second enquiry against a work order with a different BOM redraws the correct number of rows, and an unknown work order clears the subfile to zero rows (SFLCLR really fires). This is documented directly in the program source as the discipline that keeps the previous enquiry's rows from bleeding into the next.

B.3 Controls & audit workflow (no four-eyes maker–checker)

Honest statement: FORGE/i does not model a true four-eyes maker–checker / separate-authorization workflow, and the online screens are read-only inquiries — neither FGITEMIQ nor FGWOIQ updates a file. All state change happens in the batch cycles. The manual documents the control model the application does have:

In sum, the control posture is an accumulating ledger + cost history + status/state gating + key-based idempotency + a balanced, independently-proved GL, rather than a segregation-of-duties approval workflow.

C. Batch Jobs & the Periodic Cycle ↑ top

FORGE/i's processing runs as four periodic cycles, each a CL program that chains a fixed set of RPG/COBOL programs and ends with a completion banner. All programs take no CALL parameters and read no control table — a scheduled/JOBQ submission is a bare CALL of the cycle CL.

-- submit the (parameterless) daily cycle
SBMJOB CMD(CALL PGM(FORGE/FGDAILY)) JOB(FGDAILY)
-- or run interactively
CALL FORGE/FGWEEK

C.1 Full batch program set

ProgramCyclePurposeReadsWrites / effectDSPLY result
FGWORELDaily Release planned WOs: explode BOM one level, allocate components. FGWO, FGBOM, FGITEM FGWOMAT lines; FGITEM.ALLOC += qty; WOSTAT P→R, RELDT set. FGWOREL RELEASED=n SKIP=n
FGISSUEDaily Issue material to released orders. FGWOMAT, FGITEM, FGITRN FGITEM ONHAND−/ALLOC−; FGITRN 'I' row (neg qty/cost); MSTAT O→I. FGISSUE ISSUED=n SKIP=n
FGRECPTDaily Receive WO completions into stock at standard cost. FGWO, FGITEM, FGITRN FGITEM ONHAND+; FGITRN 'R' row (pos); WORCVD advanced; WOSTAT W or C. FGRECPT RECEIVED=n SKIP=n
FGMRPGENWeekly MRP regeneration: net demand, suggest replenishment. FGITEM, FGWOMAT, FGMRP FGMRP row per active item (GROSSRQ/NETREQ/SUGQTY/MSGCD). FGMRPGEN RUN=n PLANNED=n SKIP=n
FGABCWeekly Re-rank items A/B/C by extended inventory value. FGITEM FGITEM.ABCCLS set (≥2000=A, ≥500=B, else C). FGABC A=n B=n C=n
FGMRPPRWeekly Spool the MRP suggestion report (page overflow). FGMRP, FGITEM Spooled printout (FGMRPP): one line per suggested order. FGMRPPR LINES=n
FGCSTRLMonthly / Annual Standard-cost roll-up: sub-assemblies then finished goods. FGITEM, FGBOM, FGCSTH FGITEM.STDCOST updated; FGCSTH row per change (before/after). FGCSTRL COSTED=n
FGWIPVLMonthly Value work-in-process from issued material. FGWO, FGWOMAT, FGITEM FGWO.WOCOST set for R/W orders. FGWIPVL ORDERS=n WIP=amt
FGGLPSTMonthly Post a balanced DR/CR feed to the GL (SQLRPGLE). FGITRN; FGGLFEED (SQL) FGGLFEED rows: raw→WIP (issue), WIP→FG (receipt). FGGLPST BATCH=n ROWS=n
FGGLRPTMonthly / Annual GL trial balance over the ledger (COBOL). FGITRN Printed totals (issues / receipts / txn count). FGGLRPT ISSUES/RECEIPTS/TXNS
FGPHYSAnnual Physical-count variance for class-A items. FGITEM, FGITRN FGITRN 'A' adjustment; FGITEM.ONHAND corrected to count. FGPHYS ADJUSTED=n

The cycle CLs chain these: FGDAILY = FGWOREL → FGISSUE → FGRECPT; FGWEEK = FGMRPGEN → FGABC → FGMRPPR; FGMONTH = FGCSTRL → FGWIPVL → FGGLPST → FGGLRPT; FGYEAR = FGPHYS → FGCSTRL → FGGLRPT.

C.2 Daily / weekly / monthly / annual detail

Daily — FGDAILY

FGWOREL reads planned orders, and for each explodes one BOM level into FGWOMAT (a sub-assembly is a material line, not a second-level explosion), applying the scrap uplift reqqty = qtyper × woqty × (1 + scrappc/100); it allocates each component on FGITEM and flips the WO to released. FGISSUE then draws every open line, relieving on-hand and allocation and posting a negative-quantity issue transaction. FGRECPT receives the increment of completions since the last receipt (WOCOMP − WORCVD) into finished stock, rolling the order to C when WOCOMP + WOSCRAP ≥ WOQTY, else leaving it W.

Expected DSPLY (a 10-unit WO for FG100001, 4-line BOM, 6 then 4 received):
  FGWOREL RELEASED=1 SKIP=0     explode + allocate
  FGISSUE ISSUED=4 SKIP=0       4 material lines drawn
  FGRECPT RECEIVED=1 SKIP=0     this run's completion increment

Worked example (the daily test's oracle): a WO for 10×FG100001 explodes to housing 10.0000, shaft 10.2000 (10 × 1.02 scrap), sub-assembly 10.0000, seal 20.0000 (2 per unit). Issuing the housing takes on-hand 100→90 and allocation 10→0, and posts an I row of -10 qty / -425.00 cost (10 × 42.50).

Weekly — FGWEEK

FGMRPGEN plans every active item: WAVAIL = ONHAND − ALLOC − SAFETY, gross requirement = sum of every open (MSTAT='O') work-order material line for that component, NETREQ = max(0, GROSS − WAVAIL), suggested order = net; the message code is OR (order), or SS if on-hand less allocation is already below safety stock. FGABC re-ranks by ONHAND × STDCOST (≥2000→A, ≥500→B, else C). FGMRPPR spools the suggestion report.

Expected DSPLY (7 active items planned; ABC re-rank):
  FGMRPGEN RUN=202631 PLANNED=7 SKIP=0
  FGABC A=n B=n C=n
  FGMRPPR LINES=n               one line per suggested order
The seal kit (RM300004) is the worked shortage: on-hand 8, safety 30, and an open WO needing 20 — so gross 20, net > 0, message SS. The housing (on-hand 100) suggests nothing. FGMRP is keyed UNIQUE on (RUNNO, ITEMNO), so a re-run of the SAME week is refused — a second FGMRPGEN reports PLANNED=0 and the file still holds one row per item.

Monthly — FGMONTH

FGCSTRL rolls standard cost bottom-up in two passes — pass 1 costs sub-assemblies (ITYPE='S') from their components, pass 2 costs finished goods (ITYPE='F') from theirs (now including the freshly-costed sub-assemblies), writing an FGCSTH row (reason R) for each change. FGWIPVL values each R/W order at the standard cost of the material issued against it. FGGLPST sums the ledger by type and posts balanced pairs into FGGLFEED; FGGLRPT (COBOL) reads the ledger and prints the trial balance.

Expected cost roll-up (from the seeded BOM & raw costs):
  SA200001 = 25.0000 + 6.2500                       = 31.2500
  FG100001 = 42.5000 + 19.1250(shaft@2% scrap)
           + 31.2500(sub-assembly) + 12.5000(2 seals)= 105.3750
  FG100002 = 85.0000(2 housings) + 18.7500          = 103.7500

The GL posts 1310-RAW credit / 1320-WIP debit for issues and 1320-WIP credit / 1330-FG debit for receipts, so WIP appears on both sides and SUM(DR) = SUM(CR). Both FGCSTRL and FGGLRPT also run in the annual cycle.

Annual — FGYEAR

FGPHYS applies the run's deterministic physical-count convention — active class-A items count 2 units short (shrinkage), everything else clean — writing an A adjustment transaction (TQTY=-2) and correcting book on-hand to the counted quantity. FGCSTRL re-rolls the cost year; FGGLRPT reprints the trial balance.

Expected DSPLY:
  FGPHYS ADJUSTED=n             class-A items adjusted (-2 each)
FGPHYS is idempotent by its stable ledger key (item sequence): a second run finds the adjustment already posted and reports ADJUSTED=0.

C.3 Ordering & dependencies

D. Data Files (data dictionary) ↑ top

All files are in library FORGE, grounded in the DDS/SQL in sources.mjs. Dates are stored as signed numeric in YYYYMMDD form. STDCOST is packed 11P4 (four decimals — a cost rolls through several BOM levels and rounding at 2dp per level loses cents); BOM quantities are packed 9P4.

FGITEM — Item master (key ITEMNO, UNIQUE)

FieldTypeMeaning
ITEMNO8AItem number (key), e.g. FG100001.
IDESC30ADescription.
ITYPE1AF finished, S sub-assembly, R raw — drives MRP explode vs purchase.
IUOM3AUnit of measure.
STDCOST11P 4Standard cost (four decimals for multi-level roll-up).
ONHAND9P 2Book on-hand quantity.
ALLOC9P 2Quantity allocated to released work orders.
SAFETY9P 2Safety-stock level (MRP nets below this).
LEADTM3S 0Lead time, days.
ABCCLS1AABC class (re-ranked weekly by value).
ISTAT1AItem status (A active).

FGBOM — Bill of materials (key PARENT, BSEQ, UNIQUE)

FieldTypeMeaning
PARENT8AParent item (key 1).
BSEQ3S 0Line sequence (key 2) — deterministic explosion order.
COMPNO8AComponent item.
QTYPER9P 4Quantity of the component per unit of the parent.
SCRAPPC5P 2Scrap percent (uplifts required quantity).
BSTAT1ABOM-line status (A active).

FGBOMLF is a logical file over FGBOM keyed on COMPNO — the where-used access path ("what does this part go into?"), non-unique by design (one component feeds many parents).

FGWO — Work-order header (key WONO, UNIQUE)

FieldTypeMeaning
WONO8AWork-order number (key).
ITEMNO8AItem being made.
WOQTY9P 2Quantity ordered.
WOCOMP9P 2Cumulative quantity reported complete.
WOSCRAP9P 2Quantity scrapped.
DUEDT / RELDT8S 0Due date / release date (YYYYMMDD).
WOSTAT1AP planned, R released, W in-work, C complete, X cancelled.
WOCOST11P 2Order cost (set by WIP valuation).
WORCVD9P 2Quantity already received — the receipt high-water mark (increment guard).

FGWOLF is a logical file over FGWO keyed on WOSTAT then WONO — the status access path for a posting run to read only released/in-work orders.

FGWOMAT — Work-order material lines (key WONO, MSEQ, UNIQUE)

FieldTypeMeaning
WONO / MSEQ8A / 3S 0Work order + line sequence (key).
COMPNO8AComponent required.
REQQTY9P 4Required quantity (explosion result, scrap-uplifted).
ISSQTY9P 4Quantity actually issued to the shop floor.
MSTAT1AO open, I issued.

FGITRN — Inventory transaction ledger (key TRNSEQ, UNIQUE)

FieldTypeMeaning
TRNSEQ8S 0Ledger sequence (key) — derived from a stable business key (see F.3).
ITEMNO8AItem affected.
TTYPE1AI issue, R receipt, A count adjustment, V revalue.
TDT8S 0Transaction date (YYYYMMDD, compiled constant per program).
TQTY9P 2Signed quantity (negative for issues).
TCOST11P 2Extended cost (negative for issues).
TREF8ASource reference (work-order number, PHYSINV).
TMEMO25AFree-text detail.

The disjoint key ranges (F.3): issues 10000000+, receipts 20000000+, adjustments 40000000+, revalues 60000000+ — so keys from different programs never collide and every one is regenerable from its source event.

FGMRP — MRP planning results (key RUNNO, ITEMNO, UNIQUE)

FieldTypeMeaning
RUNNO6S 0Regeneration run number (key 1) — successive runs accumulate.
ITEMNO8AItem planned (key 2).
GROSSRQ9P 2Gross requirement from open WO demand.
NETREQ9P 2Net requirement (gross less available).
SUGQTY9P 2Suggested replenishment quantity.
SUGDT8S 0Suggested order date.
MSGCD2AMessage code: OR order, SS below safety stock, blank none.

FGCSTH — Cost-change history (key CSEQ, UNIQUE)

FieldTypeMeaning
CSEQ8S 0History sequence (key) — 60000000 + item sequence.
ITEMNO8AItem re-costed.
OLDCOST / NEWCOST11P 4Standard cost before / after the roll-up.
CDT8S 0Change date.
CREASON1AReason (R = roll-up).

FGWKCTR — Work-centre master (key WCNO, UNIQUE)

FieldTypeMeaning
WCNO4AWork-centre number (key).
WCDESC25ADescription.
CAPHRS7P 2Capacity hours.
WCSTAT1AStatus.

FGGLFEED — GL feed (SQL table, PK GLSEQ)

FieldTypeMeaning
GLSEQDECIMAL(8,0)GL sequence (PK) — continued from MAX() each run (see F.5).
GLBATCHDECIMAL(6,0)Batch number (YYYYMM).
ACCTCHAR(9)Account: 1310-RAW, 1320-WIP, 1330-FG.
DRCRCHAR(1)D debit, C credit.
AMTDECIMAL(11,2)Posting amount.
GLREFCHAR(8)Reference (ISSUE / RECEIPT).
GLDTDECIMAL(8,0)Posting date.

Index FGGLFACC on (ACCT, DRCR) supports the by-account roll-back the post reads before continuing.

Seeded reference data (FGREFLD)

The reference load writes 7 items (2 finished, 1 sub-assembly, 4 raw), 8 BOM lines and 2 work centres:

ItemTypeStd costOn-handSafetyNotes
FG100001F0 (rolled)125Pump assembly 2in.
FG100002F0 (rolled)34Pump assembly 4in.
SA200001S0 (rolled)2010Impeller sub-assembly.
RM300001R42.500010025Cast-iron housing.
RM300002R18.75006020Stainless shaft.
RM300003R25.00004015Bronze impeller.
RM300004R6.2500830Seal kit (below safety → the MRP shortage).

BOM: FG100001 → RM300001×1, RM300002×1 (2% scrap), SA200001×1, RM300004×2; SA200001 → RM300003×1, RM300004×1; FG100002 → RM300001×2, RM300002×1.

Relationships

E. Operations Runbook ↑ top

E.1 Day-in-the-life

  1. First-time only: build the application — CALL FORGE/FGSETUP, then load reference data with CALL FORGE/FGREFLD.
  2. Confirm the job's library list includes FORGE (LIBL = QSYS QGPL FORGE QTEMP).
  3. Enter planned work orders into FGWO (WOSTAT='P').
  4. Submit the daily shop-floor cycle: SBMJOB CMD(CALL PGM(FORGE/FGDAILY)).
  5. Post-check the daily run (below).
  6. Review inventory and orders on the read-only screens: CALL FORGE/FGMENU (option 1 item inquiry, option 2 work-order subfile).

Post-checks after the daily cycle:

E.2 The MRP run & month-end close

Weekly MRP run:

  1. Ensure the week's daily cycles have run (open demand and stock are current).
  2. Submit FGWEEK. Confirm FGMRPGEN RUN=202631 PLANNED= equals the active-item count and FGMRPPR LINES= equals the number of suggested orders.
  3. Review the plan — e.g. list the shortages:
SELECT ITEMNO, GROSSRQ, NETREQ, SUGQTY, MSGCD
  FROM FORGE/FGMRP WHERE RUNNO = 202631 AND SUGQTY > 0;

Month-end close:

  1. Confirm every business day's daily cycle for the month has run.
  2. Submit FGMONTH. Confirm the FGCSTRL COSTED=, FGWIPVL WIP=, FGGLPST ROWS= and the COBOL FGGLRPT totals all appear, ending with the month-close banner.
  3. Review and reconcile the GL feed (below).

E.3 Reconciling figures & re-run rules

Reconciling figures (the same ones the cycles simulation checks against a hand-derived oracle):

SELECT SUM(AMT) FROM FORGE.FGGLFEED WHERE DRCR = 'D';
SELECT SUM(AMT) FROM FORGE.FGGLFEED WHERE DRCR = 'C';   -- must match, non-zero
SELECT ACCT, DRCR, SUM(AMT) FROM FORGE.FGGLFEED GROUP BY ACCT, DRCR;
SituationBehaviourAction
Re-run the daily cycleEach posting program's stable ledger key is already present.Safe no-op: ISSUED=0, and on-hand does not move again. Idempotent.
Re-run FGWORELOrders already past planned are skipped.No double-allocation; material lines are not duplicated.
Re-run FGMRPGEN same week(RUNNO, ITEMNO) already exists.PLANNED=0; one row per item remains. Idempotent per week.
Re-run FGPHYSThe item's count adjustment key is already posted.ADJUSTED=0. Idempotent.
Re-run FGMONTH (new activity since last close)GLSEQ continues from MAX(); only new movement posts.The GL is not frozen — the second month's activity posts and DR still equals the issue ledger (F.5).
Partial completion reported, then the restEach receipt posts only WOCOMP − WORCVD under a per-receipt key.Report increments across days; on-hand credits each increment exactly once (F.5).
Because every movement is journaled to FGITRN with a signed quantity and extended cost, and every cost change to FGCSTH with a before image, any cycle's effect is fully reconstructable after the fact for reconciliation and recovery. The cycles test verifies the ledger accumulates every transaction class (I/R/A) and that every ledger key is unique.

F. Developer Reference ↑ top

The complete program surface, from sources.mjs. All objects are in library FORGE. RPG is written column-exact fixed-form C/D specs with /free blocks; the helpers C(...) and D(...) at the top of the source emit the exact column positions.

F.1 Programs

FGREFLD (RPGLE)
Seeds items, BOM lines and work centres by write-ing hard-coded records; DSPLYs a load summary.
FGWOREL (RPGLE)
Reads FGWO; for each planned order, explodes one BOM level into FGWOMAT with the scrap uplift, allocates each component on FGITEM, then re-CHAINs the WO and flips it to R. Skips non-planned orders.
FGISSUE (RPGLE)
Reads FGWOMAT; for each open line, checks the (WO,line) ledger key, relieves ONHAND/ALLOC (allocation floored at 0), writes a negative I ledger row, sets MSTAT=I.
FGRECPT (RPGLE)
Reads FGWO; posts the completion increment (WOCOMP−WORCVD) under a per-receipt-event key (WO×100 + slot), adds to ONHAND at standard, advances WORCVD, rolls WOSTAT to C or W.
FGMRPGEN (RPGLE)
Reads FGITEM; for each active item sums open-WO demand (nested read of FGWOMAT), nets against available, writes an FGMRP row keyed (RUNNO, ITEMNO). A KLIST of both key fields drives the idempotency CHAIN.
FGABC (RPGLE)
Reads FGITEM; sets ABCCLS from ONHAND×STDCOST value bands (≥2000 A / ≥500 B / else C).
FGCSTRL (RPGLE)
Two-pass bottom-up roll-up (S then F): for each item, sums component STDCOST×QTYPER (scrap-uplifted) one BOM level down, updates STDCOST if changed, writes an FGCSTH before/after row.
FGWIPVL (RPGLE)
Reads FGWO; for each R/W order sums ISSQTY×STDCOST over its material lines into WOCOST.
FGGLPST (SQLRPGLE)
Reads FGITRN natively, accumulates issue/receipt cost, then posts balanced DR/CR pairs into FGGLFEED via EXEC SQL INSERT, continuing GLSEQ from MAX() and posting only the movement since the last close (F.5).
FGGLRPT (COBOL)
Sequentially reads the FGITRN keyed side, totals issues/receipts by type, DISPLAYs the trial balance.
FGMRPPR (RPGLE)
Reads FGMRP; for each suggested order (SUGQTY>0) writes a detail line to the FGMRPP printer file, handling page overflow (OFLIND(*IN90)).
FGPHYS (RPGLE)
Reads FGITEM; for active class-A items writes an A variance adjustment (deterministic −2 count) under an item-sequence key and corrects ONHAND.
FGITEMIQ / FGWOIQ / FGMENU (RPGLE)
The interactive item inquiry, work-order subfile inquiry, and menu router (section B.2).

F.2 The BOM explosion & cost roll-up

Explosion (FGWOREL) walks FGBOM for the WO's parent, one level only, and for each active line computes reqqty = qtyper × woqty, then if scrappc > 0 uplifts by reqqty × scrappc / 100. A sub-assembly appears as a material line on the parent's order — the explosion is deliberately single-level; the sub-assembly's own components are planned/made through its own work order.

Roll-up (FGCSTRL) is the bottom-up complement, in two passes so a finished good picks up its sub-assembly's freshly-computed cost:

SA200001 = RM300003(25.0000)x1 + RM300004(6.2500)x1              = 31.2500
FG100001 = RM300001(42.5000)x1
         + RM300002(18.7500)x1 @2% scrap = 19.1250
         + SA200001(31.2500)x1
         + RM300004(6.2500)x2 = 12.5000                         = 105.3750
FG100002 = RM300001(42.5000)x2 = 85.0000 + RM300002(18.7500)x1  = 103.7500

The four-decimal STDCOST (11P4) is what keeps the scrap-uplifted shaft cost (19.1250) exact through the roll-up rather than losing cents at each level.

F.3 The ledger key discipline (idempotency without a control table)

FORGE/i has no LOANSVC-style control row. Instead every posting program derives its FGITRN key from a stable business key, so a re-run regenerates the same key and the CHAIN guard refuses a duplicate. The ranges are disjoint so keys from different programs never collide:

ProgramTypeKey formula
FGISSUEI10000000 + WOdigits×100 + line
FGRECPTR20000000 + WOdigits×100 + receipt-slot
FGPHYSA40000000 + item-sequence
FGCSTRL(FGCSTH)60000000 + item-sequence (cost-history key CSEQ)

The guard idiom is CHAIN(EN) on the derived key with an error/found indicator, then skip if present. FGMRPGEN uses the same discipline in FGMRP but over a composite key (RUNNO, ITEMNO) via a KLIST — the source notes that chaining on RUNNO alone would match the first row of the run and wrongly skip every later item.

F.4 Embedded-SQL & the GL feed

SQL is confined to the GL. FGGLFEED is created by RUNSQLSTM (COMMIT(*NONE)) from the FGGLFD/FGGLFC members. FGGLPST reads the ledger with native RPG I/O but posts with embedded SQL:

The postings are matched pairs: on issues, credit 1310-RAW / debit 1320-WIP; on receipts, credit 1320-WIP / debit 1330-FG — so WIP is posted on both sides and the batch balances.

F.5 Two bugs the volume simulation found

Both are documented as fixes directly in the source, and both are regression-guarded by test/forge_daily.mjs / forge_cycles.mjs:

Incremental completion reporting (FGRECPT)
WOCOMP is cumulative. The original per-WO ledger key meant the first receipt permanently blocked every later one: a shop floor reporting 4 today and 6 more tomorrow silently lost the 6 — never added to on-hand, never ledgered. The key is now per receipt event (WO×100 + receipt slot) and each posting credits only WOCOMP−WORCVD, so every increment posts exactly once. Test: 6 then 4 takes on-hand 18→22 with two ledger rows.
The GL freezing across months (FGGLPST)
The post originally restarted GLSEQ at 1 every run and re-totalled from scratch, so month 2 collided with month 1 on FGGLFEED's primary key. The inserts were correctly refused — but SQLCOD was never checked, so the job reported success while the GL silently stopped tracking the inventory ledger, permanently. The fix continues GLSEQ from MAX(), posts only the movement since the last close (net of the per-account running totals), and counts a row only when SQLCOD = 0. Test: a second month-end posts the new activity and the GL debit total still equals the issue ledger exactly.

G. Glossary ↑ top

ABC classification
Ranking items by inventory value into A (high), B, C bands so attention and count effort focus where the money is. FORGE/i re-ranks weekly (FGABC) by ONHAND×STDCOST.
Allocation
Reserving on-hand stock to a released work order without yet removing it. Held in FGITEM.ALLOC; MRP nets against it, and issue relieves it.
Available-to-promise
On-hand less allocation — the free stock. Derived on the item inquiry screen, not stored.
BOM — Bill of Materials
The parent→component structure (FGBOM) with a per-unit quantity, telling MRP and the roll-up what a part is made of. Explosion walks it downward; where-used (FGBOMLF) walks it upward.
Explosion
Expanding a parent's order into its component requirements via the BOM. FORGE/i explodes one level per work order.
Gross / net requirement
Gross = total demand for a component from open work orders; net = gross less available stock (on-hand − allocation − safety). A positive net drives a suggested order.
Idempotent
Safe to run again with the same result. In FORGE/i, achieved by deriving each ledger/plan key from a stable business key so a re-run is refused rather than double-posting.
Ledger (inventory transaction ledger, FGITRN)
The accumulating, unique-keyed audit trail of every stock movement (issue I / receipt R / adjustment A / revalue V), with signed quantity, extended cost and a source reference.
MRP — Manufacturing/Material Requirements Planning
Computing what to make or buy and when, by netting demand against supply. FORGE/i regenerates MRP weekly (FGMRPGEN) into FGMRP.
Safety stock
A buffer quantity MRP treats as unavailable, so a suggestion fires before stock actually runs out. Held in FGITEM.SAFETY; the seal kit (safety 30, on-hand 8) is FORGE/i's worked shortage.
SBMJOB
Submit Job — the IBM i command that queues a program as a batch job, e.g. SBMJOB CMD(CALL PGM(FORGE/FGDAILY)).
Scrap uplift
Increasing a component's required quantity by a scrap percentage so enough is issued to yield good units: reqqty × (1 + SCRAPPC/100).
SQLRPGLE / EXEC SQL
RPG with embedded SQL. In FORGE/i only FGGLPST uses it — native I/O over the ledger, EXEC SQL INSERT into the SQL GL feed.
Standard cost / roll-up
A fixed unit cost per item; the roll-up (FGCSTRL) recomputes each parent's cost bottom-up from its components, stored to four decimals (11P4) to survive multi-level rounding.
Subfile
A 5250 display construct listing many rows on one screen (DDS SFL/SFLCTL). FGWOIQ's material-line list is a subfile, cleared and reloaded after each enquiry.
WIP — Work In Process
Value tied up in released, not-yet-complete orders. Valued monthly (FGWIPVL) from issued material, and the GL account (1320-WIP) posted on both issue and receipt.
Work order (WO)
An order to manufacture a quantity of an item (FGWO), moving planned → released → in-work → complete, consuming its material lines (FGWOMAT).