Skip to main content

Crate mako_geli_gas

Crate mako_geli_gas 

Source
Expand description

mako-geli-gas — GeLi Gas (Geschäftsprozesse Lieferantenwechsel Gas) process engine for German gas market communication (BDEW MaKo).

§Process family

GeLi Gas governs the supplier switching processes for the German gas market, regulated by the BDEW GeLi Gas process documentation and BNetzA rulings:

ProcessPID
Lieferbeginn Gas (Anfrage LFN → NB)44001
Abmeldung NN / Lieferende Gas (Anfrage LFN → NB)44004
Bestätigung Anmeldung NN44002
Ablehnung Anmeldung NN44003
Bestätigung Abmeldung NN44005
Ablehnung Abmeldung NN44006
Abmeldung NN vom NB44007–44009
Abmeldungsanfrage des NB44010–44012
Anmeldung/Abmeldung EoG44013–44015
Kündigung beim alten Lieferanten44016
Bestätigung / Ablehnung Kündigung (LFA → LFN)44017–44018
Bestandsliste / Änderungsmeldung44019–44021

Stornierung splits by role. The LF side sends 44022 (ERP-initiated) and receives 44023 / 44024 into geli-gas-stornierung-lf; a Nb-only deployment takes all three into geli-gas-stornierung instead.

§Architecture

Each BDEW process variant is a separate mako_engine::workflow::Workflow implementation. This crate contains only pure domain logic — no I/O, no EDIFACT parsing, no network calls.

Parsing and validation of raw EDIFACT bytes must happen at the transport boundary (AS4 reception layer), before constructing a domain command. The workflow handle() function receives pre-extracted domain values:

AS4 transport layer
  └── parse raw bytes          (edi-energy)
      └── validate             (edi-energy)
          └── extract fields   (application code)
              └── GasSupplierChangeCommand { pid, malo_id, … }
                  └── Process::execute(cmd)  ← pure domain logic here

§„GeLi Gas 2.0“ and „GeLi Gas 3.0“ are both current, and both correct

The two names belong to different documents and neither supersedes the other:

NameDocumentStand
GeLi Gas 3.0the BNetzA Anlage zu BK7-06-067 in der Fassung BK7-24-01-009 — the Festlegung itselfBeschluss 12.09.2025, Tenor ab 01.01.2026
GeLi Gas 2.0the BDEW/VKU/GEODE/FNB Gas Anwendungshilfe (V1.2, 26.03.2026), which still carries the BK7-19-001 titlegültig ab 01.04.2026

The Anwendungsübersicht Prüfidentifikatoren names „GeLi Gas 2.0“ in its Festlegungs-Spalte for every 44xxx row, because it indexes the AWH. So a module citing „GeLi Gas 2.0“ for a Prüfidentifikator and „GeLi Gas 3.0“ for a Frist is not inconsistent — it is citing the two documents that state each.

§Key differences from the electricity processes

Both Sparten switch suppliers at the Marktlokation and both are driven by UTILMD — the differences that actually change code are these:

AspectGPKE (Strom)GeLi Gas
FestlegungBK6-24-174 (Teil 1–3), BK6-22-024 Anlage 1d (Teil 4)BK7-24-01-009 (GeLi Gas 3.0, Tenor ab 01.01.2026)
Antwortfrist shapea wall-clock instant on the 1. WT nach dem ÜT — 07:00 / 09:00 / 11:00 / 12:00Ablauf des 4. / 3. / 2. Werktags nach Eingang
Zuordnungszeitpunkt00:00 Uhr06:00 Uhr — the Gastag runs 06:00–06:00
Vorlauffrist des LF10 WT Anmeldung, 7 WT Abmeldung, bei Lieferantenwechsel
EntscheidungsbäumeE_06xxE_30xx
APERAKAnerkennungs- und Verarbeitbarkeitsfehlermeldung; 45 min für UTILMD/ORDERSnur Verarbeitbarkeitsfehlermeldung; nächster WT 12:00 (Folgeprozess) / 3 WT (Initialprozess)
CONTRLnur auf eine syntaktisch defekte APERAKauf jede APERAK
Grid operatorNetzbetreiber (NB)Gasnetzbetreiber (GNB)

