ORDERIS/i — Order Entry, Invoicing & Accounts Receivable

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

ORDERIS/i is an order-to-cash application: customer credit control, order capture with volume-break pricing, stock allocation and back-order handling, invoicing, cash application, AR ageing, a revenue GL post, and an annual credit-limit review with year-end roll. The processing logic lives in fixed-form and free-form ILE RPG programs (one SQLRPGLE for the GL post, one ILE COBOL for the AR control report), orchestrated by CL cycle programs; DB2 for i holds the data as keyed physical and logical files plus one SQL table. This manual is the reference for the operator who runs the four periodic cycles and the online inquiry screens, and for the developer maintaining the application. It is grounded entirely in the committed source (order-app/src/sources.mjs, order-app/src/seed.mjs, and the order-app/test/oe_*.mjs drivers).

Contents

A. Overview & Architecture ↑ top

A.1 What it does

ORDERIS/i runs the full order-to-cash cycle for a distributor:

A.2 Program-driven architecture: RPG posts, CL sequences, DB2 keeps state

The application is a classic IBM i batch estate. There is no single rules engine and no stored-procedure layer; each business rule is coded in the RPG program that owns that step:

The benefit for operations: every cycle is a bare CALL of one CL program, each program reports a one-line DSPLY tally, and re-runnability is engineered per program through derived keys (see F.3) rather than a control table. Everything runs in library ORDERIS.

A.3 Component & flow

  ONLINE (5250)          DAILY  OEDAILY                WEEKLY OEWEEK
  ------------           --------------                -------------
  OEMENU (menu)          OEPRICE   (volume pricing)    OEBOREL (b/o release sweep)
    opt 1 -> OECUSTIQ    OECREDIT  (credit check)      OEBOOK  (order-book report)
    opt 2 -> OEORDIQ     OEALLOC   (allocate/back-ord)
             (subfile)   OEINVGEN  (invoice + AR up)   MONTHLY OEMONTH
                         OECASHAP  (cash + AR down)    -------------
                                                       OEAGE   (AR ageing buckets)
  SETUP                  ANNUAL OEYEAR                 OESTMT  (statement print)
  -----                  -------------                 OEGLPST (revenue GL post)
  OESETUP                OECRREV  (credit review)      OEARRPT (AR control, COBOL)
   OEREFLD (seed data)   OEARCHIV (archive+year reset)
                         OEARRPT  (AR control)

  DATA:  OECUST OEITEM OEORDH OEORDL OEPRIC OEINVH OEAROP OECASH OESHIS
         OEORDLLF(by ITEM)  OEARDLF(by DUEDATE)  OEGLDIST(SQL)

A single day flows: capture orders into OEORDH/OEORDL (status 'N') → OEDAILY prices them, credit-checks them (approve 'A' or hold 'H'), allocates against OEITEM stock (back-ordering shortfalls), invoices allocated orders (writing OEINVH + OEAROP + OESHIS and raising OECUST.BALANCE), and applies receipts from OECASH (lowering the balance). Every money movement leaves a durable OESHIS audit row.

A.4 Object inventory

ObjectTypeRole
OECUSTPFCustomer master (credit limit, live AR balance, terms, hold).
OEITEMPFProduct master (list price, on-hand, allocated, tax code).
OEORDHPFOrder header (status, stamped net/tax/total, invoice no).
OEORDLPFOrder lines (composite key ORDNO+LSEQ).
OEORDLLFLFOrder lines keyed by ITEMNO (demand-by-product path).
OEPRICPFVolume-discount price breaks (ITEMNO+BRKQTY).
OEINVHPFInvoice header (one per invoiced order).
OEAROPPFAR open items (the receivables ledger; CUSTNO+INVNO).
OEARDLFLFAR open items keyed by ARDUEDT (ageing path).
OECASHPFCash receipts.
OESHISPFSales-history / durable audit trail.
OEGLDISTSQL tableRevenue/AR/tax GL distribution (+ index OEGLDACC).
OECUSTD / OEORDD / OEMENUDDSPFCustomer inquiry / order-subfile inquiry / menu.
OEAGEPPRTFAR ageing / order-book printer report.
OEPRICE OECREDIT OEALLOC OEINVGEN OECASHAPRPGLEThe daily order-to-cash chain.
OEBOREL OEBOOKRPGLEWeekly back-order release + order-book report.
OEAGE OESTMT OECRREV OEARCHIVRPGLEMonthly ageing/statement; annual review/archive.
OEGLPSTSQLRPGLEMonthly revenue GL post (embedded SQL).
OEARRPTCBLLEILE COBOL AR control report.
OEREFLDRPGLEReference-data seed (customers/products/breaks).
OECUSTIQ OEORDIQ OEMENURPGLEInteractive inquiry programs + menu.
OESETUPCLPObject create + program compile.
OEDAILY OEWEEK OEMONTH OEYEARCLPThe four job-cycle drivers.

