lumnik. / scenarios All scenarios · Français

AS/400: the customer over its credit limit, read in EBCDIC

Goal Read an IBM i customer master in its French EBCDIC, and be told when a customer's outstanding balance exceeds its credit limit.

An IBM i customer master, CLIENTS, CCSID 297: 30 customers.

manifests/10-clients-binary.yaml
# The first attempt: the physical file CLIENTS, transferred in binary, read as text.apiVersion: connectors.lumnik.io/v1kind: Connectormetadata:  name: scenario-as400-bin-a  connector_type: csv-file  scopes: [credit-as400-a]spec:  transport:    kind: local    path: /tmp/lumnik-scenario/as400-customer-credit/a/CLIENTS.bin  parser:    lines: true    encoding: IBM297               # CCSID 297, the IBM i's French EBCDIC  after_process: none
record 1
f4 f1 f0 f0 f0 f1 d8 a4 89 95 83 81 89 93 93 85 99 89 85 40 c4 a4 82 96 85 a4 86 40 40 40 40 40 40 40 40 40 e2 81 89 95 a3 60 71 a3 89 85 95 95 85 40 40 40 40 40 40 40 f0 f0 f0 f0 f0 f0 f3 f5 f2 f5 4b f0 f0 f0 f0 f0 f0 f0 f0 f7 f5 f0 f0 4b f0 f0 0d 25

evidence: replay.log, binary-record-1.txt, dlq-letter.txt, export-record-1.txt, clients.txt, count-read.txt, over-limit.txt, inbox-day2.json · transform v1

manifests/20-clients.yaml
apiVersion: connectors.lumnik.io/v1kind: Connectormetadata:  name: scenario-as400-a  connector_type: csv-file  scopes: [credit-as400-a]spec:  transport:    kind: local    # CPYTOIMPF FROMFILE(GESCOM/CLIENTS) TOSTMF('/exports/CLIENTS-<date>.txt') DTAFMT(*FIXED) RCDDLM(*CRLF) STMFCCSID(297)    path: /tmp/lumnik-scenario/as400-customer-credit/a/cpytoimpf/CLIENTS-*.txt  parser:    lines: true                    # fixed columns, one record per line    encoding: IBM297  after_process: none  mapping:    cell:      # CLINUM 6, RAISOC 30, VILLE 20, ENCOURS 13, PLAFOND 13: the file's DDS, column by column      - regex-extract:          column: line          pattern: "^(.{6})(.{30})(.{20})(.{13})(.{13})$"          groups: { 1: clinum, 2: raisoc, 3: ville, 4: encours, 5: plafond }      - clean: { columns: [raisoc, ville], strip: true }      - parse-number: { column: encours, decimal-separator: "." }      - parse-number: { column: plafond, decimal-separator: "." }
manifests/30-over-limit.yaml
apiVersion: apps.lumnik.io/v1kind: Processmetadata:  name: scenario-as400-over-limit-aspec:  scope: credit-as400-a  on: { event: data.row.changed, table: connector.t_scenario_as400_a }  when:    - "encours>{plafond}"            # the outstanding balance above the customer's own credit limit  emit:    type: decision.credit-over-limit-a    message: "{clinum} {raisoc} ({ville}): {encours} € outstanding, credit limit {plafond} €"    key: clinum
$ lm connector run scenario-as400-a
run scheduled: 6233527a-5fda-44fe-946b-8eb0e5df1bdd

$ lm run get 6233527a-5fda-44fe-946b-8eb0e5df1bdd
ID        CONNECTOR         ENDPOINT  STATUS     IN  OUT  SKIPPED  DEAD-LETTERS  STARTED           ENDED             EVALUATED
6233527a  scenario-as400-a  default   Completed  30  30   0        0             2026-11-06 21:08  2026-11-06 21:08  yes
• 1 file(s) unchanged since they were last read — not read again

$ lm inbox --process scenario-as400-over-limit-a
ID     WHEN      PROCESS                      MESSAGE                                                                        ENTITY_KEY
24813  just now  scenario-as400-over-limit-a  410022 Escaliers Thérèse (Valence): 16470 € outstanding, credit limit 15000 €  410022
24812  just now  scenario-as400-over-limit-a  410007 Plomberie Gaëtan (Vienne): 23820 € outstanding, credit limit 22500 €    410007
24802  just now  scenario-as400-over-limit-a  410022 Escaliers Thérèse (Valence): 16470 € outstanding, credit limit 15000 €  410022
24801  just now  scenario-as400-over-limit-a  410007 Plomberie Gaëtan (Vienne): 23820 € outstanding, credit limit 22500 €    410007

Limits

  • A binary transfer is not read: no fixed record length, no packed decimal. The export is CPYTOIMPF.
  • CCSID 297 has no œ: a name written with it on the IBM i cannot be one.
  • Each day's export is kept: the table holds one row per customer per export.
  • Synthetic customers, balances and limits.

Credit · IBM i

The customers live on an AS/400.

In EBCDIC, CCSID 297.

CLIENTS: 30 customers, outstanding and limit

The binary file

A binary transfer cannot be read.

  • No delimiter, packed fields.
  • Each line dead-lettered, the cause named.

What is not changed

The IBM i stays as it is.

  • CPYTOIMPF, its own export command.
  • No conversion to ASCII, no RPG.

What had to be written

encoding: IBM297
when: ["encours>{plafond}"]

The CCSID, the DDS widths, one condition.

  • csv-file: the fixed columns.
  • A Process: the balance above the limit.

What was fixed

A NUL byte used to fail the run.

  • Now: one dead letter, the cause, the gesture (#1855).
  • Before: "Error invoking subclass method".

Try it

The scenario replays locally.

Every step is published with its output.

This scenario runs on lumnik Open, free and open source.

Try lumnik Open →