lumnik. / scenarios All scenarios · Français

Progress OpenEdge: the 1999 order that must not become 2099

Goal Read a Progress ERP's EXPORT files, two-digit years included, and be told when a dormant customer is reactivated.

A Progress OpenEdge ERP exports its Customer table with ABL's EXPORT: a .d file, 40 customers.

line
1001 "Garage Martin" "Nîmes" 09/04/89 09/29/26 yes 733.25 "Client depuis 1989, remise 6 %"
line
1002 "Auto Bérard" "Valence" 05/08/92 02/27/16 no 0 "Client depuis 1992, remise 7 %"
line
1003 "Pneus du Sud" "Grenoble" 01/10/95 07/17/26 yes 2199.75 ?
line
1004 "Carrosserie Lefèvre" ? 09/13/97 06/10/26 yes 2932 "Client depuis 1997, remise 9 %"
line
1005 "Moto Évasion" "Annecy" 05/17/00 05/04/26 yes 3665.25 "Client depuis 2000, remise 10 %"
line
1006 "Cycles Gaëtan" "Vienne" 01/19/03 03/28/26 yes 4398.5 "Client depuis 2003, remise 11 %"
line
1007 "Atelier ""Le Piston""" "Chambéry" 04/08/91 03/14/99 no 0 "Client depuis 1991, remise 12 %"
line
1008 "Dépannage Noël" "Lyon" 05/26/08 01/13/26 yes 5864 "Client depuis 2008, remise 13 %"

evidence: replay.log, export-head.txt, customers.txt, count-read.txt, reactivated.txt, inbox-campaign.json · transform v1

manifests/09-customers-draft.yaml
# The first draft: the dates read without saying their century.apiVersion: connectors.lumnik.io/v1kind: Connectormetadata:  name: scenario-progress-a  connector_type: csv-file  scopes: [sales-progress-a]spec:  transport:    kind: local    # OUTPUT TO VALUE("/exports/customer-" + ...) . FOR EACH Customer: EXPORT Customer. END.    path: /tmp/lumnik-scenario/progress-openedge-customers/a/customer-*.d  parser:    delimiter: " "                 # EXPORT separates fields with one space    encoding: ISO-8859-1           # the session's -cpstream    has_header: false    columns: [cust_num, name, city, since, last_order, active, balance, comments]    null_values: ["?"]             # ABL's unknown value  after_process: none  mapping:    cell:      - parse-date: { column: since, formats: ["MM/dd/yy"] }      - parse-date: { column: last_order, formats: ["MM/dd/yy"] }      - parse-boolean: { column: active }                                               # yes / no      - parse-number: { column: balance, decimal-separator: "." }
manifests/10-customers.yaml
apiVersion: connectors.lumnik.io/v1kind: Connectormetadata:  name: scenario-progress-a  connector_type: csv-file  scopes: [sales-progress-a]spec:  transport:    kind: local    # OUTPUT TO VALUE("/exports/customer-" + ...) . FOR EACH Customer: EXPORT Customer. END.    path: /tmp/lumnik-scenario/progress-openedge-customers/a/customer-*.d  parser:    delimiter: " "                 # EXPORT separates fields with one space    encoding: ISO-8859-1           # the session's -cpstream    has_header: false    columns: [cust_num, name, city, since, last_order, active, balance, comments]    null_values: ["?"]             # ABL's unknown value  after_process: none  mapping:    cell:      - parse-date: { column: since, formats: ["MM/dd/yy"], century-from: 1950 }        # Progress's default -yy 1950      - parse-date: { column: last_order, formats: ["MM/dd/yy"], century-from: 1950 }      - parse-boolean: { column: active }                                               # yes / no      - parse-number: { column: balance, decimal-separator: "." }
manifests/20-reactivated-dormant.yaml
apiVersion: apps.lumnik.io/v1kind: Processmetadata:  name: scenario-progress-dormant-aspec:  scope: sales-progress-a  on: { event: data.row.changed, table: connector.t_scenario_progress_a }  when:    - active=true    - last_order<2025-11-05          # no order for a year: check the credit before the first delivery  emit:    type: decision.reactivated-dormant-a    message: "{cust_num} {name} reactivated: last order {last_order}, customer since {since} — check its credit first"    key: cust_num
$ lm connector run scenario-progress-a
run scheduled: e1abff2f-c357-4fc7-8812-3c517da9bbe1

$ lm run get e1abff2f-c357-4fc7-8812-3c517da9bbe1
ID        CONNECTOR            ENDPOINT  STATUS     IN  OUT  SKIPPED  DEAD-LETTERS  STARTED           ENDED             EVALUATED
e1abff2f  scenario-progress-a  default   Completed  40  40   0        0             2026-11-06 23:03  2026-11-06 23:03  yes
• 1 file(s) unchanged since they were last read — not read again

$ lm inbox --process scenario-progress-dormant-a
ID     WHEN      PROCESS                      MESSAGE                                                                                                          ENTITY_KEY
24881  just now  scenario-progress-dormant-a  1012 Location Hébert reactivated: last order 2003-09-02, customer since 1996-10-21 — check its credit first      1012
24880  just now  scenario-progress-dormant-a  1007 Atelier "Le Piston" reactivated: last order 1999-03-14, customer since 1991-04-08 — check its credit first  1007

Limits

  • The rule's date is written in the manifest: "a year" is not computed from today.
  • Each day's export is kept: the table holds one row per customer per export.
  • An array field (EXTENT) is exported as several fields: each needs its own column name.
  • Synthetic customers, dates and balances.

Sales · Progress

The customers live in a Progress ERP.

Its export writes years on two digits.

03/14/99

The problem

98 used to become 2098.

  • Silently, without a cell error.
  • A 1999 order was never "over a year old".

What is not changed

The ERP stays as it is.

  • Its EXPORT, as ABL writes it.
  • No conversion, no 4GL code.

What had to be written

formats: ["MM/dd/yy"]
century-from: 1950

The window Progress itself uses.

  • Without it, validate refuses.
  • With it, 99 is 1999.

What was fixed

A two-digit year says its century (#1857).

  • Two reactivated customers: two decisions.
  • Before, they read 2099 and 2003.

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 →