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

Trois systèmes, une date de réception: le lot de 00:30 et le jour de l'usine

Objectif Fusionner en une entité la date d'arrivée d'un lot telle que le LIMS, l'ERP et le transporteur la donnent, et ne garder en litige que les vrais écarts.

Une usine reçoit ses lots de matière première. Trois systèmes disent quand: le LIMS scanne l'échantillon (un instant), l'ERP saisit la réception (une date), le transporteur écrit « Livré le » dans un CSV (du texte).

plant.sql
CREATE SCHEMA lims;
CREATE SCHEMA erp;
CREATE TABLE lims.sample (sample_id text PRIMARY KEY, batch_no text NOT NULL, received_at timestamptz NOT NULL);
CREATE TABLE erp.goods_receipt (batch_no text PRIMARY KEY, supplier text NOT NULL, receipt_date date NOT NULL);
INSERT INTO lims.sample VALUES ('E-26-4410', 'L-0101', '2026-11-05T08:12:00+01:00');
INSERT INTO erp.goods_receipt VALUES ('L-0101', 'Chimie du Rhône', '2026-11-05');
INSERT INTO lims.sample VALUES ('E-26-4411', 'L-0102', '2026-11-05T10:47:00+01:00');
INSERT INTO erp.goods_receipt VALUES ('L-0102', 'Solvants de l''Est', '2026-11-05');
INSERT INTO lims.sample VALUES ('E-26-4412', 'L-0103', '2026-11-05T14:20:00+01:00');
INSERT INTO erp.goods_receipt VALUES ('L-0103', 'Arômes Provence', '2026-11-05');
INSERT INTO lims.sample VALUES ('E-26-4413', 'L-0104', '2026-11-06T00:30:00+01:00');
INSERT INTO erp.goods_receipt VALUES ('L-0104', 'Polymères Atlantique', '2026-11-06');
INSERT INTO lims.sample VALUES ('E-26-4414', 'L-0105', '2026-11-05T16:05:00+01:00');
INSERT INTO erp.goods_receipt VALUES ('L-0105', 'Chimie du Rhône', '2026-11-05');
INSERT INTO lims.sample VALUES ('E-26-4415', 'L-0106', '2026-11-05T23:40:00+01:00');
INSERT INTO erp.goods_receipt VALUES ('L-0106', 'Solvants de l''Est', '2026-11-05');
INSERT INTO lims.sample VALUES ('E-26-4416', 'L-0107', '2026-11-06T07:55:00+01:00');
INSERT INTO erp.goods_receipt VALUES ('L-0107', 'Arômes Provence', '2026-11-06');
INSERT INTO lims.sample VALUES ('E-26-4417', 'L-0108', '2026-11-06T09:31:00+01:00');
INSERT INTO erp.goods_receipt VALUES ('L-0108', 'Polymères Atlantique', '2026-11-06');

… 8 lignes de plus

