#![deny(unsafe_code)]
#![deny(missing_docs)]
#![warn(clippy::pedantic, clippy::must_use_candidate)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::doc_markdown)] #![allow(clippy::too_many_lines)] #![allow(clippy::match_same_arms)] #![allow(clippy::manual_let_else)] #![allow(clippy::redundant_closure_for_method_calls)]
#![allow(clippy::unnested_or_patterns)]
#![allow(clippy::map_unwrap_or)]
#![allow(clippy::items_after_statements)]
pub mod consent;
pub mod ersteinbau;
pub mod esa;
pub mod esa_wertebestellung;
pub mod geraeteubernahme;
pub mod geraetewechsel;
pub mod insrpt;
pub mod invoic;
pub mod preisanfrage;
pub mod preisliste;
pub mod rechnungsabwicklung;
pub mod stammdaten;
pub mod steuerungsauftrag;
pub mod technik_aenderung;
pub mod weiterverpflichtung;
pub mod wertebestellung;
pub use geraeteubernahme::{
ANKUENDIGUNG_PIDS as GERAETEUBERNAHME_ANKUENDIGUNG_PIDS, BESTELLUNG_PIDS,
GERAETEUBERNAHME_PIDS, GeraeteubernahmeCommand, GeraeteubernahmeData, GeraeteubernahmeEvent,
GeraeteubernahmeProjection, GeraeteubernahmeRecord, GeraeteubernahmeRecordData,
GeraeteubernahmeState, ORDRSP_DEADLINE_LABEL as GERAETEUBERNAHME_ORDRSP_DEADLINE_LABEL,
WORKFLOW_NAME as GERAETEUBERNAHME_WORKFLOW_NAME, WimGeraeteubernahmeWorkflow,
};
pub use geraetewechsel::{
ANTWORT_FRIST_WINDOW_LABEL as GERAETEWECHSEL_ANTWORT_FRIST_WINDOW_LABEL,
AUFTRAG_ANTWORT_WINDOW_LABEL, DEVICE_CHANGE_ANTWORT_PIDS, DEVICE_CHANGE_PIDS,
DeviceChangeCommand, DeviceChangeData, DeviceChangeEvent, DeviceChangeProjection,
DeviceChangeRecord, DeviceChangeState, WORKFLOW_NAME, WimDeviceChangeWorkflow,
antwort_frist_werktage, antwort_pid_meaning,
};
pub use insrpt::{
ANTWORT_WINDOW_LABEL as INSRPT_ANTWORT_WINDOW_LABEL,
ERGEBNIS_WINDOW_LABEL as INSRPT_ERGEBNIS_WINDOW_LABEL, INSRPT_ANFRAGE_PIDS,
INSRPT_ANTWORT_PIDS, INSRPT_ERGEBNIS_PID, INSRPT_INFORMATIONS_PIDS, Seite as InsrptSeite,
StoerungsmeldungCommand, StoerungsmeldungData, StoerungsmeldungEvent, StoerungsmeldungState,
WEITERLEITUNG_WINDOW_LABEL as INSRPT_WEITERLEITUNG_WINDOW_LABEL,
WORKFLOW_NAME as INSRPT_WORKFLOW_NAME, WimInsrptWorkflow,
};
pub use invoic::{
GasAblehnung, SETTLEMENT_WINDOW_LABEL as INVOIC_SETTLEMENT_WINDOW_LABEL,
WIM_COMDIS_ABLEHNUNG_PID, WIM_INVOIC_PIDS, WIM_REMADV_PIDS,
WORKFLOW_NAME as INVOIC_WORKFLOW_NAME, WimInvoic, WimInvoicWorkflow, gas_ablehnungs_ebd,
};
pub use preisanfrage::{
PREISANFRAGE_DEADLINE_LABEL, PreisanfrageCommand, PreisanfrageData, PreisanfrageEvent,
PreisanfrageState, QUOTES_PIDS, REQOTE_PIDS, WORKFLOW_NAME as PREISANFRAGE_WORKFLOW_NAME,
WimPreisanfrageWorkflow, antwort_frist_werktage as preisanfrage_antwort_frist_werktage,
};
pub use preisliste::{
PRICAT_PIDS, PreislisteCommand, PreislisteData, PreislisteEvent, PreislisteState,
WORKFLOW_NAME as PREISLISTE_WORKFLOW_NAME, WimPreislisteWorkflow,
};
pub use rechnungsabwicklung::{
RECHNUNGSABWICKLUNG_DEADLINE_LABEL, RECHNUNGSABWICKLUNG_ORDERS_PIDS,
RECHNUNGSABWICKLUNG_ORDRSP_PIDS, RechnungsabwicklungCommand, RechnungsabwicklungData,
RechnungsabwicklungEvent, RechnungsabwicklungState,
WORKFLOW_NAME as RECHNUNGSABWICKLUNG_WORKFLOW_NAME, WimRechnungsabwicklungWorkflow,
};
pub use stammdaten::{
ANFORDERUNG_PID, STAMMDATEN_DEADLINE_LABEL, StammdatenCommand, StammdatenData, StammdatenEvent,
StammdatenProjection, StammdatenRecord, StammdatenRecordData, StammdatenState,
UEBERMITTLUNG_PIDS, WORKFLOW_NAME as STAMMDATEN_WORKFLOW_NAME, WimStammdatenWorkflow,
};
pub use steuerungsauftrag::{
STEUERUNGSAUFTRAG_DEADLINE_LABEL, SteuerungsCommandType, SteuerungsauftragCommand,
SteuerungsauftragData, SteuerungsauftragEvent, SteuerungsauftragState,
WORKFLOW_NAME as STEUERUNGSAUFTRAG_WORKFLOW_NAME, WimSteuerungsauftragWorkflow,
};
pub use technik_aenderung::{
AuftragData as TechnikAenderungAuftragData, ORDERS_PIDS as TECHNIK_AENDERUNG_ORDERS_PIDS,
ORDRSP_PIDS as TECHNIK_AENDERUNG_ORDRSP_PIDS, TechnikAenderungCommand, TechnikAenderungEvent,
TechnikAenderungState, WORKFLOW_NAME as TECHNIK_AENDERUNG_WORKFLOW_NAME,
WimTechnikAenderungWorkflow,
};
pub use weiterverpflichtung::{
ANTWORT_WINDOW_LABEL as WEITERVERPFLICHTUNG_ANTWORT_WINDOW_LABEL,
AUFTRAG_PID as WEITERVERPFLICHTUNG_AUFTRAG_PID, WEITERVERPFLICHTUNG_PIDS,
WORKFLOW_NAME as WEITERVERPFLICHTUNG_WORKFLOW_NAME, WeiterverpflichtungCommand,
WeiterverpflichtungData, WeiterverpflichtungEvent, WeiterverpflichtungProjection,
WeiterverpflichtungState, WimWeiterverpflichtungWorkflow,
};
pub struct WimModule;
impl mako_engine::builder::EngineModule for WimModule {
fn name(&self) -> &'static str {
"wim"
}
fn workflow_names(&self) -> &'static [&'static str] {
&[
geraetewechsel::WORKFLOW_NAME,
geraeteubernahme::WORKFLOW_NAME,
ersteinbau::WORKFLOW_NAME,
stammdaten::WORKFLOW_NAME,
wertebestellung::WORKFLOW_NAME,
esa_wertebestellung::WORKFLOW_NAME,
steuerungsauftrag::WORKFLOW_NAME,
preisanfrage::WORKFLOW_NAME,
preisliste::WORKFLOW_NAME,
rechnungsabwicklung::WORKFLOW_NAME,
weiterverpflichtung::WORKFLOW_NAME,
invoic::WORKFLOW_NAME,
insrpt::WORKFLOW_NAME,
technik_aenderung::WORKFLOW_NAME,
]
}
fn register_pids_with_roles(
&self,
router: &mut mako_engine::pid_router::PidRouter,
roles: &mako_engine::marktrolle::DeploymentRoles,
) {
for &pid in geraetewechsel::DEVICE_CHANGE_PIDS {
router.register(pid, "wim-device-change");
}
for &(antwort_pid, _, _) in geraetewechsel::DEVICE_CHANGE_ANTWORT_PIDS {
router.register(antwort_pid, "wim-device-change");
}
router.register(
weiterverpflichtung::AUFTRAG_PID,
weiterverpflichtung::WORKFLOW_NAME,
);
for &pid in geraeteubernahme::GERAETEUBERNAHME_PIDS {
router.register(pid, geraeteubernahme::WORKFLOW_NAME);
}
for pid in [19_015_u32, 19_016] {
router.register(pid, geraeteubernahme::WORKFLOW_NAME);
}
if !roles.is_all() && roles.contains(mako_engine::marktrolle::Marktrolle::Nmsb) {
for pid in [19_001_u32, 19_002] {
router.register_with_module(pid, "wim-geraeteubernahme", "wim");
}
}
router.register(stammdaten::ANFORDERUNG_PID.as_u32(), "wim-stammdaten");
#[rustfmt::skip]
const GPKE_OWNED_IN_RANGE: &[u32] = &[
17102, 17113, 17110, 17114, 17120, 17121, 17122, 17123, 17128, 17129, 17130, 17131, 17133, ];
if !roles.is_all() && roles.contains(mako_engine::marktrolle::Marktrolle::Nb) {
for pid in stammdaten::UEBERMITTLUNG_PIDS {
if matches!(pid, 17115..=17117) {
continue;
}
if GPKE_OWNED_IN_RANGE.contains(&pid) {
continue;
}
router.register(pid, "wim-stammdaten");
}
}
for &pid in preisanfrage::REQOTE_PIDS
.iter()
.chain(preisanfrage::QUOTES_PIDS)
{
router.register(pid, "wim-preisanfrage");
}
for &pid in preisliste::PRICAT_PIDS {
router.register(pid, "wim-preisliste");
}
for &pid in rechnungsabwicklung::RECHNUNGSABWICKLUNG_ORDERS_PIDS
.iter()
.chain(rechnungsabwicklung::RECHNUNGSABWICKLUNG_ORDRSP_PIDS)
{
router.register(pid, rechnungsabwicklung::WORKFLOW_NAME);
}
router.register(
rechnungsabwicklung::RECHNUNGSABWICKLUNG_ABLEHNUNG_PID,
rechnungsabwicklung::WORKFLOW_NAME,
);
if roles.contains(mako_engine::marktrolle::Marktrolle::Msb) {
router.register(
wertebestellung::ANFRAGE_PID.as_u32(),
wertebestellung::WORKFLOW_NAME,
);
router.register(
wertebestellung::BESTELLUNG_PID.as_u32(),
wertebestellung::WORKFLOW_NAME,
);
router.register(
wertebestellung::ABBESTELLUNG_PID.as_u32(),
wertebestellung::WORKFLOW_NAME,
);
router.register(
wertebestellung::STORNIERUNG_PID.as_u32(),
wertebestellung::WORKFLOW_NAME,
);
}
if roles.contains(mako_engine::marktrolle::Marktrolle::Esa) {
for &pid in esa_wertebestellung::ESA_INBOUND_PIDS {
router.register(pid.as_u32(), esa_wertebestellung::WORKFLOW_NAME);
}
}
for &pid in invoic::WIM_INVOIC_PIDS {
router.register(pid, "wim-invoic");
}
for &pid in invoic::WIM_REMADV_PIDS {
router.register(pid, "wim-invoic");
}
router.register(invoic::WIM_COMDIS_ABLEHNUNG_PID.as_u32(), "wim-invoic");
router.register_with_sparte(
invoic::WIM_COMDIS_ABLEHNUNG_PID.as_u32(),
mako_engine::types::Sparte::Strom,
"wim-invoic",
);
router.register(geraetewechsel::ENDE_MSB_VOM_NB_PID, "wim-device-change");
for &pid in geraetewechsel::IFTSTA_PIDS {
router.register(pid, "wim-device-change");
}
for &pid in ersteinbau::ERSTEINBAU_PIDS {
router.register(pid, ersteinbau::WORKFLOW_NAME);
}
for &pid in insrpt::INSRPT_ANFRAGE_PIDS
.iter()
.chain(insrpt::INSRPT_ANTWORT_PIDS)
{
router.register(pid, insrpt::WORKFLOW_NAME);
}
for &pid in technik_aenderung::ORDERS_PIDS {
router.register(pid, technik_aenderung::WORKFLOW_NAME);
}
for &pid in technik_aenderung::ORDRSP_PIDS {
router.register(pid, technik_aenderung::WORKFLOW_NAME);
}
}
fn profile_requirements(&self) -> &'static [mako_engine::profile::ProfileRequirement] {
use mako_engine::profile::ProfileRequirement;
&[
ProfileRequirement {
message_type: "UTILMD",
label: "UTILMD Strom (WiM Gerätewechsel)",
},
ProfileRequirement {
message_type: "APERAK",
label: "APERAK (WiM)",
},
ProfileRequirement {
message_type: "ORDERS",
label: "ORDERS (WiM Geräteübernahme/Stammdaten)",
},
ProfileRequirement {
message_type: "ORDRSP",
label: "ORDRSP (WiM Geräteübernahme Bestätigung 19001/19002/19015/19016)",
},
ProfileRequirement {
message_type: "ORDCHG",
label: "ORDCHG (WiM Stornierung)",
},
ProfileRequirement {
message_type: "IFTSTA",
label: "IFTSTA (WiM MSB-Wechsel 21007/21009–21013/21018/21036, \
Ersteinbau iMS 21029–21031, Durchführungsmeldung 21025/21027)",
},
ProfileRequirement {
message_type: "INVOIC",
label: "INVOIC MSB-Rechnung (31009)",
},
ProfileRequirement {
message_type: "REMADV",
label: "REMADV Zahlungsavis (WiM 33001/33002)",
},
ProfileRequirement {
message_type: "COMDIS",
label: "COMDIS Ablehnung REMADV (WiM 29001)",
},
ProfileRequirement {
message_type: "INSRPT",
label: "INSRPT Störungsmeldung (WiM Strom/Gas, 23001–23012)",
},
]
}
fn configure(&self) -> Result<(), String> {
let named: &[(&str, &[u32])] = &[
(
"geraeteubernahme::BESTELLUNG_PIDS",
geraeteubernahme::BESTELLUNG_PIDS,
),
(
"geraeteubernahme::ANKUENDIGUNG_PIDS",
geraeteubernahme::ANKUENDIGUNG_PIDS,
),
("geraetewechsel::IFTSTA_PIDS", geraetewechsel::IFTSTA_PIDS),
("invoic::WIM_INVOIC_PIDS", invoic::WIM_INVOIC_PIDS),
("invoic::WIM_REMADV_PIDS", invoic::WIM_REMADV_PIDS),
("insrpt::INSRPT_ANFRAGE_PIDS", insrpt::INSRPT_ANFRAGE_PIDS),
("insrpt::INSRPT_ANTWORT_PIDS", insrpt::INSRPT_ANTWORT_PIDS),
(
"technik_aenderung::ORDERS_PIDS",
technik_aenderung::ORDERS_PIDS,
),
(
"technik_aenderung::ORDRSP_PIDS",
technik_aenderung::ORDRSP_PIDS,
),
];
for (name, pids) in named {
if pids.is_empty() {
return Err(format!(
"wim: PID slice '{name}' is empty — \
at least one PID must be registered for each workflow group",
));
}
}
if stammdaten::UEBERMITTLUNG_PIDS.is_empty() {
return Err("wim: stammdaten::UEBERMITTLUNG_PIDS is empty — \
at least one PID must be registered for the Stammdaten workflow"
.to_owned());
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use mako_engine::{
builder::EngineModule,
marktrolle::{DeploymentRoles, Marktrolle},
pid_router::PidRouter,
};
#[test]
fn nb_role_sperrung_not_overwritten_by_stammdaten_range() {
let nb = DeploymentRoles::from_roles([Marktrolle::Nb]);
let mut router = PidRouter::new();
router.register(17115, "gpke-sperrung");
router.register(17116, "gpke-sperrung");
router.register(17117, "gpke-sperrung");
router.register(17102, "gpke-datenabruf");
router.register(17113, "gpke-datenabruf");
router.register(17110, "gpke-allokationsliste");
router.register(17114, "gpke-allokationsliste");
router.register(17120, "gpke-konfiguration-aenderung");
router.register(17121, "gpke-konfiguration-aenderung");
router.register(17122, "gpke-konfiguration-aenderung");
router.register(17123, "gpke-konfiguration-aenderung");
router.register(17128, "gpke-konfiguration-aenderung");
router.register(17129, "gpke-konfiguration-aenderung");
router.register(17130, "gpke-konfiguration-aenderung");
router.register(17131, "gpke-konfiguration-aenderung");
router.register(17133, "gpke-konfiguration-aenderung");
WimModule.register_pids_with_roles(&mut router, &nb);
assert_eq!(
router.route(17115),
Some("gpke-sperrung"),
"17115 must route to gpke-sperrung"
);
assert_eq!(
router.route(17116),
Some("gpke-sperrung"),
"17116 must route to gpke-sperrung"
);
assert_eq!(
router.route(17117),
Some("gpke-sperrung"),
"17117 must route to gpke-sperrung"
);
assert_eq!(
router.route(17102),
Some("gpke-datenabruf"),
"17102 must route to gpke-datenabruf"
);
assert_eq!(
router.route(17113),
Some("gpke-datenabruf"),
"17113 must route to gpke-datenabruf"
);
assert_eq!(
router.route(17110),
Some("gpke-allokationsliste"),
"17110 must route to gpke-allokationsliste"
);
assert_eq!(
router.route(17114),
Some("gpke-allokationsliste"),
"17114 must route to gpke-allokationsliste"
);
assert_eq!(
router.route(17120),
Some("gpke-konfiguration-aenderung"),
"17120 must route to gpke-konfiguration-aenderung"
);
assert_eq!(
router.route(17122),
Some("gpke-konfiguration-aenderung"),
"17122 must route to gpke-konfiguration-aenderung"
);
assert_eq!(
router.route(17128),
Some("gpke-konfiguration-aenderung"),
"17128 must route to gpke-konfiguration-aenderung"
);
assert_eq!(
router.route(17133),
Some("gpke-konfiguration-aenderung"),
"17133 must route to gpke-konfiguration-aenderung"
);
assert_eq!(
router.route(17132),
Some("wim-stammdaten"),
"17132 (ANFORDERUNG_PID) must route to wim-stammdaten"
);
assert_eq!(
router.route(17103),
Some("wim-stammdaten"),
"17103 must route to wim-stammdaten"
);
}
#[test]
fn all_roles_uebermittlung_gate_does_not_fire() {
let all = DeploymentRoles::all();
let mut router = PidRouter::new();
router.register(17115, "gpke-sperrung");
router.register(17116, "gpke-sperrung");
router.register(17117, "gpke-sperrung");
WimModule.register_pids_with_roles(&mut router, &all);
assert_eq!(router.route(17115), Some("gpke-sperrung"));
assert_eq!(router.route(17116), Some("gpke-sperrung"));
assert_eq!(router.route(17117), Some("gpke-sperrung"));
assert_eq!(router.route(17132), Some("wim-stammdaten"));
}
}