DEPOT/i is a distribution-centre warehouse management application: a warehouse and
bin/location master, stock held by (item, location, lot), inbound receiving and put-away, wave pick
release and pick confirmation, despatch, cycle counting, bin-to-bin replenishment, stock valuation and a
monthly GL post. Its central discipline is that stock only ever moves — a put-away, a pick
and a replenishment each take quantity out of one bin and put the same quantity into another, so the sum
of on-hand across all bins for an item is conserved; only receiving (from outside), despatch (to outside)
and a count variance change that total, and each writes a signed movement-ledger row that explains the
delta exactly. This manual is the reference for the operator who runs the online screens and the periodic
job cycles, and for the developer maintaining the application. It is grounded entirely in the committed
source (wms-app/src/sources.mjs, seed.mjs, and the
test/wh_*.mjs drivers). Everything runs in library DEPOT.
DEPOT/i runs the full physical flow of a distribution centre:
The one property the whole application is built around, and the one the test suites assert at every
step, is that a warehouse move conserves stock. Formally: for any item, the sum of
WHSTK.SQTY over all bins is unchanged by a put-away, a pick, a pick-confirm or a
replenishment — each takes quantity from one bin and gives the same quantity to another. Exactly
three events change the site total, and each writes a signed row into the movement ledger
WHMOVE that accounts for the delta:
MFROM (the dock) and
MTO (the bin); the goods were already booked to the dock, so put-away is internal and
the total does not change. A genuine external receipt into the site is the inbound booking
that placed stock on the dock in the first place.'D' row with MQTY negative, MFROM
the staging lane and MTO blank (it left the building). This is the one daily step that
legitimately reduces the total.'A' (cycle-count) or 'Y' (physical) row
with a signed MQTY and both MFROM and MTO blank:
nothing moved, the book was wrong.The COBOL reconciliation report WHMOVRP is the arbiter: it sums the ledger by type and
shows the internal moves netting the site's flows, so any cycle's effect on the balance is provable
after the fact.
DAILY (WHDAILY) WEEKLY (WHWEEK) MONTHLY (WHMONTH) ANNUAL (WHYEAR)
------------------- --------------- ----------------- ---------------
WHPUTWY receive/put-away WHREPL replenish WHCNTPS count post WHPHYS physical
WHWAVE pick release WHSLOW ABC re-rank WHVALUE valuation WHRESLT re-slot
WHPCKPR print pick list WHMOVRP reconcile WHGLPST GL post WHVALUE valuation
WHPKCFM pick confirm WHMOVRP reconcile WHMOVRP reconcile
WHDSPCH despatch
ONLINE (WHMENU)
1 -> WHSTKIQ stock inquiry (plain DSPF over WHSTK/WHITEM/WHLOC)
2 -> WHPCKIQ wave pick-list inquiry (SUBFILE over WHPICK)
every posting program --writes--> WHMOVE (movement ledger, one accumulating history)
WHRCPT --> WHSTK <-- WHORD/WHORDL --> WHPICK --> WHSTK(staging) --> out
^ \ WHGLFEED (SQL GL feed)
WHLOC ----+ +-- WHSTKLF (by-location LF) WHPCKLF (by-status pick LF)
WHITEM ---+
A daily flow runs: WHPUTWY moves receipts off the dock into bins → WHWAVE
reserves pick-face stock against open orders and writes pick lines → WHPCKPR prints the
floor's pick list → WHPKCFM moves the picked stock to the staging lane and releases the
reservation → WHDSPCH ships the staged stock and posts the negative ledger rows. Every
quantity change writes a WHMOVE row.
| Object | Type | Role |
|---|---|---|
| WHLOC | PF | Location (bin) master — type/zone/capacity/velocity. |
| WHITEM | PF | Item master — UOM, case pack, min/max, cost, ABC. |
| WHSTK | PF | Stock by (item, location, lot) — the heart of the app. |
| WHSTKLF | LF | Stock keyed LOCID-first (by-location access path). |
| WHRCPT | PF | Inbound receipt lines. |
| WHORD / WHORDL | PF | Despatch order header / lines. |
| WHPICK | PF | Wave pick instructions. |
| WHPCKLF | LF | Picks keyed PSTAT-first (by-status access path). |
| WHMOVE | PF | Movement ledger — the durable audit trail. |
| WHCNT | PF | Cycle-count sheets. |
| WHCARR | PF | Carrier master. |
| WHGLFEED | SQL table | GL feed the monthly close posts into (+ index WHGLFACC). |
| WHSTKD / WHPCKD / WHMENUD | DSPF | Stock inquiry / wave subfile / menu display files. |
| WHPCKP | PRTF | Printed pick list. |
| WHREFLD | RPGLE | Seeds locations, items and carriers. |
| WHPUTWY / WHWAVE / WHPCKPR / WHPKCFM / WHDSPCH | RPGLE | The daily receive-pick-ship chain. |
| WHREPL / WHSLOW | RPGLE | Weekly replenishment / slow-mover re-rank. |
| WHCNTPS / WHVALUE / WHPHYS / WHRESLT | RPGLE | Count post / valuation / physical count / re-slot. |
| WHGLPST | SQLRPGLE | Monthly GL post (embedded SQL into WHGLFEED). |
| WHSTKIQ / WHPCKIQ / WHMENU | RPGLE | Interactive inquiry / subfile / menu programs. |
| WHMOVRP | CBLLE | ILE COBOL ledger reconciliation report. |
| WHSETUP | CLP | Create every object & compile every program. |
| WHDAILY / WHWEEK / WHMONTH / WHYEAR | CLP | The four job cycles. |
The full catalogue is 10 physical files + 2 logical files + 3 display files + 1 printer file + 1 SQL table (and its index), driven by 16 RPG programs, 1 ILE COBOL program and 5 CL programs. Sections D and F expand each.
DEPOT/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, from the WHMENU menu, or
from a JOBQ/scheduler for the batch jobs. Before invoking anything, the job's library list must include
DEPOT — the tested jobs run with LIBL = QSYS QGPL DEPOT QTEMP and
CURLIB = DEPOT. The one-time WHSETUP creates the objects and compiles the
programs; WHREFLD seeds the reference data.
| To do this | Type on the command line |
|---|---|
| Build the library (objects + programs) | CALL DEPOT/WHSETUP |
| Seed reference data (7 locations, 5 items, 2 carriers) | CALL DEPOT/WHREFLD |
| Open the main menu | CALL DEPOT/WHMENU |
| Open stock inquiry directly | CALL DEPOT/WHSTKIQ |
| Open the wave pick-list inquiry directly | CALL DEPOT/WHPCKIQ |
| Run the daily receive-pick-ship cycle | CALL DEPOT/WHDAILY (or SBMJOB it) |
| Run the weekly cycle | CALL DEPOT/WHWEEK |
| Run the monthly cycle | CALL DEPOT/WHMONTH |
| Run the annual cycle | CALL DEPOT/WHYEAR |
The batch drivers take no CALL parameters; a scheduled submission is a bare CALL.
Only WHMENU, WHSTKIQ and WHPCKIQ are interactive; every batch
program runs to completion and DSPLYs a one-line summary per step.
20260801, the weekly replenishment 20260807, the
monthly close 20260831, and the annual run 20261231 (and WHGLPST
posts batch 202608). To move the app to a different processing date you change the source and
recompile; there is no operator date parameter or control table to advance.WHMENU (over WHMENUD) is a plain menu: option 1 CALLs
WHSTKIQ, option 2 CALLs WHPCKIQ, any other non-blank value shows
“Invalid option.”; F3 exits. Both inquiries are read-only — the
online layer inspects stock and picks, it does not post movements.
Key an item number and a location; the screen chains the item master (description, unit cost) and the
location master (bin type, zone), then walks that item's stock rows for the named bin and shows the
on-hand, allocated and the derived pickable figure (SQTY − SALLOC).
| Field | Type (DDS) | Shows |
|---|---|---|
| IITEM | 8A input/output | Item number to look up. |
| ILOC | 10A input/output | Location (bin) to look up. |
| DDESC / DCOST | 30A / 14A output | Item description / unit cost (from WHITEM). |
| DLTYPE / DZONE | 1A / 2A output | Bin type / zone (from WHLOC). |
| DLOT | 8A output | Lot in that bin. |
| DQTY / DALLOC / DPICK | 14A output | On hand / allocated / pickable (derived). |
| DMSG | 50A output | “Stock found.” / “No stock in that bin.” / “Item not found.” |
The app's subfile screen. Key a wave number; the program clears the subfile and reloads it from
WHPICK for that wave (record PSFL under control PCTL,
SFLPAG(5) per page, SFLSIZ(20), ROLLUP/ROLLDOWN paging
and SFLEND(*MORE)). It totals the pick lines, units and open-line count into the header
fields.
| Field | Type (DDS) | Shows |
|---|---|---|
| IWAVE | 5Y0 input/output | Wave number to display. |
| SSEQ | 4Y0 output | Pick walk sequence (PSEQ). |
| SITEM / SFROM | 8A / 10A output | Item / source bin. |
| SQTYD / SSTAT | 12A / 1A output | Pick quantity / status (O open, C confirmed, S short, X cancelled). |
| SORD | 8A output | Order number the pick belongs to. |
| DWCNT / DWQTY / DWOPEN | 12A output | Header totals: pick lines / total units / open lines. |
SFLCLR indicator (*IN31) on after the EXFMT
and before the load loop, so a re-enquiry never shows the previous wave's rows. See F.5 for the
one-column-left indicator placement this DDS uses so the emulator's parser reads the conditioning
indicators correctly.Honest statement: DEPOT/i does not model a true four-eyes maker–checker / separate-authorization workflow, and it has no user-level security or approval gate in the application code: a batch step posts its movements the moment it runs, and the online screens are read-only. The manual documents the control model the application does have:
WHSTK writes a durable ledger
row naming the type, quantity, both bins (where applicable), a business reference and a memo. It is
the after-the-fact accountability trail and the arbiter of the conservation invariant.CHAIN(EN):
a re-run regenerates the same key and the guard refuses it rather than double-posting. This is what
makes the whole daily chain safely re-runnable (the tests assert the ledger gains no rows on a
second WHDAILY).WHPUTWY only puts away receipts in RSTAT='O' (then flips to 'P');
WHWAVE only releases orders in OSTAT='O'; WHPKCFM only confirms
picks in PSTAT='O'; WHDSPCH only ships orders whose lines are all
fully picked; WHCNTPS only posts count lines in CSTAT='O'.if sqlcod = 0), so a refused duplicate never inflates the row count
— the feed's SUM(DR) = SUM(CR).In sum, the control posture is durable movement audit + stable-key idempotency + status/state gating + capacity/policy enforcement, rather than a segregation-of-duties approval workflow or a security model.
DEPOT/i's work runs as four periodic cycles, each packaged as a CL program that adds
DEPOT to the library list and CALLs its steps in order: a daily receive-pick-ship
chain, a weekly replenishment + slow-mover review, a monthly count-variance close +
valuation + GL post, and an annual wall-to-wall physical inventory + pick-face re-slot. Every batch
program takes no CALL parameters and stamps hard-coded processing dates (see B.1).
-- run a cycle interactively, or submit it as a batch job
CALL DEPOT/WHDAILY
SBMJOB CMD(CALL PGM(DEPOT/WHDAILY)) JOB(WHDAILY)
| Program | Cycle | Purpose | Files touched | DSPLY summary |
|---|---|---|---|---|
| WHPUTWY | Daily | Receive & put away open receipt lines. | WHRCPT, WHITEM, WHLOC, WHSTK, WHSTKLF, WHMOVE | PUTAWAY=/SKIP=/REJECT= |
| WHWAVE | Daily | Release open orders into a pick wave (FEFO, pick faces only). | WHORD, WHORDL, WHSTK, WHLOC, WHPICK | WAVE=/PICKS=/SHORT=/SKIP= |
| WHPCKPR | Daily | Print the wave pick list (PRTF, page overflow). | WHPICK, WHPCKP | LINES=/UNITS= |
| WHPKCFM | Daily | Confirm open picks: pick face → staging lane. | WHPICK, WHSTK, WHORDL, WHMOVE | CONFIRMED=/UNITS=/SKIP= |
| WHDSPCH | Daily | Despatch fully-picked orders off the staging lane. | WHORD, WHORDL, WHSTK, WHMOVE | ORDERS=/LINES=/SKIP= |
| WHREPL | Weekly | Replenish pick faces below min from reserve (whole case packs). | WHITEM, WHSTK, WHLOC, WHMOVE | MOVED=/SKIP= |
| WHSLOW | Weekly | Re-rank each item's ABC class by shipped throughput. | WHITEM, WHMOVE | A=/B=/C= |
| WHCNTPS | Monthly | Post cycle-count variances; correct the book. | WHCNT, WHSTK, WHMOVE | ADJUSTED=/NET=/SKIP= |
| WHVALUE | Monthly/Annual | Value stock at unit cost, split by location type. | WHSTK, WHITEM, WHLOC | ROWS=/TOTAL=/RESERVE=/FORWARD=/STAGED= |
| WHGLPST | Monthly | Post the movement ledger to the SQL GL feed as balanced pairs. | WHMOVE, WHITEM, WHGLFEED (SQL) | BATCH=/ROWS= |
| WHPHYS | Annual | Full physical count (reserve bins count 1 short); correct book. | WHSTK, WHLOC, WHMOVE | ADJUSTED=/NET=/SKIP= |
| WHRESLT | Annual | Stamp item velocity class onto pick-face slots (upgrade only). | WHITEM, WHSTK, WHLOC, WHMOVE | RESLOTTED=/SKIP= |
| WHMOVRP | W/M/A | ILE COBOL ledger reconciliation report. | WHMOVE | PUTAWAY/INTERNAL/SHIPPED/ADJUSTED/MOVES |
WHPUTWY walks the open receipt lines. Put-away policy is deterministic: honour an explicit
RPUTLOC; else send a hazmat item to C-09-01 (the segregated rack) and everything
else to B-05-01 (the default reserve). It sums what is already in the target bin through the
location-keyed WHSTKLF path and refuses to overfill (LCAP); it takes the
quantity off the dock, adds it into the bin (creating the row if new), writes a 'P' ledger
row naming both bins, and flips the receipt to RSTAT='P'. WHWAVE allocates each open
order's lines against forward-pick-face stock only, reserving via SALLOC (never moving
SQTY), and writes one pick row per source in aisle-walk (LSEQ) order.
WHPCKPR prints that wave. WHPKCFM confirms each open pick — SQTY falls in
the pick face and rises in the staging lane by the same amount, SALLOC is released, a
'K' ledger row is written, the order line's OPICKQ rolls up. WHDSPCH
ships every order whose lines are all fully picked: it draws the quantity off the staging lane, writes a
negative 'D' ledger row (MTO blank), and rolls the header to OSTAT='D'.
Expected DSPLY (the wh_daily scenario: receipt R0000101 + order OR000501): WHPUTWY PUTAWAY=2 SKIP=0 REJECT=0 WHWAVE WAVE=8001 PICKS=2 SHORT=0 SKIP=0 WHPCKPR LINES=2 UNITS=50 WHPKCFM CONFIRMED=2 UNITS=50 SKIP=0 WHDSPCH ORDERS=1 LINES=2 SKIP=0 WG total 840 -> 810, GZ 250 -> 230
WHREPL walks the item master. For each active item it sums what sits in forward pick faces; if
that total is below IMINQ it computes the gap to IMAXQ, rounds it up to a whole
case pack (IPKQTY — a picker moves cartons), finds a reserve bin holding that lot with
enough free stock, and moves the quantity down (out of reserve, into the pick face), writing a
'T' ledger row naming both bins. It is a pure internal move — the total is unchanged.
WHSLOW re-ranks each item's ABC class by units actually shipped ('D' ledger rows):
≥40 → A, ≥10 → B, else C (slow mover). WHMOVRP
reconciles the ledger.
Expected DSPLY (the wh_cycles weekly scenario): WHREPL MOVED=2 SKIP=... WG face 20+108=128 (reserve 500-108=392); WHSLOW A=1 B=1 C=... SP face 10+250=260 (reserve 300-250=50) WHMOVRP INTERNAL 358.00 108 + 250 units moved internally WHMOVRP SHIPPED -57.00 -45 + -12 shipped
WHCNTPS posts each open count sheet line: it compares the counted quantity against the book
quantity in that bin now, and if they differ corrects SQTY and writes a signed 'A'
ledger row (both bins blank — nothing moved). A zero-variance line is left open, not falsely posted.
WHVALUE values every stock row at the item's unit cost and reports the total split by location
type (reserve / forward / staged — staged stock is already committed revenue). WHGLPST totals
the ledger by type, values it at cost, and posts balanced DR/CR pairs into WHGLFEED, continuing
the GLSEQ sequence and posting only the movement since the last close. WHMOVRP
reconciles.
Expected figures (the wh_cycles monthly scenario): WHCNTPS ADJUSTED=1 NET=-3 counted bin 128 -> 125 WHVALUE RESERVE=6209.50 FORWARD=1832.50 STAGED=... GL: 5000-CGS (CGS) 445.50 45x3.5000 + 12x24.0000 5900-SHR (shrink) 10.50 3 units short x 3.5000 1400-INV credited 456.00 445.50 shipped + 10.50 shrunk; SUM(DR)=SUM(CR)
WHPHYS counts the building. Its deterministic convention: every stocked reserve bin counts
1 unit short (pallet-face shrinkage), every other bin clean; it corrects the book and writes a signed
'Y' ledger row (both bins blank). WHRESLT stamps each item's velocity class
(IABC) onto the pick-face bins holding it, but only ever upgrades a slot (A beats B
beats C) so a shared bay is deterministic and re-runs are stable; it writes an 'S' ledger row
per re-slotted item. WHVALUE re-values, WHMOVRP reconciles.
Expected DSPLY (the wh_cycles annual scenario): WHPHYS ADJUSTED=3 NET=-3 3 reserve bins each -1 (392->391, 200->199, 50->49) WHRESLT RESLOTTED=2 SKIP=... pick faces re-slotted to the faster class
WHPCKPR is a
report and can print any time after the wave.'D' rows.WHRESLT uses are set by WHSLOW in the
weekly cycle, which in turn depends on the daily despatch history — run the dailies and weeklies
of the year before the annual re-slot.All files are in library DEPOT, grounded in the DDS/SQL members of
sources.mjs. Dates are stored as zoned/packed integers in YYYYMMDD form; money
is DECIMAL (unit cost is 11P4, to fractions of a cent). Field types are shown in DDS
notation: A=alphanumeric, P=packed decimal, S=zoned decimal.
| Field | Type | Meaning |
|---|---|---|
| WHSE | 3A | Warehouse code (seeded DC1) (K). |
| LOCID | 10A | Bin coordinate, e.g. A-01-01 (K). |
| LDESC | 25A | Bin description. |
| LTYPE | 1A | R reserve, F forward pick face, S staging/despatch, D dock/receiving. |
| LZONE | 2A | Zone (DK/PF/RS/SH). |
| LCAP | 9P2 | Capacity in units; put-away refuses to overfill. |
| LSEQ | 5S0 | Pick-walk sequence (pickers walk in LSEQ order). |
| LVELOC | 1A | Velocity class (A/B/C) the annual re-slot stamps. |
| LSTAT | 1A | Status (A active). |
Seeded set: 1 dock (DOCK-IN-01), 2 forward pick faces (A-01-01
LSEQ 100, A-01-02 LSEQ 110), 3 reserve racks (B-05-01/02, C-09-01),
1 staging lane (SHIP-LN-01). Pick faces walk before reserve racks.
| Field | Type | Meaning |
|---|---|---|
| ITEMNO | 8A | Item number (K), e.g. WG100001. |
| IDESC | 30A | Description. |
| IUOM | 3A | Stocking unit (EA). |
| IPKQTY | 9P2 | Case pack — the granularity replenishment moves in. |
| IMINQ / IMAXQ | 9P2 | Forward-pick min/max (drives weekly replenishment). |
| ICOST | 11P4 | Unit cost, to fractions of a cent. |
| IHAZMAT | 1A | Y/N — a Y is segregated to C-09-01 on put-away. |
| IABC | 1A | Velocity class (re-ranked weekly by shipped throughput). |
| ISTAT | 1A | Status (A active). |
The heart of the system. The composite key is why the same item lives in many bins and the same bin holds several lots. Pickable = SQTY − SALLOC.
| Field | Type | Meaning |
|---|---|---|
| ITEMNO / LOCID / LOTNO | 8A / 10A / 8A | Item + bin + lot (composite K). |
| SQTY | 9P2 | Physical on-hand in this bin. |
| SALLOC | 9P2 | Quantity a released wave has claimed but not yet picked. |
| SEXPDT | 8S0 | Lot expiry date (the FEFO pick order uses it). |
| SLSTDT | 8S0 | Last-movement date stamped by the posting programs. |
| SSTAT | 1A | Status (A active). |
WHSTKLF is a logical file over WHSTK keyed LOCID-first then ITEMNO,
LOTNO — the by-location access path (“what is in this bin?”), non-unique on LOCID by design.
| Field | Type | Meaning |
|---|---|---|
| RCPTNO / RSEQ | 8A / 3S0 | Receipt + line number (K). |
| ITEMNO / LOTNO | 8A / 8A | Item / lot received. |
| RQTY | 9P2 | Quantity received. |
| RDOCK | 10A | Dock the carrier dropped it in. |
| RPUTLOC | 10A | Explicit put-away bin (blank = policy decides). |
| REXPDT | 8S0 | Lot expiry. |
| RSTAT | 1A | O open, P put away, X cancelled. |
| Field | Type | Meaning |
|---|---|---|
| ORDNO | 8A | Order number (K on both). |
| CUSTNO / CUSTNM | 6A / 25A | Customer number / name (header). |
| ODATE / OSHIPDT | 8S0 | Order / ship date (header). |
| OWAVE | 5S0 | Wave the order was released into (0 while open) (header). |
| OSTAT | 1A | O open, R released, P picked, D despatched, X cancelled (header). |
| OCARR | 4A | Carrier code (header). |
| OLSEQ | 3S0 | Line number (line K). |
| OQTY / OPICKQ / OSHIPQ | 9P2 | Ordered / picked / shipped quantity (line). |
| OLSTAT | 1A | O open, R released, P picked, D despatched (line). |
| Field | Type | Meaning |
|---|---|---|
| WAVENO / PSEQ | 5S0 / 5S0 | Wave + pick walk sequence (K). |
| ORDNO / OLSEQ | 8A / 3S0 | Order + line this pick serves. |
| ITEMNO / LOTNO | 8A / 8A | Item / lot to pick. |
| PFROM / PTO | 10A / 10A | Source bin / staging lane destination. |
| PQTY / PCONFQ | 9P2 | Instructed / confirmed quantity. |
| PSTAT | 1A | O open, C confirmed, S short, X cancelled. |
WHPCKLF is a logical file over WHPICK keyed PSTAT-first — the
by-status access path (read only the open picks to confirm, the confirmed ones to despatch).
The durable audit trail and the arbiter of conservation. Every WHSTK quantity change writes one row.
MSEQ is a stable, disjoint-per-program key (see F.2), so all programs accumulate into one
history and re-runs are refused.
| Field | Type | Meaning |
|---|---|---|
| MSEQ | 8S0 | Movement sequence (K, unique, derived from a business key). |
| ITEMNO / LOTNO | 8A / 8A | Item / lot moved. |
| MTYPE | 1A | P put-away, K pick, D despatch, T replenish, A cycle-count, Y physical, S re-slot. |
| MDT | 8S0 | Movement date (YYYYMMDD). |
| MQTY | 9P2 | Signed quantity (negative for despatch; signed for variances). |
| MFROM / MTO | 10A / 10A | The two sides of the move; blank where not applicable. |
| MREF | 8A | Business reference (receipt / order / literal like REPLEN). |
| MMEMO | 25A | Human-readable memo. |
| Field | Type | Meaning |
|---|---|---|
| CSHEET / CSEQ | 6S0 / 3S0 | Count sheet + line (K). |
| ITEMNO / LOCID / LOTNO | 8A / 10A / 8A | What was counted, and where. |
| CBOOK | 9P2 | Book quantity captured (the before-image, written at posting). |
| CCOUNT | 9P2 | Quantity the counter keyed. |
| CDT | 8S0 | Count date. |
| CSTAT | 1A | O open, P posted, X void. |
| Field | Type | Meaning |
|---|---|---|
| CARRCD | 4A | Carrier code (K), e.g. RDX1, PLT2. |
| CARRNM / CARRSVC | 25A / 10A | Carrier name / service level. |
| CARRSTA | 1A | Status (A active). |
| Field | Type | Meaning |
|---|---|---|
| GLSEQ | DECIMAL(8,0) | GL sequence (PK), continued across closes. |
| GLBATCH | DECIMAL(6,0) | Posting batch (YYYYMM). |
| ACCT | CHAR(9) | Account: 1400-INV, 2100-GRN, 5000-CGS, 5900-SHR. |
| DRCR | CHAR(1) | D debit / C credit. |
| AMT | DECIMAL(11,2) | Posting amount. |
| GLREF / GLDT | CHAR(8) / DECIMAL(8,0) | Reference / date. |
Index WHGLFACC on (ACCT, DRCR) supports the “posted-to-date”
sums WHGLPST reads to post only the incremental movement each close.
'P').'K'); then WHDSPCH ships and writes WHMOVE ('D').CALL DEPOT/WHSETUP then CALL DEPOT/WHREFLD; confirm
the “setup complete” banner and that WHREFLD reports LOCS=7 ITEMS=5 CARRIERS=2.WHRCPT (RSTAT=O) and the day's despatch orders into
WHORD/WHORDL (OSTAT=O).SBMJOB CMD(CALL PGM(DEPOT/WHDAILY)).WHSTKIQ / WHPCKIQ to inspect a bin
or a wave as questions arise.Pre-checks: confirm the job's library list includes DEPOT; confirm receipts are
RSTAT='O' and orders OSTAT='O' (anything else is skipped).
Post-checks after the daily cycle:
WHPUTWY PUTAWAY= equals your open receipt lines; REJECT= should be 0 (a
non-zero reject means a bin would overfill — the line is left open).WHWAVE PICKS= equals the order lines that found pick-face stock; SHORT=
counts lines that could not be fully allocated from pick faces.WHPKCFM UNITS= equals the picked total; the picked stock is now in SHIP-LN-01
and each pick face fell by exactly what was picked, with SALLOC back to 0.WHDSPCH LINES= equals the shipped lines; the staging lane is empty and the site total
fell by exactly the shipped quantity (the only step that reduces it).WHMOVE.MSEQ is unique — the durable audit trail holds (a regression guard the
tests verify).WHWEEK — replenish pick faces and re-rank
ABC. Confirm WHREPL MOVED= matches the items below their pick-face minimum and
WHMOVRP INTERNAL equals the replenished units (a pure internal move).WHCNT (CSTAT=O), then submit
WHMONTH. Confirm WHCNTPS ADJUSTED=/NET=, the WHVALUE
split, and that the GL feed is balanced.SUM(DR) must equal SUM(CR) and be non-zero; the feed row
count is even (every posting is a pair).WHYEAR — physical count, re-slot, re-value, reconcile.
Confirm the reserve bins each fell by 1 and the pick faces carry the re-slotted velocity class.SELECT ACCT, DRCR, SUM(AMT) FROM DEPOT.WHGLFEED GROUP BY ACCT, DRCR;
SELECT SUM(CASE WHEN DRCR='D' THEN AMT ELSE 0 END) AS DR,
SUM(CASE WHEN DRCR='C' THEN AMT ELSE 0 END) AS CR FROM DEPOT.WHGLFEED;
The site balance for an item is reconciled against the movement ledger. Opening on-hand plus every
non-internal ledger delta must equal the closing on-hand — internal moves (put-away
'P', pick 'K', replenish 'T', re-slot 'S') net to zero
across bins, so only despatch 'D' and count variances 'A'/'Y' change
the total.
SUM(SQTY) over all WHSTK bins for the item. In the wh_daily
scenario WG100001 opens at 840 and closes at 810 after shipping 30; GZ200001 opens 250, closes 230.SUM(MQTY) over the 'D'/'A'/'Y'
rows for the item. Despatch rows are negative and, for the wh_daily scenario, sum to exactly −50
(−30 WG, −20 GZ).opening + ledger delta = closing (840 + (−30) = 810).
The COBOL WHMOVRP proves the same at building level: internal P/K/T flows
net, external D shipped and A/Y adjusted are reported separately.5000-CGS equals shipped units ×
unit cost (445.50 in the wh_cycles month); shrinkage on 5900-SHR equals short units
× cost (10.50); inventory is credited for the sum (456.00).SELECT ITEMNO, SUM(SQTY) AS ONHAND FROM DEPOT.WHSTK GROUP BY ITEMNO;
SELECT ITEMNO, MTYPE, SUM(MQTY) FROM DEPOT.WHMOVE
WHERE MTYPE IN ('D','A','Y') GROUP BY ITEMNO, MTYPE;
Each program DSPLYs a one-line summary. Because every posting derives a stable, disjoint ledger key and
guards each write with CHAIN(EN), and because each step also gates on record status, the
cycles are safe to re-submit.
| Situation | Behaviour | Action |
|---|---|---|
| Daily chain fails partway | Put-away rows that posted are RSTAT='P'; the rest stay 'O'. | Re-submit WHDAILY: posted rows are skipped (stable key + status guard), the rest process. Idempotent. |
| Re-run WHPUTWY / WHWAVE / WHPKCFM / WHDSPCH | PUTAWAY=0 / PICKS=0 / CONFIRMED=0 / ORDERS=0; no double move. | Safe no-op — the ledger gains no rows and totals do not fall twice. |
| Put-away rejected (REJECT>0) | Target bin would overfill; the receipt line stays RSTAT='O'. | Direct it to a bin with room via RPUTLOC, or free capacity, then re-run. |
| Wave line short (SHORT>0) | Not enough pick-face stock; the order line is not marked released unless something was picked. | Run WHREPL to top up the pick face, then re-release. |
| Re-run WHREPL / WHCNTPS / WHPHYS / WHRESLT | MOVED=0 / ADJUSTED=0 / RESLOTTED=0. | Naturally idempotent for a fixed state — the stable key refuses a second post. |
| Re-run WHGLPST | Re-totals the whole ledger but posts only the incremental movement since the last close; a refused insert is not counted. | Safe — the sequence continues and the feed stays balanced (this was a fixed defect: see F.3). |
WHMOVE with both sides named
(or blank for a variance), and the COBOL WHMOVRP re-derives the flows from it, any cycle's
effect on the balance is fully reconstructable after the fact for reconciliation and recovery.The programs are fixed-form + free-form RPG IV (with one ILE COBOL and one SQLRPGLE), driving keyed
DISK files by CHAIN/READE/UPDATE/WRITE. All objects are in library DEPOT.
WHRCPT lines; decides the bin (explicit RPUTLOC, else hazmat
→ C-09-01 / else B-05-01); sums the target via the location-keyed
WHSTKLF and rejects an overfill; moves off the dock into the bin; writes a 'P'
ledger row; flips RSTAT='P'.LTYPE='F'),
reserving SALLOC without moving SQTY; writes one WHPICK row per
source keyed on a pseq that folds in the order digits, the location LSEQ and the order
line; marks the line released only if something was actually picked.SALLOC) and adds to the
staging lane (creating the row if new); writes a positive 'K' ledger row naming both
bins; rolls OPICKQ up and flips the line to P when fully picked.OLSTAT='P'; pass 2 draws each line's
quantity off the staging lane, writes a negative 'D' ledger row (MTO blank),
records OSHIPQ, and rolls the header to OSTAT='D'.'T' move), ABC re-rank by shipped throughput, count-variance post
('A'), value-by-location-type, physical count ('Y'), and upgrade-only
pick-face re-slot ('S').WHMOVE.MSEQ is UNIQUE and each program derives its key from a stable business key inside a
disjoint 10-million-wide band, so a re-run regenerates the same key and the CHAIN(EN) guard
refuses it — the mechanism that makes every cycle idempotent.
| Program | MTYPE | Key formula |
|---|---|---|
| WHPUTWY | P | 10000000 + receipt digits*100 + line |
| WHPKCFM | K | 20000000 + wave*1000 + pick seq |
| WHDSPCH | D | 30000000 + order digits*100 + line |
| WHREPL | T | 40000000 + item digits*100 + occurrence |
| WHCNTPS | A | 50000000 + count-sheet*100 + line |
| WHPHYS | Y | 60000000 + item digits*10 + bin ordinal |
| WHRESLT | S | 70000000 + item digits |
The monthly post totals the ledger by type, values it at unit cost, reads the posted-to-date sums from
WHGLFEED, and posts only the incremental movement as balanced pairs:
'P') — DEBIT 1400-INV (inventory), CREDIT
2100-GRN (goods-received-not-invoiced).'D') — DEBIT 5000-CGS (cost of goods sold), CREDIT
1400-INV. The ledger holds despatch negative, so the sign is flipped.'A') — a loss DEBITs 5900-SHR (shrinkage) /
CREDITs inventory; a gain reverses it. Shrinkage is carried as a signed net so a later gain unwinds an
earlier loss.'K', 'T', 'S') never touch the GL — the
goods never left the site.GLSEQ from it. Starting the sequence at 1 made month 2 re-derive
month 1's keys; the inserts were correctly refused, but the return code was not checked, so the job reported
success while the GL feed silently stopped tracking the ledger from month two on. The fix continues the
sequence from MAX(GLSEQ), posts only the incremental movement (against the posted-to-date sums),
and counts a row only when sqlcod = 0.WHSTK is keyed ITEM-first; a capacity check that must sum a
bin's contents therefore uses WHSTKLF (LOCID-first). Reading the base PF with a
bare location value would position on the leading ITEMNO key and walk the wrong rows — a fixed
defect that had let an over-capacity put-away through.READE loop over a file followed by a
CHAIN/UPDATE to that same file moves the cursor; the programs
re-CHAIN (or SETGT) before the next read. Where the intervening CHAIN is to a
different file (e.g. WHLOC while looping WHSTK) the source notes no re-position is needed.WHWAVE reserves SALLOC only after
the idempotency guard confirms a new pick line — a fixed defect had raised the reservation first,
stranding stock against an order with no pick row.Two accommodations are documented in the source so the app behaves correctly on the emulator:
N31's condition and mis-reading 31). The
SFLDSP/SFLDSPCTL/SFLCLR indicators are therefore written one
column left of the standard position; the keyword stays in its normal column. Operationally the subfile
displays and clears exactly as described in B.2.SFLCLR via *IN31) sits
after the EXFMT and before the reload, so a re-enquiry never wipes rows before they can be
shown.A fast (≥40 units shipped), B (≥10),
C slow. Re-ranked weekly by WHSLOW from shipped ledger rows; stamped onto
pick-face slots annually by WHRESLT.SUM(SQTY) over all bins for an item is
unchanged by put-away, pick, pick-confirm and replenishment. Only receiving, despatch and count
variances change it, each with a signed ledger row.WHCNTPS, 'A') counts
selected sheets monthly; a physical count (WHPHYS, 'Y') counts the whole
building annually. Both write a variance row with no bins named.LTYPE='D') is inbound-only, the staging lane
(LTYPE='S') outbound-only. Stock is booked to the dock on receipt and leaves the site from
the staging lane on despatch.SEXPDT.LTYPE='F') is the small, hand-pickable bin picking draws from; a
reserve (LTYPE='R') is bulk pallet storage, not hand-pickable, that replenishes the pick
face.MSEQ and the CHAIN(EN) guard
refuses the duplicate.SQTY − SALLOC. Shown on the stock
inquiry.SBMJOB CMD(CALL PGM(DEPOT/WHDAILY))).WHPCKIQ's wave
pick list is a subfile; the operator keys a wave and the rows reload.WHWAVE), sequenced in aisle-walk
(LSEQ) order so a picker walks the aisle once.