livraisons.csv
N° lot;Fournisseur;Livré le;Quai
L-0101;Chimie du Rhône;05/11/2026;Q1
L-0102;Solvants de l'Est;05/11/2026;Q2
L-0103;Arômes Provence;05/11/2026;Q3
L-0104;Polymères Atlantique;06/11/2026;Q1
L-0105;Chimie du Rhône;05/11/2026;Q2
L-0106;Solvants de l'Est;05/11/2026;Q3
L-0107;Arômes Provence;06/11/2026;Q1
L-0108;Polymères Atlantique;06/11/2026;Q2
L-0109;Chimie du Rhône;06/11/2026;Q3
L-0110;Solvants de l'Est;06/11/2026;Q1
L-0111;Arômes Provence;06/11/2026;Q2
L-0112;Polymères Atlantique;06/11/2026;Q3
manifests/10-plant-db.yaml
apiVersion: connectors.lumnik.io/v1kind: Connectormetadata:  name: scenario-dates-plant-a  connector_type: jdbc-generic  scopes: [receiving-a]spec:  connection:    url: jdbc:postgresql://dates-plant-db:5432/plant    user: hub_reader    password_env: SCENARIO_DATES_PASSWORD_A    dialect: postgres  source:    tables:      - name: sample                 # the LIMS: received_at timestamptz, the instant the lab scanned the sample        schema: lims        mode: full        pk_columns: [sample_id]        target: scenario_dates_lims_a      - name: goods_receipt          # the ERP: receipt_date date, typed by the warehouse clerk        schema: erp        mode: full        pk_columns: [batch_no]        target: scenario_dates_erp_a
manifests/20-carrier.yaml
apiVersion: connectors.lumnik.io/v1kind: Connectormetadata:  name: scenario-dates-carrier-a  connector_type: csv-file  scopes: [receiving-a]spec:  transport:    kind: local    path: /tmp/lumnik-scenario/dates-across-sources/a/livraisons.csv   # the carrier's delivery report  parser:    delimiter: ";"    encoding: ISO-8859-1    has_header: false    columns: [batch_no, supplier, delivered_on, dock]  after_process: none  mapping:    dataset:      - filter-where: { column: batch_no, regex: "L-[0-9]+" }    # the header line
manifests/30-batch.yaml
kind: Entityname: ScenarioReceivedBatchAdescription: "One batch of raw material as three systems saw it arrive: the lab's scan, the ERP's goods receipt, the carrier."scopes: [receiving-a]sources:  - table: t_scenario_dates_lims_a    map: { batch_no: batch_no, received_at: received }  - table: t_scenario_dates_erp_a    map: { batch_no: batch_no, receipt_date: received, supplier: supplier }  - table: t_scenario_dates_carrier_a    map: { batch_no: batch_no, delivered_on: received, dock: dock }match: [batch_no]
manifests/21-carrier-typed.yaml
apiVersion: connectors.lumnik.io/v1kind: Connectormetadata:  name: scenario-dates-carrier-a  connector_type: csv-file  scopes: [receiving-a]spec:  transport:    kind: local    path: /tmp/lumnik-scenario/dates-across-sources/a/livraisons.csv   # the carrier's delivery report  parser:    delimiter: ";"    encoding: ISO-8859-1    has_header: false    columns: [batch_no, supplier, delivered_on, dock]  after_process: none  mapping:    dataset:      - filter-where: { column: batch_no, regex: "L-[0-9]+" }    # the header line    cell:      - parse-date: { column: delivered_on, formats: ["dd/MM/yyyy"] }   # a day, no time: a date
manifests/31-batch-zone.yaml
kind: Entityname: ScenarioReceivedBatchAdescription: "One batch of raw material as three systems saw it arrive: the lab's scan, the ERP's goods receipt, the carrier."scopes: [receiving-a]zone: Europe/Paris                # the plant's day: a date meets a time on the day it has in Parissources:  - table: t_scenario_dates_lims_a    map: { batch_no: batch_no, received_at: received }  - table: t_scenario_dates_erp_a    map: { batch_no: batch_no, receipt_date: received, supplier: supplier }  - table: t_scenario_dates_carrier_a    map: { batch_no: batch_no, delivered_on: received, dock: dock }match: [batch_no]

Limites

  • La zone vaut pour toute l'entité: une usine sur deux fuseaux demande deux entités.
  • La table du transporteur n'est pas retypée sur place: elle est recréée, et ses lignes relues.
  • Le hub compare au jour; il ne dit pas lequel des trois systèmes a raison.
  • Lots, fournisseurs et heures synthétiques.

Réception · trois systèmes

Un lot arrive. Trois systèmes le disent.

Le LIMS: un instant. L'ERP: une date. Le transporteur: du texte.

00:30 · 2026-11-06 · 06/11/2026

Le problème

Le lot de 00:30 était en litige.

  • À Paris, c'est le 6. En UTC, c'est encore le 5.
  • L'ERP dit le 6: le hub comparait au jour UTC.

Ce qui n'est pas modifié

Les trois systèmes restent tels quels.

  • Le LIMS garde son instant, l'ERP sa date.
  • Le CSV du transporteur n'est pas retouché.

Ce qu'il a fallu écrire

zone: Europe/Paris

Une ligne dans l'entité.

  • Une date tombe à minuit à Paris.
  • Une heure tombe sur son jour à Paris.

Ce qui a été corrigé

L'entité déclare le jour de l'usine (#1881).

  • Un parse-date ajouté se dit à l'apply (#1882).
  • Il reste un litige: L-0109, le 4 au lieu du 6.

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 →