Every Frist above lives in mako_fristen, never in a literal here: the two families disagree on shape as well as on number, and a helper chosen by Sparte rather than by Prüfidentifikator is how the 10-Werktage Vorlauffrist ended up sized as an answer window across this crate.

§Command construction example

use edi_energy::{AnyMessage, EdiEnergyMessage, Platform};
use mako_geli_gas::lieferbeginn::{GeliGasSupplierChangeWorkflow, GasSupplierChangeCommand};

let msg    = Platform::with_all_profiles().parse(&raw_bytes)?;
let report = msg.validate()?;
let AnyMessage::Utilmd(u) = &msg else { anyhow::bail!("not UTILMD") };

let cmd = GasSupplierChangeCommand::ReceiveUtilmd {
    pid:               msg.detect_pruefidentifikator()?,
    sender:            u.sender().and_then(|n| n.party_id.clone()).unwrap_or_default(),
    receiver:          u.receiver().and_then(|n| n.party_id.clone()).unwrap_or_default(),
    malo_id:           u.transactions().first()
                        .and_then(|t| t.marktlokation()).unwrap_or_default(),
    document_date:     u.dtm().iter().find(|d| d.is_document_date())
                        .and_then(|d| d.value.clone()).unwrap_or_default(),
    message_ref:       msg.message_ref().to_owned(),
    validation_passed: report.is_valid(),
    validation_errors: report.errors().iter()
                        .map(|i| format!("{i}")).collect(),
    bilanzierungsmethode: None,
    fallgruppe: None,
};

process.execute(cmd).await?;

Re-exports§