The full catalogue is 9 PFs + 2 LFs + 3 DSPFs + 1 PRTF + 1 SQL table, driven by 16 RPG programs, 1 COBOL program and 5 CL programs. Sections D and F expand each.

B. Online Transactions & Screens ↑ top

B.1 The command/entry line

ORDERIS/i has no CICS transaction identifiers and no transid switch. On IBM i, each program is reached by name from a 5250 command-entry line (or a JOBQ/scheduler for the cycle programs). 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 ORDERIS — the tested jobs run with LIBL = QSYS QGPL ORDERIS QTEMP and CURLIB = ORDERIS.

To do thisType on the command line
Open the main menu (routes to the two inquiries)CALL ORDERIS/OEMENU
Open customer inquiry directlyCALL ORDERIS/OECUSTIQ
Open order inquiry (subfile) directlyCALL ORDERIS/OEORDIQ
Run the daily order-to-cash cycleCALL ORDERIS/OEDAILY (or SBMJOB it)
Run the weekly back-order/order-book cycleCALL ORDERIS/OEWEEK
Run the monthly AR closeCALL ORDERIS/OEMONTH
Run the annual credit review / year-end rollCALL ORDERIS/OEYEAR
Create objects & compile (first-time / rebuild)CALL ORDERIS/OESETUP then CALL ORDERIS/OEREFLD

The four cycle programs take no CALL parameters and drive their run dates from constants inside the posting programs (the invoicing run stamps 20260801; ageing/GL run at 20260930), so a scheduled submission is a bare CALL. Only the three inquiry programs are interactive; the cycles run to completion and DSPLY a one-line tally per step.

B.2 The inquiry screens (OEMENU / OECUSTIQ / OEORDIQ)

Honest statement: the online layer is inquiry-only. There is no online order-entry, payment-posting or maintenance screen — orders and receipts are created into the files (batch load or capture upstream) and the RPG cycles do all the processing. The three DDS programs let an operator look at a customer or an order; they never update a master file.

OEMENU — main menu

A plain screen (record OEMENU) offering option 1 Customer Inquiry (calls OECUSTIQ) and 2 Order Inquiry (calls OEORDIQ). Any other non-blank option shows Invalid option. F3 ends the program.

OECUSTIQ — customer inquiry (plain DSPF)

Keys a customer number into ICUST, CHAINs OECUST, and shows the master fields plus the derived available credit (limit less balance) — the figure the credit check actually reasons about. A miss shows Customer not found.

Customer Inquiry - ORDERIS/i Customer number: C00001 Name . . . . . : NORTHWIND TRADING CO Town . . . . . : LEEDS Credit limit . : 50,000.00 Balance . . . : 1,922.40 Available . . : 48,077.60 Terms (days) . : 30 On hold . . . : N Customer found. F3=Exit Enter=Inquire

OEORDIQ — order inquiry with a line subfile (SFL/SFLCTL)

The app's subfile screen. Keys an order number into IORDNO, CHAINs OEORDH for the header (customer, status, hold reason, order total), then loads the order's lines into subfile OSFL under control record OCTL (SFLPAG(5) per page, SFLSIZ(20), ROLLUP/ROLLDOWN paging). A credit-held order renders its status H and hold reason (e.g. CL) on screen.

Order Inquiry - ORDERIS/i Order number: ORD00001 Customer . . . : C00001 Status . . . . : I Hold reason . : Order total . : 1,922.40 Seq Item Ordered Alloc B/Ord Net S 1 PR100001 20 20 0 450.00 I 2 PR100002 10 10 0 1330.00 I Order found. F3=Exit Roll=Page Enter=Inquire

Subfile columns (OSFL)

