HOSTEL/i is a hotel front-desk and folio-management application: reservation capture and
room allocation by type, check-in, a nightly room+tax posting (the night audit), incidental and payment
application, check-out with settlement, weekly housekeeping turnover and no-show release, a monthly
occupancy/revenue report and a room-revenue/tax GL feed, and a year-end folio archive. The application is
a classic IBM i estate app: RPG IV programs over keyed DB2 for i physical and logical files, one ILE COBOL
control report, DDS display and printer files, embedded SQL for the GL distribution, and CL job cycles.
This manual is the reference for the operator who runs the online screens and the four periodic cycles,
and for the developer maintaining the application. It is grounded entirely in the committed source
(hotel-app/src/sources.mjs, src/seed.mjs, and the test/ht_*.mjs
drivers). Everything runs in library HOSTEL.
HOSTEL/i services the full life of a hotel stay, from reservation to settled folio to year-end archive:
HOSTEL/i is a conventional record-level-access RPG estate app, not a two-layer SQL-PL design: business
logic lives in the RPG programs, which read and update keyed DB2 files directly (CHAIN / READ / READE /
UPDATE / WRITE). Embedded SQL appears in exactly one place — HTGLPST, the GL post —
and one ILE COBOL program, HTAUDRPT, produces a folio control report. The whole estate is
built and compiled by one CL setup program (HTSETUP) and driven by four CL job cycles
(HTDAILY, HTWEEK, HTMONTH, HTYEAR).
The heart of the application is the reservation status model on HTRESV.RSTAT, which
every program keys its behaviour off:
| RSTAT | Meaning | Set by |
|---|---|---|
| N | New — captured, room type requested, no room yet. | Front desk (reservation write). |
| W | Waitlisted — no room of the type was free at capture. | HTRESERV. |
| B | Booked — a specific room assigned, arrival pending. | HTRESERV. |
| I | Checked in — guest in-house, folio open. | HTCHKIN. |
| O | Checked out — stay settled and closed. | HTCHKOUT. |
| X | Cancelled. | Front desk. |
| S | No-show — past arrival, never checked in. | HTNOSHOW. |
A parallel room status on HTROOM.RSTAT drives availability: V
vacant-clean (sellable), O occupied (taken off the pool at booking), D
vacant-dirty (checked out, needs housekeeping before resale), X out-of-order (never
allocated). The "stamp it once, trust the stamp" invariant used across the estate applies here to
the rate: RATELOCK captures the room-type rate at booking so a later rate change never
reprices a guest already holding a reservation.
ONLINE BATCH CYCLES (CL job streams)
------ ----------------------------
HTMENU (5250) HTDAILY --> HTRESERV (allocate room by type)
opt 1 -> HTRESVIQ HTCHKIN (check in arrivals + night 1)
opt 2 -> HTFOLIQ (SFL) HTNAUDIT (post each further night room+tax)
HTINCTAL (accrue F&B / minibar lines)
HTPAYAPL (apply PY payment lines)
HTCHKOUT (settle + release room dirty)
HTWEEK --> HTHSKP (dirty -> clean)
HTNOSHOW (release no-show rooms)
HTMONTH --> HTOCCRPT (occupancy/revenue printer report)
HTGLPST (room-rev/tax GL post, embedded SQL)
HTAUDRPT (ILE COBOL folio control report)
HTYEAR --> HTARCHIV (folio archive + counter reset)
HTAUDRPT
HTRESV (reservation header, RBAL mirror) <----writes---- every posting program
| \ HTFOLIO (one row per charge/payment line)
| +--> HTROOM (V/O/D/X availability) HTGLDIST (SQL GL distribution, HTGLPST)
+------> HTRTYP (type rate) / HTGUEST (guest master)
A single processing event — say, one night's audit — flows: HTNAUDIT reads its
fixed run date → for each checked-in stay not yet audited today it posts a room line and a tax line to
HTFOLIO and raises HTRESV.RBAL by room+tax → the reservation header's
RBAL mirror then answers "what is owed" without re-summing the folio. The
RLAUDT stamp on the header makes a same-day re-run a no-op.
| Object | Type | Role |
|---|---|---|
| HTRTYP | PF | Room-type / rate master. |
| HTROOM | PF | Room master (availability by number). |
| HTROOMLF | LF | Rooms keyed by RTYPE (availability-by-type walk). |
| HTGUEST | PF | Guest master. |
| HTRESV | PF | Reservation header (the stay lifecycle + RBAL mirror). |
| HTRESVLF | LF | Reservations keyed by ARRDT (arrivals / no-show walk). |
| HTFOLIO | PF | Folio charge/payment lines (composite key RESVNO,FSEQ). |
| HTFOLLF | LF | Folio lines keyed by FCODE (revenue-by-department). |
| HTGLDIST | SQL table | Room-revenue/tax GL distribution (HTGLDACC index). |
| HTRESVD / HTFOLD / HTMENUD | DSPF | Inquiry, subfile-folio and menu display files. |
| HTOCCP | PRTF | Occupancy/revenue printer file. |
| HTREFLD | RPG | Seed reference data (types, rooms, guests). |
| HTRESERV | RPG | Reservation capture + room allocation. |
| HTCHKIN | RPG | Check-in + first night's room+tax. |
| HTNAUDIT | RPG | Night audit (each further night's room+tax). |
| HTINCTAL | RPG | Incidental (F&B/minibar) accrual. |
| HTPAYAPL | RPG | Payment application. |
| HTCHKOUT | RPG | Check-out + settlement + room release. |
| HTHSKP | RPG | Weekly housekeeping turnover sweep. |
| HTNOSHOW | RPG | Weekly no-show release sweep. |
| HTOCCRPT | RPG | Monthly occupancy/revenue report. |
| HTGLPST | SQLRPGLE | Monthly room-revenue/tax GL post. |
| HTARCHIV | RPG | Annual folio archive + counter reset. |
| HTRESVIQ / HTFOLIQ / HTMENU | RPG | Online inquiry, subfile-folio, menu. |
| HTAUDRPT | ILE COBOL | Folio control report (room/tax reconciliation). |
| HTSETUP | CL | Create every object & compile every program. |
| HTDAILY / HTWEEK / HTMONTH / HTYEAR | CL | The four job-cycle streams. |
The full catalogue is 5 physical files + 3 logical files + 1 SQL table (with index), 3 display files and 1 printer file, driven by 15 RPG programs, 1 ILE COBOL program and 5 CL programs. Sections D and F expand each.
HOSTEL/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 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 HOSTEL — the tested jobs run with
LIBL = QSYS QGPL HOSTEL QTEMP and CURLIB = HOSTEL.
| To do this | Type on the command line |
|---|---|
| Open the operator menu | CALL HOSTEL/HTMENU |
| Open the reservation inquiry directly | CALL HOSTEL/HTRESVIQ |
| Open the folio inquiry (subfile) directly | CALL HOSTEL/HTFOLIQ |
| Run the daily cycle | CALL HOSTEL/HTDAILY (or SBMJOB it) |
| Run the weekly cycle | CALL HOSTEL/HTWEEK |
| Run the monthly close | CALL HOSTEL/HTMONTH |
| Run the annual archive | CALL HOSTEL/HTYEAR |
| Build/compile the whole estate | CALL HOSTEL/HTSETUP |
| Load the seed reference data | CALL HOSTEL/HTREFLD |
The batch drivers take no CALL parameters. Only HTMENU, HTRESVIQ and
HTFOLIQ are interactive; every batch program runs to completion and DSPLYs a
one-line result (its counts) to the job log.
HOSTEL/i has three interactive programs. The menu (HTMENU / HTMENUD) is the
entry point; it CALLs one of the two inquiry programs by option and returns on F3.
The inquiry programs are read-only — they display reservation and folio data but do not post
or maintain it. All maintenance (reservations, incidentals, payments) is data-entry into the files plus the
batch cycle; see B.3.
HTRESVIQ (reservation inquiry).HTFOLIQ (folio inquiry with subfile).Invalid option. in the
message line (DMSG).CA03) ends the program; F3 inside a called inquiry returns
to the menu.A plain (non-subfile) screen. Key a reservation number and Enter; the program
CHAINs HTRESV and (for the guest name) HTGUEST, and renders the header plus the
locked rate and folio balance. An unknown number clears the detail and shows
Reservation not found.
| Field | Type (DDS) | Shows |
|---|---|---|
| IRESV | 8A input/output | Reservation number keyed in. |
| DGNAME | 30A output | Guest name (from HTGUEST). |
| DRTYPE / DROOM | 3A / 4A output | Room type and assigned room number. |
| DSTAT | 1A output | Reservation status (RSTAT). |
| DRATE | 14A output | Locked nightly rate (RATELOCK, edited). |
| DARR / DDEP | 10A output | Arrival / departure dates. |
| DBAL | 14A output | Folio balance from the RBAL mirror (edited). |
| DMSG | 50A output | Found / not-found message line. |
The app's subfile screen. DDS record FSFL under control record FCTL,
SFLPAG(5) per page, SFLSIZ(20), with ROLLUP/ROLLDOWN
paging keys and SFLEND(*MORE). Key a reservation number and Enter;
the program clears the subfile (*IN31 drives SFLCLR), CHAINs the header/guest, then
READEs every folio line for that reservation into the subfile and displays it. A subsequent enquiry clears
and reloads — a genuine clear-then-reload discipline so an unknown number does not redisplay the
previous stay's rows.
| Field | Type (DDS) | Shows |
|---|---|---|
| IRESV | 8A input/output | Reservation number keyed in. |
| DGNAME / DSTAT / DBAL | output | Header: guest, status, folio balance. |
| SSEQ | 3Y,0 output | Folio line sequence (FSEQ). |
| SCODE | 2A output | Charge code: RM/TX/FB/MB/PY/YE. |
| SDT | 10A output | Line date (FDT, edited). |
| SAMT | 12A output | Line amount (FAMT, edited; PY is negative). |
| SFST | 1A output | Line status: O open, S settled, A accrued/applied. |
N31/N32 so it is shown only once
at least one row has actually loaded — the program source notes this prevents an unknown reservation
number from redisplaying the previous enquiry's rows. Operationally the screen behaves as described; the
interactive test asserts the 4-row load, the rendered 100.00 room / 10.00 tax lines, and the 220.00 header
balance.Honest statement: HOSTEL/i does not model a four-eyes maker–checker /
separate-authorization workflow, and it has no dedicated audit-trail file. The inquiry screens are
read-only; front-desk maintenance is performed by writing reservation and folio rows (the test drivers do
this directly against HTRESV/HTFOLIO) and then running the daily cycle, which
applies each new row exactly once. The control model the application does have is built from state
gating and idempotency:
RSTAT/FSTAT and skips
anything not in the state it acts on: HTRESERV only touches N;
HTCHKIN only B arrivals due; HTNAUDIT only I;
HTCHKOUT only settled I stays past departure; HTNOSHOW only
B past arrival.HTCHKOUT refuses to close a stay whose
RBAL > 0 (counted as HELD), so an unsettled folio cannot check out —
the front desk's real control point.HTFOLIO is a complete, append-only-in-practice ledger:
one row per room night, tax, incidental, payment and year-end archive line, each carrying its code,
date, amount and status. HTAUDRPT (ILE COBOL) reconciles it: totalling room, tax and
other, and counting open lines — the after-the-fact accountability report.RBAL so the
header alone answers "what is owed"; every posting program keeps it in step (room+tax at check-in and
audit, incidental accrual, payment application), and the AR-style invariant — balance rises by
exactly one night per audit — is what the daily battle asserts.RLAUDT same-day stamp, the
FSTAT flip on accrued/applied lines, and the GL post's movement-since-last-close
read-back all prevent double-counting on a re-run.In sum, the control posture is state gating + a settlement gate + a reconstructable folio ledger + idempotency, all in RPG record-level logic, rather than a segregation-of-duties approval workflow or a trigger-written audit file.
HOSTEL/i runs as four CL job-cycle streams rather than one monolithic nightly job: a daily cycle
(the reservation-to-folio flow), a weekly cycle (housekeeping + no-show), a monthly close
(report + GL + control report), and an annual roll (archive + reset). Each CL simply
ADDLIBLE HOSTEL then CALLs its programs in order; the batch programs take no
parameters. This is the SBMJOB idiom — a scheduled submission is a bare CALL of the
cycle CL.
-- submit a (parameterless) cycle
SBMJOB CMD(CALL PGM(HOSTEL/HTDAILY)) JOB(HTDAILY)
SBMJOB CMD(CALL PGM(HOSTEL/HTWEEK)) JOB(HTWEEK)
SBMJOB CMD(CALL PGM(HOSTEL/HTMONTH)) JOB(HTMONTH)
SBMJOB CMD(CALL PGM(HOSTEL/HTYEAR)) JOB(HTYEAR)
WRUNDT):
HTCHKIN 20260801, HTNAUDIT 20260802, HTCHKOUT 20260803, HTNOSHOW
20260805; the GL post batches 202608 and dates rows 20260831; the
archive writes 20261231. This makes the estate-sample oracle exactly hand-checkable across the
first days of August 2026. See F.4 for the operational consequence.| Program | Cycle | Purpose | Files | Output (DSPLY) |
|---|---|---|---|---|
| HTRESERV | Daily | Allocate a room by type to each new (N) reservation; lock the rate; else waitlist. | HTRESV(UF), HTRTYP(IF), HTROOMLF(UF) | HTRESERV BOOKED=n WAITLIST=n SKIP=n |
| HTCHKIN | Daily | Check in B arrivals due (ARRDT≤rundate); post night-1 room+tax. | HTRESV(UF), HTFOLIO(UF A) | HTCHKIN CHECKEDIN=n SKIP=n |
| HTNAUDIT | Daily | Post each further night's room+tax on checked-in stays not yet audited today. | HTRESV(UF), HTFOLIO(UF A) | HTNAUDIT POSTED=n SKIP=n |
| HTINCTAL | Daily | Accrue open F&B/minibar folio lines into RBAL once (stamp FSTAT='A'). | HTFOLIO(UF), HTRESV(UF) | HTINCTAL ACCRUED=n SKIP=n |
| HTPAYAPL | Daily | Apply open PY payment lines against RBAL once (stamp FSTAT='A'). | HTFOLIO(UF), HTRESV(UF) | HTPAYAPL APPLIED=n SKIP=n |
| HTCHKOUT | Daily | Check out settled (RBAL≤0) stays past departure; release room 'D'; settle open lines. Unsettled → held. | HTRESV(UF), HTROOM(UF), HTFOLIO(UF) | HTCHKOUT OUT=n HELD=n SKIP=n |
| HTHSKP | Weekly | Turn every vacant-dirty (D) room back to vacant-clean (V). | HTROOM(UF) | HTHSKP CLEANED=n |
| HTNOSHOW | Weekly | Mark B reservations past arrival as no-show (S); release their earmarked room to V. | HTRESVLF(UF), HTROOM(UF) | HTNOSHOW RELEASED=n |
| HTOCCRPT | Monthly | Print every occupied room with guest and folio balance; total occupied + balance. | HTROOM/HTRESV/HTGUEST(IF), HTOCCP(PRTF) | HTOCCRPT ROOMS=n BAL=n |
| HTGLPST | Monthly | Sum posted room + tax revenue; post the movement since last close (cash Dr / room Cr / tax Cr). | HTFOLIO(IF), HTGLDIST(SQL) | HTGLPST BATCH=202608 ROWS=n |
| HTAUDRPT | Monthly/Annual | ILE COBOL folio control report: total room/tax/other, count lines and open lines. | HTFOLIO (indexed) | HTAUDRPT ROOM/TAX/OTHER/LINES/OPEN |
| HTARCHIV | Annual | Write one YE archive line per settled (O) stay with its full room+tax+incidental turnover; reset RNIGHTS/RLAUDT. | HTRESV(UF), HTFOLIO(UF A) | HTARCHIV ARCHIVED=n RESET=n SKIP=n |
Runs the six programs above in order: HTRESERV → HTCHKIN → HTNAUDIT → HTINCTAL
→ HTPAYAPL → HTCHKOUT. Allocation walks the type-keyed room LF in (RTYPE,ROOMNO) order for
the first vacant-clean room; a booked room is taken off the vacant pool immediately (RSTAT→'O') so a
second reservation cannot double-book it. Occupancy tax is a flat 10% of the room charge. The
daily chain is safely re-runnable end to end — every step's guard makes a re-run a no-op.
Expected DSPLY (four seeded reservations, two STD rooms free): HTRESERV BOOKED=3 WAITLIST=1 2 STD + 1 DLX booked; 3rd STD waitlisted (0103 is OOO) HTCHKIN CHECKEDIN=2 2 arrivals due 20260801 (DLX arrives 20260802, not yet) HTNAUDIT POSTED=2 a 2nd night for both -> each folio 110.00 -> 220.00 HTINCTAL ACCRUED=1 one 45.00 F&B line -> 265.00 HTPAYAPL APPLIED=2 full 265.00 -> 0.00; partial 100.00 -> 120.00 HTCHKOUT OUT=1 HELD=1 settled stay out (room -> D); unsettled 120.00 held
Runs HTHSKP → HTNOSHOW. Housekeeping returns every vacant-dirty room (left by a
check-out) to vacant-clean; the no-show sweep walks the arrival-date-keyed reservation LF and, for every
B booked stay whose arrival date has passed (relative to HTNOSHOW's 20260805
run date) without a check-in, marks it S and releases its room to V.
Expected DSPLY: HTHSKP CLEANED=1 the checked-out room 0101 D -> V HTNOSHOW RELEASED=1 DLX RESV0004 never checked in -> S, room 0201 -> V
Runs HTOCCRPT → HTGLPST → HTAUDRPT. The occupancy report lists each occupied
room with its checked-in guest and running balance. The GL post sums every room and tax folio
line ever posted, then posts only the movement since the last close — it reads back what is
already on 4100-ROOM/2200-TAX and subtracts it, so a re-run in the same period
posts zero rows. Each post is a balanced set: cash debit = room credit + tax credit. The COBOL control
report reconciles the folio totals independently.
Expected DSPLY (one checked-in stay, 2 nights, balance 220.00): HTOCCRPT ROOMS=1 BAL=220.00 HTGLPST BATCH=202608 ROWS=3 1100-CASH D 220.00, 4100-ROOM C 200.00, 2200-TAX C 20.00 HTAUDRPT ROOM 200.00 / TAX 20.00 / LINES 4 / OPEN 4
Runs HTARCHIV → HTAUDRPT. For every settled (checked-out, O)
reservation still carrying nights, the archive sums the stay's room+tax+F&B+minibar turnover from its
own folio lines and writes one summary line into the same folio file under code YE
at a reservation-derived sequence band (900 + RNIGHTS×2) that no live posting program
uses, then resets RNIGHTS=0 and RLAUDT=0 so next year's audit does not inherit
this year's counters. The RNIGHTS=0 reset is itself the re-run guard.
Expected DSPLY (one settled stay, 220.00 turnover): HTARCHIV ARCHIVED=1 RESET=1 one YE line of 220.00; counters cleared
HTARCHIV only
archives settled (O) reservations, so a stay must be paid and checked out before the
year-end roll can summarise and reset it.All files are in library HOSTEL, grounded in the DDS and SQL DDL in
src/sources.mjs. Dates are stored as signed numeric YYYYMMDD (8S,0) or
YYYYMM for the GL batch; money is packed decimal (nP m). "P" = packed,
"S" = zoned/signed, "A" = character.
| Field | Type | Meaning |
|---|---|---|
| RTYPE | 3A | Room-type code (key), e.g. STD/DLX/STE. |
| RDESC | 20A | Description, e.g. STANDARD DOUBLE. |
| RATE | 9P 2 | Standard nightly rate this type books at. |
| MAXOCC | 1S 0 | Maximum guests the type sleeps. |
| RSTAT | 1A | A active (sellable); else withdrawn. |
Seeded types: STD 100.00/maxocc 2, DLX 150.00/maxocc 2, STE 250.00/maxocc 4 (all active).
| Field | Type | Meaning |
|---|---|---|
| ROOMNO | 4A | Room number (key), e.g. 0101. |
| RTYPE | 3A | Room type it belongs to (drives its rate). |
| RFLOOR | 2S 0 | Floor number. |
| RSTAT | 1A | V vacant-clean, O occupied, D vacant-dirty, X out-of-order. |
Seeded rooms: 0101/0102 STD V, 0103 STD X (out-of-order — drives the waitlist case), 0201 DLX V, 0301 STE V.
Alternate access path over HTROOM keyed RTYPE, ROOMNO — the
availability-by-type walk allocation genuinely wants (find a free room of the requested type) instead of
scanning the whole room list in room-number order.
| Field | Type | Meaning |
|---|---|---|
| GUESTID | 6A | Guest id (key), e.g. G00001. |
| GNAME | 30A | Guest name. |
| GPHONE | 15A | Phone number. |
| GVIP | 1A | VIP Y/N — cosmetic on the inquiry screen, not load-bearing in the arithmetic (no invented VIP discount). |
| GSTAT | 1A | A active. |
Seeded guests: G00001 JANET OKAFOR (N), G00002 MARCUS VANCE (VIP Y), G00003 PRIYA RAMASWAMY (N), G00004 TOM LINDQVIST (N).
| Field | Type | Meaning |
|---|---|---|
| RESVNO | 8A | Reservation number (key), e.g. RESV0001. |
| GUESTID | 6A | Owning guest. |
| RTYPE | 3A | Requested room type. |
| ARRDT / DEPDT | 8S 0 | Arrival / departure dates (YYYYMMDD). |
| ROOMNO | 4A | Assigned room (blank until booked; blank on waitlist). |
| RSTAT | 1A | Stay lifecycle: N/W/B/I/O/X/S (see A.2). |
| RATELOCK | 9P 2 | Room-type rate stamped at booking (never repriced later). |
| RNIGHTS | 3S 0 | Nights already posted by the night audit (re-run guard; 0 = year-end reset). |
| RLAUDT | 8S 0 | Last calendar date audited (same-day double-post guard). |
| RBAL | 11P 2 | Folio running-balance mirror — what the stay owes. |
Alternate access path keyed ARRDT, RESVNO — the arrivals list the front desk works
from (who is due in today) and the walk the no-show sweep needs (who is still B past their
arrival date).
| Field | Type | Meaning |
|---|---|---|
| RESVNO | 8A | Reservation the line belongs to (key part 1). |
| FSEQ | 3S 0 | Line sequence within the stay (key part 2). |
| FDT | 8S 0 | Line date (YYYYMMDD). |
| FCODE | 2A | RM room, TX occupancy tax, FB food&beverage, MB minibar, PY payment (negative), YE year-end archive. |
| FAMT | 11P 2 | Line amount (payments are negative). |
| FSTAT | 1A | O open, S settled, A accrued/applied into RBAL. |
FKEY KLIST over (WRESV, WSEQ) in the night audit —
the same convention as the estate's order-line files.Alternate access path keyed FCODE, RESVNO, FSEQ — the revenue-by-department view
(room vs tax vs F&B vs minibar) the monthly close and GL post want without re-summing every folio.
| Field | Type | Meaning |
|---|---|---|
| GLSEQ | DECIMAL(8,0) | GL row sequence (PK) — never restarted; MAX+1 each post. |
| GLBATCH | DECIMAL(6,0) | Batch/period, e.g. 202608. |
| ACCT | CHAR(9) | Account: 1100-CASH, 4100-ROOM, 2200-TAX. |
| DRCR | CHAR(1) | D debit / C credit. |
| AMT | DECIMAL(11,2) | Posted amount. |
| GLREF | CHAR(8) | Reference, e.g. ROOMREV. |
| GLDT | DECIMAL(8,0) | GL date (YYYYMMDD). |
Index HTGLDACC on (ACCT, DRCR) supports the movement-since-last-close
read-back.
RESVINQ, the plain reservation inquiry screen for HTRESVIQ.FSFL under control FCTL (SFLSIZ 20 / SFLPAG 5 / ROLLUP/ROLLDOWN / SFLEND(*MORE)), the folio inquiry for HTFOLIQ.HTMENU, the operator menu for HTMENU.OCCHDR/OCCDTL/OCCTOT, the occupancy/revenue report HTOCCRPT prints.HOSTEL (LIBL = QSYS QGPL HOSTEL QTEMP).HTRESV rows with RSTAT='N' (guest, type, arrival, departure; room blank, balances zero).HTFOLIO lines (FCODE='FB'/'MB', FSTAT='O') and any payments (FCODE='PY', FAMT negative, FSTAT='O').SBMJOB CMD(CALL PGM(HOSTEL/HTDAILY)).CALL HOSTEL/HTMENU (reservation and folio inquiry).HTWEEK to clean turned-over rooms and release no-shows.Post-checks after the daily cycle (each program DSPLYs its counts to the job log):
HTRESERV BOOKED/WAITLIST reconcile to the new requests vs available rooms of each type; booked rooms are now O and off the vacant pool.HTCHKIN CHECKEDIN equals the B arrivals due; each checked-in stay is I with a two-line folio (room + tax) and RBAL = rate + 10% tax.HTNAUDIT POSTED equals the in-house stays not yet audited today; the AR invariant — each audited stay's RBAL rose by exactly one night (rate + tax), no more.HTINCTAL ACCRUED / HTPAYAPL APPLIED equal the open incidental / payment lines; each moved RBAL by exactly the line amount and the line flipped to FSTAT='A'.HTCHKOUT OUT/HELD — only settled (RBAL≤0) stays past departure checked out (room → D, open lines → S); any unsettled stay is HELD, still I, room still O.Month-end:
HTMONTH. Confirm HTOCCRPT ROOMS=/BAL=, HTGLPST BATCH=202608 ROWS=, and the HTAUDRPT totals.SELECT ACCT, DRCR, AMT FROM HOSTEL.HTGLDIST ORDER BY GLSEQ;
Reconciling figures (the same ones the cycles battle checks by hand against the seeded scenario — one checked-in STD stay, 2 nights):
4100-ROOM credit = Σ posted RM folio lines = 2 × 100.00 = 200.00 (tax excluded).2200-TAX credit = Σ posted TX lines = 2 × 10.00 = 20.00.1100-CASH debit = room + tax = 200.00 + 20.00 = 220.00; the batch balances (Dr 220.00 = Cr 200.00 + 20.00).HTGLPST in the same period posts 0 further rows: it reads back what is already on 4100-ROOM/2200-TAX and subtracts it (ROWS=0).HTAUDRPT independently reports ROOM 200.00, TAX 20.00, LINES 4, OPEN 4 (folio not yet settled).Year-end: after the settled stays have checked out, submit HTYEAR. Confirm
HTARCHIV ARCHIVED=/RESET=; each settled stay gets one YE folio line carrying its
full room+tax(+F&B+minibar) turnover (e.g. 220.00) and its RNIGHTS/RLAUDT reset to 0.
Every program DSPLYs its counts; a healthy re-run of an already-processed cycle shows all-zero action counts (nothing left in the acted-on state). The estate tests assert every cycle is safely re-runnable.
| Situation | Behaviour | Action |
|---|---|---|
| Daily chain fails partway | Completed steps left their state stamped (RSTAT/FSTAT/RLAUDT); pending rows untouched. | Re-submit HTDAILY: each step skips what it already did and finishes the rest. Idempotent by state. |
| Re-run allocation | Only N reservations are processed. | Safe no-op: HTRESERV BOOKED=0 WAITLIST=0. |
| Re-run night audit same day | RLAUDT ≥ run date guard skips every stay. | Safe no-op: POSTED=0, balances unchanged. A new night requires advancing the run date (see F.4). |
| Re-run incidental / payment | A line already folded into RBAL is FSTAT='A'. | Safe no-op: ACCRUED=0 / APPLIED=0; never double-counted. |
| Check-out of an unsettled stay | Balance > 0 → counted as HELD, left checked-in. | Post/apply a payment to clear the balance, then re-run HTCHKOUT. |
| Re-run GL post same period | Movement-since-last-close read-back nets to zero. | Safe no-op: ROWS=0; the ledger is not double-posted. A refused insert is not counted as a posted row (guarded on sqlcod=0). |
| Re-run annual archive | RNIGHTS=0 reset signal is already set. | Safe no-op: ARCHIVED=0 RESET=0; a stay is never archived twice. |
HTFOLIO plus
HTRESV.RBAL, and HTAUDRPT reconciles the room/tax totals independently for
recovery.The complete program surface, from src/sources.mjs. All objects are in library
HOSTEL. Fixed-form RPG C-specs and free-form /free blocks are used side by side,
mirroring the estate's ibmi/samples.js convention.
HTREFLD RTYPE=3 ROOM=5 GUEST=4. Run once after HTSETUP.N reservation: CHAIN HTRTYP for the rate; SETLL/READE the type-keyed HTROOMLF for the first V room; if found, flip room to O, set reservation ROOMNO/RATELOCK/RSTAT='B'; else RSTAT='W'. Re-CHAINs the reservation after the room walk moved the cursor.B stay with ARRDT ≤ run date: RSTAT='I', RNIGHTS=1, RLAUDT=run date, RBAL = rate + tax; WRITE folio lines FSEQ 1 (RM) and 2 (TX). Tax = rate × 10 / 100.I stay with RLAUDT < run date and DEPDT > RLAUDT: post one more room+tax pair at FSEQ = RNIGHTS×2 + 1 (and +1), RNIGHTS++, RLAUDT=run date, RBAL += rate + tax. Stays past departure are not billed further.HTFOLIO; for each O line that is not RM/TX/PY, stamps it A and adds FAMT to the reservation's RBAL once.HTFOLIO; for each O line with FCODE='PY' (amount already negative), stamps it A and adds the negative FAMT to RBAL once (reducing it).I stay with DEPDT ≤ run date: if RBAL > 0, count HELD and leave; else RSTAT='O', release room to D, and set every open folio line to S.HTROOM; every D room becomes V.HTRESVLF (arrival-keyed); each B stay with ARRDT < run date becomes S and its room is released to V.O (occupied) room, finds the checked-in reservation that holds it, resolves the guest, and prints room/type/status/guest/balance via HTOCCP; totals count and balance with overflow (*IN90) header reprint.MAX(GLSEQ) and the already-posted 4100-ROOM / 2200-TAX credits, subtracts them, and inserts the balanced movement (cash Dr, room Cr, tax Cr). A refused insert (sqlcod ≠ 0) is not counted.O stay with RNIGHTS ≠ 0: sums the stay's RM/TX/FB/MB folio lines, WRITEs one YE line at FSEQ = 900 + RNIGHTS×2, then resets RNIGHTS=0, RLAUDT=0.HTFOLIO sequentially by key; accumulates room / tax / other and counts total lines and open lines; DISPLAYs the five totals. The independent reconciliation of the RPG postings.QDDSSRC, RUNSQLSTM the GL table + index from QSQLSRC, CRTBNDRPG all 15 RPG programs and CRTBNDCBL the COBOL program.The three logical files exist because each carries a genuinely different leading key from its PF, giving a program the ordering it actually needs:
SETLL(WTYPE) then READE by type, so
it walks only rooms of the requested type in room-number order and takes the first V one.
The base HTROOM is ROOMNO-keyed; the LF is RTYPE-keyed — genuinely different
orderings, which is what makes the walk worth having (the build test asserts this).B stays whose arrival has passed.Programs that walk a keyed file to enumerate rows and then need the header again re-CHAIN the
header afterwards, because the row walk moved the shared cursor — e.g. HTRESERV re-CHAINs
HTRESVR after the room walk, and HTARCHIV re-CHAINs after summing folio lines.
| Guard | Where | How it prevents a double |
|---|---|---|
| RSTAT skip | HTRESERV/HTCHKIN/HTNAUDIT/HTCHKOUT/HTNOSHOW | Only rows in the acted-on state are processed; a processed row has moved to a new state. |
| RLAUDT stamp | HTNAUDIT | RLAUDT ≥ run date skips a stay already audited on that date — the same-day double-post guard. |
| FSTAT flip | HTINCTAL / HTPAYAPL | A line folded into RBAL is stamped A; a re-run only sees O lines. |
| Movement read-back | HTGLPST | Reads already-posted 4100-ROOM/2200-TAX and subtracts, so a re-run's delta is zero (never restarts GLSEQ at 1). |
| RNIGHTS=0 reset | HTARCHIV | A reset stay carries RNIGHTS 0; a live stay always ≥ 1, so a second annual run finds nothing to archive. |
| Settlement gate | HTCHKOUT | Refuses RBAL > 0; a stay cannot be closed (or double-closed) with money owing. |
Every date-sensitive program carries its processing date as a compiled literal in a
WRUNDT/WBATCH field rather than reading a control row:
| Program | Literal | Meaning |
|---|---|---|
| HTCHKIN | 20260801 | Check-in / first-night run date. |
| HTNAUDIT | 20260802 | Night-audit run date (posts night 2). |
| HTCHKOUT | 20260803 | Check-out run date. |
| HTNOSHOW | 20260805 | No-show sweep run date. |
| HTGLPST | 202608 / 20260831 | GL batch period / GL row date. |
| HTARCHIV | 20261231 | Year-end archive-line date. |
Operational consequence: the shipped estate is a hand-checkable oracle across the first days of
August 2026 — the night audit posts exactly one further night, check-out lands on the departure date,
and the no-show sweep fires for the DLX reservation that was never checked in. To advance the model to a
new business date in a real deployment, the run-date literals are the single edit point (change
WRUNDT and recompile), not a control-row update. This is an honest limitation of the sample:
it trades a live clock for a deterministic, auditable oracle.
SBMJOB CMD(CALL PGM(HOSTEL/HTDAILY))). The cycle CLs take no parameters.