pub use stammdatenaenderung::ANFRAGE_PIDS as GAS_STAMMDATEN_ANFRAGE_PIDS;
pub use stammdatenaenderung::GasAntwort;
pub use stammdatenaenderung::GasStammdatenCommand;
pub use stammdatenaenderung::GasStammdatenData;
pub use stammdatenaenderung::GasStammdatenEvent;
pub use stammdatenaenderung::GasStammdatenState;
pub use stammdatenaenderung::GeliGasStammdatenaenderungWorkflow;
pub use stammdatenaenderung::STAMMDATEN_PAIRS as GAS_STAMMDATEN_PAIRS;
pub use stammdatenaenderung::WORKFLOW_NAME as GAS_STAMMDATEN_WORKFLOW_NAME;
pub use stammdatenaenderung::antwort_for as gas_stammdaten_antwort_for;
pub use stammdatenaenderung::is_aenderung_pid as gas_is_stammdaten_aenderung_pid;
pub use datenabruf::GeliGasDatenabrufCommand;
pub use datenabruf::GeliGasDatenabrufEvent;
pub use datenabruf::GeliGasDatenabrufState;
pub use datenabruf::GeliGasDatenabrufWorkflow;
pub use datenabruf::ORDERS_ANFRAGE_PIDS as GELI_GAS_DATENABRUF_ORDERS_PIDS;
pub use datenabruf::ORDRSP_ABLEHNUNG_PIDS as GELI_GAS_DATENABRUF_ORDRSP_PIDS;
pub use datenabruf::WORKFLOW_NAME as GELI_GAS_DATENABRUF_WORKFLOW_NAME;
pub use invoic::GeliGasSperrprozesseInvoic;
pub use invoic::GeliGasSperrprozesseInvoicWorkflow;
pub use invoic::SETTLEMENT_WINDOW_LABEL as SPERRPROZESSE_INVOIC_SETTLEMENT_LABEL;
pub use invoic::SPERRPROZESSE_INVOIC_PID;
pub use invoic::SPERRPROZESSE_REMADV_PIDS;
pub use invoic::WORKFLOW_NAME as GELI_GAS_SPERRPROZESSE_INVOIC_WORKFLOW_NAME;
pub use lf_anmeldung::ANFRAGE_PIDS_LF as LF_ANMELDUNG_ANFRAGE_PIDS;
pub use lf_anmeldung::ANTWORT_PIDS_LF as LF_ANMELDUNG_ANTWORT_PIDS;
pub use lf_anmeldung::GNB_RESPONSE_WINDOW_LABEL as LF_ANMELDUNG_RESPONSE_WINDOW_LABEL;
pub use lf_anmeldung::GeliGasLfAnmeldungCommand;
pub use lf_anmeldung::GeliGasLfAnmeldungData;
pub use lf_anmeldung::GeliGasLfAnmeldungEvent;
pub use lf_anmeldung::GeliGasLfAnmeldungState;
pub use lf_anmeldung::GeliGasLfAnmeldungWorkflow;
pub use lf_anmeldung::WORKFLOW_NAME as LF_ANMELDUNG_WORKFLOW_NAME;
pub use lf_stornierung::ANFRAGE_PID_LF as STORNIERUNG_ANFRAGE_PID_LF;
pub use lf_stornierung::ANTWORT_PIDS_LF as STORNIERUNG_ANTWORT_PIDS_LF;
pub use lf_stornierung::GNB_RESPONSE_WINDOW_LABEL as STORNIERUNG_LF_RESPONSE_WINDOW_LABEL;
pub use lf_stornierung::GeliGasLfStornierungWorkflow;
pub use lf_stornierung::LfStornierungCommand;
pub use lf_stornierung::LfStornierungData;
pub use lf_stornierung::LfStornierungEvent;
pub use lf_stornierung::LfStornierungState;
pub use lf_stornierung::WORKFLOW_NAME as STORNIERUNG_LF_WORKFLOW_NAME;
pub use lieferbeginn::ANFRAGE_PIDS as LIEFERBEGINN_ANFRAGE_PIDS;
pub use lieferbeginn::ANTWORT_PIDS as LIEFERBEGINN_ANTWORT_PIDS;
pub use lieferbeginn::GasProcessVariant;
pub use lieferbeginn::GasSupplierChangeCommand;
pub use lieferbeginn::GasSupplierChangeData;
pub use lieferbeginn::GasSupplierChangeEvent;
pub use lieferbeginn::GasSupplierChangeProjection;
pub use lieferbeginn::GasSupplierChangeRecord;
pub use lieferbeginn::GasSupplierChangeRecordData;
pub use lieferbeginn::GasSupplierChangeState;
pub use lieferbeginn::GeliGasSupplierChangeWorkflow;
pub use lieferbeginn::RESPONSE_WINDOW_LABEL as LIEFERBEGINN_RESPONSE_WINDOW_LABEL;
pub use lieferbeginn::UTILMD_PIDS;
pub use lieferbeginn::WORKFLOW_NAME;
pub use lieferbeginn::response_pid_for;
pub use mscons::GasMsconsDatenCommand;
pub use mscons::GasMsconsDatenEvent;
pub use mscons::GasMsconsDatenState;
pub use mscons::GeliGasMsconsWorkflow;
pub use mscons::MSCONS_PIDS as GELI_GAS_MSCONS_PIDS;
pub use mscons::WORKFLOW_NAME as GAS_MSCONS_WORKFLOW_NAME;
pub use partin::GasKommunikationsdatenCommand;
pub use partin::GasKommunikationsdatenData;
pub use partin::GasKommunikationsdatenEvent;
pub use partin::GasKommunikationsdatenState;
pub use partin::GeliGasPartinWorkflow;
pub use partin::PARTIN_GAS_PIDS as GELI_GAS_PARTIN_PIDS;
pub use partin::WORKFLOW_NAME as GELI_GAS_PARTIN_WORKFLOW_NAME;
pub use sperrung_lf::ANTWORT_WINDOW_LABEL as GELI_GAS_SPERRUNG_LF_ANTWORT_WINDOW_LABEL;
pub use sperrung_lf::GasSperrungAuftragData;
pub use sperrung_lf::GasSperrungLfCommand;
pub use sperrung_lf::GasSperrungLfEvent;
pub use sperrung_lf::GasSperrungLfState;
pub use sperrung_lf::GeliGasSperrungLfWorkflow;
pub use sperrung_lf::ORDRSP_SPERRUNG_PIDS as GELI_GAS_SPERRUNG_LF_ORDRSP_PIDS;
pub use sperrung_lf::ORDRSP_STORNO_PIDS as GELI_GAS_SPERRUNG_LF_ORDRSP_STORNO_PIDS;
pub use sperrung_lf::SPERRUNG_ANFRAGE_PIDS as GELI_GAS_SPERRUNG_ANFRAGE_PIDS;
pub use sperrung_lf::WORKFLOW_NAME as GELI_GAS_SPERRUNG_LF_WORKFLOW_NAME;
pub use sperrung_nb::ANTWORT_WINDOW_LABEL as GELI_GAS_SPERRUNG_NB_ANTWORT_WINDOW_LABEL;
pub use sperrung_nb::GasSperrungNbCommand;
pub use sperrung_nb::GasSperrungNbData;
pub use sperrung_nb::GasSperrungNbEvent;
pub use sperrung_nb::GasSperrungNbState;
pub use sperrung_nb::GeliGasSperrungNbWorkflow;
pub use sperrung_nb::MSB_ANTWORT_PIDS as GELI_GAS_SPERRUNG_NB_MSB_ANTWORT_PIDS;
pub use sperrung_nb::ORDCHG_STORNIERUNG_PIDS as GELI_GAS_SPERRUNG_NB_ORDCHG_PIDS;
pub use sperrung_nb::SPERRUNG_PIDS as GELI_GAS_SPERRUNG_NB_PIDS;
pub use sperrung_nb::WORKFLOW_NAME as GELI_GAS_SPERRUNG_NB_WORKFLOW_NAME;
pub use stornierung::GeliGasStornierungCommand;
pub use stornierung::GeliGasStornierungData;
pub use stornierung::GeliGasStornierungEvent;
pub use stornierung::GeliGasStornierungState;
pub use stornierung::GeliGasStornierungWorkflow;
pub use stornierung::STORNIERUNG_PIDS;
pub use stornierung::STORNIERUNG_RESPONSE_WINDOW_LABEL;
pub use stornierung::WORKFLOW_NAME as STORNIERUNG_WORKFLOW_NAME;
pub use gas_quality::normalize_gasqualitaet;
pub use zuordnungsmeldung::AUFHEBUNG_PID as GAS_AUFHEBUNG_PID;
pub use zuordnungsmeldung::BEENDIGUNG_PID as GAS_BEENDIGUNG_PID;
pub use zuordnungsmeldung::GeliGasZuordnungsmeldungWorkflow;
pub use zuordnungsmeldung::INFORMATION_PID as GAS_INFORMATION_PID;
pub use zuordnungsmeldung::WORKFLOW_NAME as GAS_ZUORDNUNGSMELDUNG_WORKFLOW_NAME;
pub use zuordnungsmeldung::ZUORDNUNGSMELDUNG_PIDS as GAS_ZUORDNUNGSMELDUNG_PIDS;