FieldType (DDS)Shows
SSEQ2Y,0 outputLine sequence (LSEQ).
SITEM8A outputProduct number (ITEMNO).
SQTY10A outputOrdered quantity (LQTY).
SALL10A outputAllocated / shippable now (LALLOC).
SBO10A outputBack-ordered remainder (LBORD).
SNET12A outputExtended net (LNET).
SSTAT1A outputLine status (LSTAT: O/A/B/I/X).
The subfile is cleared and re-loaded on every enquiry (SFLCLR via *IN31), and SFLDSP/SFLDSPCTL are driven off an indicator (N31) so an order number that does not exist shows Order not found. and an empty subfile rather than redisplaying the previous enquiry's rows — a real-DDS fix noted in the program source.

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

Honest statement: ORDERIS/i does not model a true four-eyes maker–checker / separate-authorization workflow. No "one user posts, a second user approves" step exists in the code; the batch cycles process whatever orders and receipts are present. The manual documents the control model the application does have:

In sum, the control posture is a credit-control gate + a strict AR-balance invariant + a durable audit trail + derived-key idempotency, all enforced in the posting programs, rather than a segregation-of-duties approval workflow.

C. Batch Jobs & the Periodic Cycle ↑ top

ORDERIS/i runs as four periodic cycles rather than one monolithic nightly job: a daily order-to-cash chain, a weekly back-order/report cycle, a monthly AR close, and an annual credit review / year-end roll. Each is one CL program that CALLs its posting programs in order and ends with an SNDPGMMSG completion banner. None takes CALL parameters; run dates are constants inside the posting programs.

-- run a cycle interactively
CALL ORDERIS/OEDAILY

-- or submit it to a job queue / scheduler (bare CALL, no parms)
SBMJOB CMD(CALL PGM(ORDERIS/OEMONTH)) JOB(OEMONTH)

C.1 Full batch program set

ProgramCyclePurposeReads / writesDSPLY tally
OEPRICEDailyPrice open lines from volume breaks; stamp header net/tax/total (tax 8% on 'S').OEORDH/OEORDL/OEITEM/OEPRIC.OEPRICE PRICED=n SKIP=n
OECREDITDailyCredit-check 'N' orders vs available credit; hold with reason CL/MH/CS.OEORDH/OECUST.OECREDIT APPROVED=n HELD=n SKIP=n
OEALLOCDailyAllocate approved lines against free stock; back-order the shortfall. Skips held orders.OEORDH/OEORDL/OEITEM.OEALLOC ALLOC=n BORD=n SKIP=n
OEINVGENDailyInvoice allocated orders; write OEINVH+OEAROP+OESHIS; raise OECUST.BALANCE; relieve stock.OEORDH/OEORDL/OEITEM/OEINVH/OEAROP/OECUST/OESHIS.OEINVGEN INVOICED=n SKIP=n
OECASHAPDailyApply unapplied receipts to open items; lower OECUST.BALANCE by what is applied.OECASH/OEAROP/OECUST/OEINVH/OESHIS.OECASHAP APPLIED=n SKIP=n
OEBORELWeeklyRelease back-ordered lines as stock arrives; lift the header back to 'A' to bill the remainder.OEORDH/OEORDL/OEITEM/OESHIS.OEBOREL RELEASED=n STILLBO=n
OEBOOKWeeklyPrint the un-invoiced order book (held/approved/back-order) on the PRTF.OEORDH/OEORDL/OECUST → OEAGEP.OEBOOK ORDERS=n VALUE=n
OEAGEMonthlyAge open items into buckets 0/1/2/3 via the 30/360 serial; read oldest-due-first through OEARDLF.OEAROP (via OEARDLF).OEAGE B0=n B1=n B2=n B3=n
OESTMTMonthlyPrint the AR statement/ageing report over the due-date path.OEAROP (via OEARDLF)/OECUST → OEAGEP.OESTMT LINES=n OPEN=n
OEGLPSTMonthlyPost balanced DR AR / CR Revenue / CR Tax from the invoice register into OEGLDIST.OEINVH → OEGLDIST (embedded SQL).OEGLPST BATCH=n ROWS=n
OEARRPTMonthly/AnnualILE COBOL AR control report: raised / open / item count / overdue over the ledger.OEAROP.OEARRPT RAISED/OPEN/ITEMS/OVERDUE
OECRREVAnnualCredit-limit review: halve+hold bad payers (bucket 3), reward good ones (+20%); stamp CREVYR.OECUST/OEAROP.OECRREV UP=n DOWN=n SAME=n
OEARCHIVAnnualWrite one turnover-archive row per customer; close fully-settled AR items (year-end reset).OECUST/OESHIS/OEAROP.OEARCHIV ARCHIVED=n CLOSED=n SKIP=n
OEREFLDSetupSeed 4 customers, 5 products, 4 volume breaks.OECUST/OEITEM/OEPRIC.OEREFLD CUST=4 ITEM=5 PRICE=4

