lumnik. / scénarios Tous les scénarios · English

Progress OpenEdge: la commande de 1999 qui ne doit pas devenir 2099

Objectif Lire les fichiers EXPORT d'un ERP Progress, années sur deux chiffres comprises, et être prévenu quand un client dormant est réactivé.

Un ERP Progress OpenEdge exporte sa table Customer avec l'EXPORT d'ABL: un fichier .d, 40 clients.

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 %"

preuves: 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

Limites

  • La date de la règle est écrite dans le manifeste: « un an » n'est pas calculé depuis aujourd'hui.
  • L'export de chaque jour est gardé: la table tient une ligne par client et par export.
  • Un champ tableau (EXTENT) s'exporte en plusieurs champs: chacun demande son nom de colonne.
  • Clients, dates et soldes synthétiques.

Ventes · Progress

Les clients vivent dans un ERP Progress.

Son export écrit les années sur deux chiffres.

03/14/99

Le problème

98 devenait 2098.

  • En silence, sans erreur de cellule.
  • Une commande de 1999 n'avait jamais « plus d'un an ».

Ce qui n'est pas modifié

L'ERP reste tel quel.

  • Son EXPORT, tel qu'ABL l'écrit.
  • Aucune conversion, aucun code 4GL.

Ce qu'il a fallu écrire

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

La fenêtre que Progress utilise lui-même.

  • Sans elle, validate refuse.
  • Avec elle, 99 vaut 1999.

Ce qui a été corrigé

Une année sur deux chiffres dit son siècle (#1857).

  • Deux clients réactivés: deux décisions.
  • Avant, ils lisaient 2099 et 2003.

Essayer

Le scénario se rejoue en local.

Chaque étape est publiée avec sa sortie.

Ce scénario tourne sur lumnik Open, gratuit et open source.

Essayer lumnik Open →