Modules§

antwortfrist
GeLi Gas answer Fristen — the table itself lives in mako_fristen::antwort, and what stays here is the check that it agrees with these workflows.
datenabruf
GeLi Gas / WiM Gas Datenabruf — Gas-specific data requests.
gas_quality
Gas quality normalisation for the GeLi Gas / WiM Gas process family.
invoic
GeLi Gas INVOIC billing for AWH Sperrprozesse Gas — PID 31011 (Rechnung sonstige Leistung, VNB → LFN/LFA).
lf_anmeldung
GeLi Gas LFN-side Lieferbeginn/Lieferende/Kündigung workflow.
lf_stornierung
GeLi Gas LF-side Stornierung workflow — cancellation of supply-change requests.
lieferbeginn
GeLi Gas Lieferantenwechsel — full gas supplier-change workflow.
mscons
GeLi Gas / WiM Gas MSCONS data delivery workflow.
partin
GeLi Gas PARTIN Kommunikationsdaten workflow — Gas market participant master data.
sperrung_lf
GeLi Gas LF-side Gas Sperrung / Entsperrung workflow (ORDERS 17115/17117, ORDRSP 19116/19117).
sperrung_nb
GeLi Gas NB-side (GNB-role) Gas Sperrung / Entsperrung workflow.
stammdatenaenderung
GeLi Gas Stammdatenänderung — master-data change process family (44109–44182).
stornierung
GeLi Gas / WiM Gas Stornierung — GNB-side workflow for cancellation of supply-change and MSB-change requests (PIDs 44022–44024).
zuordnungsmeldung
GeLi Gas Informationsmeldungen — the three one-way notifications the GNB owes around a Lieferbeginn.

Structs§

GeliGasModule
Engine module for the GeLi Gas process family.