C.2 Daily / weekly / monthly / annual detail

Daily — OEDAILY (OEPRICE → OECREDIT → OEALLOC → OEINVGEN → OECASHAP)

Pricing. For each order line, OEPRICE walks the item's OEPRIC breaks in ascending quantity and keeps the last break the line quantity qualifies for — the biggest discount earned. Unit = list − discount%; line net = (allocated if >0 else ordered) × unit. The header carries the summed net, 8% tax on 'S'-rated lines only, and the total. It is idempotent: it recomputes from LQTY every run, so a re-run lands on identical numbers.

Credit check. OECREDIT considers only 'N' orders. Available = CRLIMIT − BALANCE; if the order total exceeds it → hold CL; a CHOLD='Y' customer → MH; a non-active or unknown customer → CS; otherwise approve ('A').

Allocation. OEALLOC processes only 'A' orders. Free = on-hand less already-allocated; it takes min(free, ordered), back-orders the rest, values the line on what will ship, and sets the order to 'B' only if nothing at all could be allocated.

Invoicing. OEINVGEN invoices 'A' orders: invoice number IN0+order digits (stable), relieves on-hand and allocation for what shipped, raises BALANCE by the total, writes the invoice, the AR open item (due = invoice date + terms), and an OESHIS row. A line with a back-ordered remainder stays open for the weekly sweep.

Cash. OECASHAP applies each 'U' (unapplied) receipt to its named open item, taking only what is owed; an over-payment is part-applied (RCSTAT='P'). Balance falls by exactly what was applied.

Expected DSPLY (three seeded orders, one cash receipt):
  OEPRICE PRICED=3 SKIP=0
  OECREDIT APPROVED=2 HELD=1 SKIP=0    ORD00002 held CL (720.00 > 500.00)
  OEALLOC ALLOC=n BORD=1 SKIP=1        ORD00003 line back-orders 7 of 12; held order skipped
  OEINVGEN INVOICED=2 SKIP=1           IN000001 = 1922.40, IN000003 = 67.50
  OECASHAP APPLIED=1 SKIP=0            1000.00 vs IN000001 -> balance 922.40

Weekly — OEWEEK (OEBOREL → OEBOOK)

OEBOREL walks back-ordered ('B') lines and re-allocates whatever stock has arrived, flipping a line back to 'A' when it can be filled in full, re-valuing on the new allocation, and writing a 'B'-type OESHIS row. Crucially it lifts a partially-invoiced header ('I') back to 'A' so OEINVGEN bills the released remainder — a volume-simulation fix noted in the source. OEBOOK then prints the still-open book.

Expected DSPLY (7 units restocked, back-order fully released):
  OEBOREL RELEASED=1 STILLBO=0    ORD00003 line: 7 allocated, header B/I -> A
  OEBOOK ORDERS=n VALUE=n

Monthly — OEMONTH (OEAGE → OESTMT → OEGLPST → OEARRPT)

OEAGE ages every open item using the 30/360 serial ((yyyy*12)+mm)*30+dd: days = serial(run) − serial(due), bucket 0 current, 1 (1–30), 2 (31–60), 3 (61+). OESTMT prints the ageing over the due-date path. OEGLPST sums the invoice register and posts balanced DR 1200-AR / CR 4000-REV / CR 2200-TAX into OEGLDIST, continuing the GLSEQ sequence from what is already posted and only posting movement since the last close (so month two does not collide on the primary key). OEARRPT (COBOL) reports the ledger totals.

Expected DSPLY (one item in each of four buckets seeded):
  OEAGE B0=1 B1=2 B2=1 B3=1
  OESTMT LINES=n OPEN=n
  OEGLPST BATCH=202609 ROWS=n     DR 1200-AR 1989.90; CR 4000-REV 1842.50; CR 2200-TAX 147.40
  OEARRPT RAISED / OPEN / ITEMS / OVERDUE

Annual — OEYEAR (OECRREV → OEARCHIV → OEARRPT)

