use crate::outbox::PendingOutbox;
use crate::types::{MaLo, MarktpartnerCode, Pruefidentifikator};
#[derive(Debug, Clone, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct LfVorgangsdaten {
pub transaktionsgrund: Option<String>,
pub transaktionsgrund_ergaenzung: Option<String>,
pub vorgangsnummer: Option<String>,
pub uet_lieferanmeldung: Option<String>,
pub naechstmoeglicher_termin: Option<String>,
pub kunde_name: Option<String>,
pub kunde_namensformat: Option<String>,
pub lfn_mp_id: Option<String>,
}
impl LfVorgangsdaten {
#[must_use]
pub fn process_initiated(
&self,
pid: Pruefidentifikator,
malo_id: &MaLo,
sender: &MarktpartnerCode,
receiver: &MarktpartnerCode,
process_date: &str,
extra: &serde_json::Value,
) -> PendingOutbox {
let mut payload = serde_json::json!({
"pid": pid.as_u32(),
"malo_id": malo_id.as_str(),
"sender": sender.as_str(),
"receiver": receiver.as_str(),
"grid_operator": sender.as_str(),
"process_date": process_date,
"termin": process_date,
});
let obj = payload.as_object_mut().expect("json! built an object");
let mut set = |key: &str, value: &Option<String>| {
if let Some(v) = value {
obj.insert(key.to_owned(), serde_json::Value::String(v.clone()));
}
};
set("transaktionsgrund", &self.transaktionsgrund);
set(
"transaktionsgrund_ergaenzung",
&self.transaktionsgrund_ergaenzung,
);
set("vorgangsnummer", &self.vorgangsnummer);
set("uet_lieferanmeldung", &self.uet_lieferanmeldung);
set("naechstmoeglicher_termin", &self.naechstmoeglicher_termin);
set("kunde_name", &self.kunde_name);
set("kunde_namensformat", &self.kunde_namensformat);
set("lfn_mp_id", &self.lfn_mp_id);
if let Some(extra) = extra.as_object() {
for (k, v) in extra {
obj.entry(k.clone()).or_insert_with(|| v.clone());
}
}
PendingOutbox::new("ProcessInitiated", receiver.as_str(), payload)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn outbox(vorgang: &LfVorgangsdaten, extra: &serde_json::Value) -> serde_json::Value {
vorgang
.process_initiated(
Pruefidentifikator::new(55_016).expect("valid PID"),
&MaLo::new("51238696012"),
&MarktpartnerCode::new("9900357000004"),
&MarktpartnerCode::new("9900000000001"),
"20260901",
extra,
)
.payload
.clone()
}
#[test]
fn a_missing_fact_is_absent_rather_than_null() {
let p = outbox(&LfVorgangsdaten::default(), &serde_json::Value::Null);
for key in [
"transaktionsgrund",
"transaktionsgrund_ergaenzung",
"vorgangsnummer",
"uet_lieferanmeldung",
"naechstmoeglicher_termin",
"kunde_name",
"kunde_namensformat",
"lfn_mp_id",
] {
assert!(p.get(key).is_none(), "{key} must be absent, got {p:#}");
}
}
#[test]
fn every_branching_fact_is_carried() {
let p = outbox(
&LfVorgangsdaten {
transaktionsgrund: Some("E03".into()),
transaktionsgrund_ergaenzung: Some("ZW4".into()),
vorgangsnummer: Some("NNV1234".into()),
uet_lieferanmeldung: Some("20260820".into()),
naechstmoeglicher_termin: Some("20261231".into()),
kunde_name: Some("Mustermann Erika".into()),
kunde_namensformat: Some("Z01".into()),
lfn_mp_id: Some("9900357000004".into()),
},
&serde_json::Value::Null,
);
assert_eq!(p["transaktionsgrund"], "E03");
assert_eq!(p["transaktionsgrund_ergaenzung"], "ZW4");
assert_eq!(p["vorgangsnummer"], "NNV1234");
assert_eq!(p["uet_lieferanmeldung"], "20260820");
assert_eq!(p["naechstmoeglicher_termin"], "20261231");
assert_eq!(p["kunde_name"], "Mustermann Erika");
assert_eq!(p["kunde_namensformat"], "Z01");
assert_eq!(p["lfn_mp_id"], "9900357000004");
}
#[test]
fn extras_are_merged_without_overwriting() {
let p = outbox(
&LfVorgangsdaten {
transaktionsgrund: Some("E03".into()),
..LfVorgangsdaten::default()
},
&serde_json::json!({
"bilanzierungsmethode": "SLP",
"gasqualitaet": "H-Gas",
"transaktionsgrund": "SHOULD-NOT-WIN",
}),
);
assert_eq!(p["bilanzierungsmethode"], "SLP");
assert_eq!(p["gasqualitaet"], "H-Gas");
assert_eq!(p["transaktionsgrund"], "E03");
}
#[test]
fn the_notification_is_addressed_to_the_answering_party() {
let ob = LfVorgangsdaten::default().process_initiated(
Pruefidentifikator::new(55_007).expect("valid PID"),
&MaLo::new("51238696012"),
&MarktpartnerCode::new("9900357000004"),
&MarktpartnerCode::new("9900000000001"),
"20260901",
&serde_json::Value::Null,
);
assert_eq!(&*ob.recipient, "9900000000001");
assert_eq!(ob.payload["grid_operator"], "9900357000004");
}
}