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:
| Process | PID |
|---|---|
| Lieferbeginn Gas (Anfrage LFN → NB) | 44001 |
| Abmeldung NN / Lieferende Gas (Anfrage LFN → NB) | 44004 |
| Bestätigung Anmeldung NN | 44002 |
| Ablehnung Anmeldung NN | 44003 |
| Bestätigung Abmeldung NN | 44005 |
| Ablehnung Abmeldung NN | 44006 |
| Abmeldung NN vom NB | 44007–44009 |
| Abmeldungsanfrage des NB | 44010–44012 |
| Anmeldung/Abmeldung EoG | 44013–44015 |
| Kündigung beim alten Lieferanten | 44016 |
| Bestätigung / Ablehnung Kündigung (LFA → LFN) | 44017–44018 |
| Bestandsliste / Änderungsmeldung | 44019–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:
| Name | Document | Stand |
|---|---|---|
| GeLi Gas 3.0 | the BNetzA Anlage zu BK7-06-067 in der Fassung BK7-24-01-009 — the Festlegung itself | Beschluss 12.09.2025, Tenor ab 01.01.2026 |
| GeLi Gas 2.0 | the BDEW/VKU/GEODE/FNB Gas Anwendungshilfe (V1.2, 26.03.2026), which still carries the BK7-19-001 title | gü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:
| Aspect | GPKE (Strom) | GeLi Gas |
|---|---|---|
| Festlegung | BK6-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 shape | a wall-clock instant on the 1. WT nach dem ÜT — 07:00 / 09:00 / 11:00 / 12:00 | Ablauf des 4. / 3. / 2. Werktags nach Eingang |
| Zuordnungszeitpunkt | 00:00 Uhr | 06:00 Uhr — the Gastag runs 06:00–06:00 |
| Vorlauffrist des LF | — | 10 WT Anmeldung, 7 WT Abmeldung, bei Lieferantenwechsel |
| Entscheidungsbäume | E_06xx | E_30xx |
| APERAK | Anerkennungs- und Verarbeitbarkeitsfehlermeldung; 45 min für UTILMD/ORDERS | nur Verarbeitbarkeitsfehlermeldung; nächster WT 12:00 (Folgeprozess) / 3 WT (Initialprozess) |
| CONTRL | nur auf eine syntaktisch defekte APERAK | auf jede APERAK |
| Grid operator | Netzbetreiber (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§
- Geli
GasModule - Engine module for the GeLi Gas process family.