OECRREV reviews each active customer once per review year (guarded by CREVYR): anything in ageing bucket 3 → limit halved and manual hold set; else balance ≤ 25% of limit → limit +20%; else unchanged. OEARCHIV writes one turnover-archive row per trading customer (sum of that customer's invoice history) and closes every fully-settled AR open item (ARSTAT='C').

Expected DSPLY:
  OECRREV UP=n DOWN=n SAME=n     C00002 500.00 -> 250.00 + hold; C00004 25000 -> 30000
  OEARCHIV ARCHIVED=n CLOSED=n SKIP=n

C.3 Ordering & dependencies

D. Data Files (data dictionary) ↑ top

All files are in library ORDERIS, grounded in order-app/src/sources.mjs. Dates are stored as signed numeric YYYYMMDD; money and quantities are packed decimal (P); prices are 4-decimal packed (11P4), most values 2-decimal.

OECUST — Customer master (key CUSTNO, UNIQUE)

FieldTypeMeaning
CUSTNO6ACustomer number (key).
CNAME30ACustomer name.
CTOWN20ATown.
CRLIMIT11P,2Credit ceiling the credit check tests against.
BALANCE11P,2Live AR balance; moved ONLY by invoicing (up) and cash (down).
CTERMS3S,0Payment terms in days (drives the AR due date).
CDISC5P,2Customer discount percent (carried, informational).
CHOLD1A'Y' parks the customer on manual hold regardless of arithmetic.
CSTAT1ACustomer status ('A' active).
CREVYR4S,0Review year stamp — the annual credit-review idempotency guard.

OEITEM — Product master (key ITEMNO, UNIQUE)

FieldTypeMeaning
ITEMNO8AProduct number (key).
IDESC30ADescription.
IUOM3AUnit of measure.
LISTPR11P,4Pre-discount unit price.
ONHAND9P,2On-hand quantity.
ALLOC9P,2Allocated (reserved) quantity; free stock = ONHAND − ALLOC.
TAXCD1A'S' standard-rated (8% tax), 'Z' zero-rated.
ISTAT1AProduct status ('A' active).

OEORDH — Order header (key ORDNO, UNIQUE)

FieldTypeMeaning
ORDNO8AOrder number (key), e.g. ORD00001.
CUSTNO6AOwning customer.
ORDDT8S,0Order date (YYYYMMDD).
OSTAT1AN new, H on credit hold, A approved/allocated, B back-ordered, I invoiced, X cancelled.
OHOLDR2AHold reason (CL / MH / CS) when OSTAT='H'.
ONETVAL / OTAXVAL / OTOTVAL11P,2Stamped net / tax / total (pricing & invoicing).
OINVNO8AInvoice number once invoiced.

OEORDL — Order lines (composite key ORDNO+LSEQ, UNIQUE)

FieldTypeMeaning
ORDNO / LSEQ8A / 3S,0Order + line sequence (composite key → needs a KLIST to re-CHAIN).
ITEMNO8AProduct.
LQTY9P,2Ordered quantity.
LALLOC9P,2Allocated (shippable now).
LBORD9P,2Back-ordered remainder = LQTY − LALLOC.
LUNITP11P,4Unit price after the volume break.
LDISCP5P,2Discount percent taken off list.
LNET11P,2Extended net (valued on what ships).
LSTAT1AO open, A allocated, B back-order, I invoiced, X cancelled.

OEPRIC — Volume-discount price breaks (composite key ITEMNO+BRKQTY, UNIQUE)

FieldTypeMeaning
ITEMNO / BRKQTY8A / 9P,2Product + quantity threshold (key, ascending walk).
BRKDISC5P,2Discount percent once the line reaches BRKQTY.
PSTAT1ABreak status ('A' active).

Seeded breaks: PR100001 10+→10% & 50+→15%; PR100002 5+→5%; PR100004 20+→20%; others none.

OEINVH — Invoice header (key INVNO, UNIQUE)

FieldTypeMeaning
INVNO8AInvoice number (key), DERIVED from the order (IN0+order digits).
ORDNO / CUSTNO8A / 6ASource order and customer.
INVDT8S,0Invoice date.
INVNET / INVTAX / INVTOT11P,2Net / tax / total.
INVSTAT1A'O' open, 'P' paid (set by cash application).

OEAROP — AR open items / receivables ledger (composite key CUSTNO+INVNO, UNIQUE)

FieldTypeMeaning
CUSTNO / INVNO6A / 8ACustomer + invoice (key; groups a customer's items).
ARINVDT / ARDUEDT8S,0Invoice date / due date (= invoice date + terms).
ARAMT11P,2Original invoice total.
AROPEN11P,2Outstanding amount (reduced as cash is applied).
ARAGE1S,0Ageing bucket 0/1/2/3 stamped by OEAGE.
ARSTAT1A'O' open, 'P' settled, 'C' closed (year-end reset).

OECASH — Cash receipts (key RCPTNO, UNIQUE)

FieldTypeMeaning
RCPTNO8AReceipt number (key).
CUSTNO / RCINVNO6A / 8ACustomer + nominated invoice.
RCDT8S,0Receipt date.
RCAMT11P,2Amount tendered.
RCAPPL11P,2Amount actually applied (≤ open balance).
RCSTAT1A'U' unapplied, 'A' fully applied, 'P' part-applied.

OESHIS — Sales history / durable audit trail (key HSEQ, UNIQUE)

FieldTypeMeaning
HSEQ8S,0Sequence (key) — disjoint numeric ranges per program (see F.3).
CUSTNO / HITEM6A / 8ACustomer + item (or a marker like *ORDER/*CASH).
HTYPE1AI invoice, C cash, B back-order release, Y year-end archive.
HDT / HQTY / HAMT8S,0 / 9P,2 / 11P,2Date / quantity / amount (cash amounts are negative).
HREF / HMEMO8A / 25AReference (order/invoice) + free-text memo.

OEGLDIST — GL distribution (SQL table, PK GLSEQ; index OEGLDACC on ACCT,DRCR)

FieldTypeMeaning
GLSEQDECIMAL(8,0)Monotonic sequence (PK); continued across months.
GLBATCHDECIMAL(6,0)Post batch (YYYYMM).
ACCT / DRCRCHAR(9) / CHAR(1)Account (1200-AR, 4000-REV, 2200-TAX) + D/C.
AMTDECIMAL(11,2)Posted amount.
GLREF / GLDTCHAR(8) / DECIMAL(8,0)Reference + posting date.

Logical files

Relationships

E. Operations Runbook ↑ top

E.1 Day-in-the-life

  1. Confirm the job's library list includes ORDERIS (ADDLIBLE LIB(ORDERIS) — the cycle CL programs already do this).
  2. Ensure the day's new orders are captured into OEORDH/OEORDL at status 'N', and any receipts into OECASH at RCSTAT='U'.
  3. Submit the daily cycle: SBMJOB CMD(CALL PGM(ORDERIS/OEDAILY)).
  4. Post-check the daily run (see below).
  5. On the weekly day (once stock has been restocked), submit OEWEEK; review OEBOREL RELEASED= and the order-book report.
  6. Answer inquiries interactively via CALL ORDERIS/OEMENU (customer / order inquiry).

Post-checks after the daily cycle:

E.2 Month-end & year-end close

  1. Confirm every business day's daily cycle and each weekly sweep has run for the period.
  2. Submit OEMONTH. Confirm the ageing spread, the statement, and the GL post.
  3. Review and reconcile the GL distribution:
SELECT ACCT, DRCR, SUM(AMT) FROM ORDERIS.OEGLDIST GROUP BY ACCT, DRCR;

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

Year-end (annual): submit OEYEAR; confirm the credit review moved the right limits (a bucket-3 debtor's limit halved and put on hold; a well-settled account raised 20%), one turnover-archive row exists per trading customer (archived turnover = that customer's invoiced history), and fully-settled AR items are closed while genuinely-open items stay open.

E.3 Failure & re-run rules

Each program DSPLYs a one-line tally; a chain that ran clean ends with its CL completion banner (e.g. ORDERIS daily order-to-cash cycle complete.). Re-runnability is engineered per program.

SituationBehaviourAction
Re-run OEPRICE / OEDAILYPricing recomputes from LQTY; the chain is idempotent.Safe. Re-run raises no new invoices and does not move the balance again.
Re-run OEINVGENDerived invoice key already exists; CHAIN(EN) refuses it.Never double-invoices. Register count and balance unchanged.
Re-run OECASHAPReceipt-derived history key already present; receipt already flipped off 'U'.Applies nothing further; balance does not fall twice.
Re-run OEALLOCJudges the header from PERSISTED line state, not this pass.Re-run is a no-op; allocation is not doubled (stays reserved once).
Re-run OEBORELNothing left in 'B'; release-history key guards each line.Releases nothing further; stock reservation not doubled.
Re-run OEGLPSTContinues GLSEQ from max posted; posts only movement since last close; checks SQLCOD.Second month does not collide on the PK, and a refused insert is NOT counted as posted.
Re-run OECRREVCREVYR stamp skips an already-reviewed customer.A second review leaves every limit exactly where it was (no compounding).
Re-run OEARCHIVCustomer-derived archive key guards the row.Archives nothing further; no duplicate archive rows.
Order stuck on holdHeld order never allocates or invoices.Clear the cause (raise limit / lift CHOLD / activate customer), reset OSTAT to 'N', re-run OEDAILY.
Because every money movement is journaled to OESHIS with a unique key, and the AR balance moves only through invoicing and cash, any cycle's effect is fully reconstructable after the fact for reconciliation and recovery.

F. Developer Reference ↑ top

The complete program surface, from order-app/src/sources.mjs. All objects are in library ORDERIS; the seed loader is order-app/src/seed.mjs.

F.1 Batch / posting programs

OEPRICE (RPGLE)
Prices every open order line: keeps the biggest qualifying volume break, sets LUNITP/LDISCP/LNET, stamps ONETVAL/OTAXVAL/OTOTVAL (8% tax on 'S'). Skips 'I'/'X' orders. Idempotent (recomputes from LQTY).
OECREDIT (RPGLE)
Credit-checks 'N' orders against CRLIMIT−BALANCE; holds with CL/MH/CS or approves ('A').
OEALLOC (RPGLE)
Allocates 'A' orders against free stock (ONHAND−ALLOC), back-orders shortfalls, values on what ships, demotes to 'B' only if nothing allocated. Re-run safe via persisted line state.
OEINVGEN (RPGLE)
Invoices 'A' orders: derived INVNO, relieves stock, writes OEINVH/OEAROP/OESHIS, raises BALANCE by the total, due = invoice date + terms; a back-ordered remainder stays 'B' for the weekly sweep.
OECASHAP (RPGLE)
Applies 'U' receipts to their open item (only what is owed), lowers BALANCE by what is applied, marks the invoice 'P' when settled, writes an OESHIS cash row (negative amount).
OEBOREL (RPGLE)
Weekly: re-allocates arrived stock to 'B' lines, flips to 'A' when filled, lifts a partially-invoiced header back to 'A', writes a 'B' history row.
OEBOOK (RPGLE)
Weekly: prints the un-invoiced order book (excludes 'I'/'X') on OEAGEP with overflow handling.
OEAGE (RPGLE)
Monthly: stamps ARAGE 0/1/2/3 from the 30/360 serial days-overdue, walking OEARDLF oldest-due-first.
OESTMT (RPGLE)
Monthly: prints the AR statement/ageing over the due-date path with overflow handling.
OEGLPST (SQLRPGLE)
Monthly: sums OEINVH, posts DR 1200-AR / CR 4000-REV / CR 2200-TAX into OEGLDIST via embedded SQL, continuing GLSEQ and posting only the movement since the last close; counts a row only if SQLCOD=0.
OECRREV (RPGLE)
Annual: halves+holds bucket-3 debtors, raises well-behaved accounts 20%, stamps CREVYR to prevent re-run compounding.
OEARCHIV (RPGLE)
Annual: one turnover-archive OESHIS row per customer; year-end reset closes fully-settled AR items ('C').
OEARRPT (ILE COBOL)
AR control report over OEAROP: RAISED / OPEN / ITEMS / OVERDUE totals proving the sub-ledger reconciles.
OEREFLD (RPGLE)
Seeds 4 customers, 5 products, 4 volume breaks.

F.2 Interactive programs

OEMENU (RPGLE / OEMENUD)
Main menu; option 1 CALLs OECUSTIQ, option 2 CALLs OEORDIQ; F3 exits.
OECUSTIQ (RPGLE / OECUSTD)
Plain customer inquiry: CHAIN OECUST, shows master + derived available credit (limit−balance). Inquiry-only.
OEORDIQ (RPGLE / OEORDD)
Order inquiry with an SFL/SFLCTL line subfile; clears + re-loads each enquiry, drives SFLDSP off an indicator so a miss shows an empty subfile. Inquiry-only.

F.3 Idempotency & the derived sales-history keys

Re-runnability is achieved without a control table: each posting program computes a stable HSEQ from a business key in a disjoint numeric range and guards it with CHAIN(EN) (chain, no-lock, return found/not-found), so a repeat is refused.

ProgramKey derivationGuard
OEINVGEN10000000 + order digits (and INVNO = IN0+order digits)CHAIN(EN) OEINVHR / OESHISR
OECASHAP20000000 + receipt digitsCHAIN(EN) OESHISR + RCSTAT flip
OEBOREL30000000 + order digits × 100 + lineCHAIN(EN) OESHISR (per line)
OEARCHIV50000000 + customer digitsCHAIN(EN) OESHISR (per customer)
OECRREV(no history row) — guarded by the CREVYR fieldskip if CREVYR = review year
OEGLPSTGLSEQ continued from MAX(GLSEQ); posts movement since last closeSQLCOD checked; PK on GLSEQ

F.4 The order-line re-CHAIN idiom (fixed-form)

Several programs read OEORDL with a READE loop, then read other files (OEITEM, OEPRIC) whose I/O moves the update-file cursor. To update the line they re-CHAIN it by its composite key using a KLIST (WORD+WSEQ) before UPDATE — and likewise re-CHAIN the header (WORD) before updating it. This is why the source carries LKEY/ARKEY KLISTs and comments such as "re-CHAIN the line: the item update moved this file's cursor". It is native-I/O discipline, not a bug.

F.5 Status-code reference

FieldValueMeaning
OSTAT (order)N / H / A / B / I / XNew / held / approved-allocated / back-ordered / invoiced / cancelled.
OHOLDR (hold reason)CL / MH / CSCredit-limit exceeded / manual hold / customer not active.
LSTAT (line)O / A / B / I / XOpen / allocated / back-order / invoiced / cancelled.
INVSTAT (invoice)O / POpen / paid.
ARSTAT (AR item)O / P / COpen / settled / closed (year-end).
RCSTAT (receipt)U / A / PUnapplied / fully applied / part-applied.
ARAGE (bucket)0 / 1 / 2 / 3Current / 1–30 / 31–60 / 61+ days overdue.
TAXCDS / ZStandard-rated (8%) / zero-rated.

G. Glossary ↑ top

Allocation
Reserving free stock (on-hand less already-allocated) against an approved order line. Allocation moves ALLOC, not ONHAND; the on-hand is relieved only when the line is invoiced/shipped.
Available credit
The figure the credit check reasons about: CRLIMIT − BALANCE. An order total over this is held with reason CL.
Back-order
The unshippable remainder of an order line (LQTY − LALLOC), carried as status 'B' until the weekly sweep (OEBOREL) can fill it from arrived stock.
Composite key
A multi-field key (OEORDL's ORDNO+LSEQ, OEAROP's CUSTNO+INVNO). Re-CHAINing such a record needs a KLIST, not a single-field CHAIN.
Cash application
Matching a receipt to an AR open item and reducing both the open balance and the customer balance by what is applied, taking only what is owed on an over-payment.
Credit hold
Blocking an order from allocation/invoicing because it breaches credit or belongs to a held/inactive customer (OSTAT='H', reason CL/MH/CS). The gate OEALLOC honours.
Derived key
An invoice/history/sequence key computed from a stable business key so a re-run regenerates the same key and a CHAIN(EN) guard refuses the duplicate — the app's idempotency mechanism.
Idempotent
Safe to run again with the same result. The whole daily chain, the weekly sweep, ageing, the GL post and the annual cycle are all engineered to be re-runnable (F.3).
Order book
The un-invoiced orders (held, approved, back-ordered) — what OEBOOK reports.
SBMJOB
Submit Job — the IBM i command that queues a program as a batch job, e.g. SBMJOB CMD(CALL PGM(ORDERIS/OEDAILY)).
Subfile
A 5250 display construct listing many rows on one screen (DDS SFL/SFLCTL). OEORDIQ's order-line list is a subfile with SFLPAG(5)/SFLSIZ(20) paging.
Terms
A customer's payment window in days (CTERMS); the AR due date is invoice date + terms.
30/360 serial
The ageing convention: each month counts 30 days, so a YYYYMMDD collapses to ((yyyy*12)+mm)*30+dd; days overdue = serial(run) − serial(due).
Volume break
A quantity threshold (OEPRIC) at which a discount percent applies; OEPRICE keeps the biggest break the line quantity earns.
WAC / ALLL
Not modelled here — ORDERIS/i is an order-to-cash (sales/AR) application, not a lending book; its close produces an AR ageing and a revenue GL post rather than a portfolio valuation.