use mig_bo4e::model::{
DynamicInterchange, Interchange, Interchangedaten, Nachricht, Nachrichtendaten,
};
use mig_bo4e::MappingEngine;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct TestMsg {
marktteilnehmer: Option<Vec<serde_json::Value>>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct TestTx {
marktlokation: Option<serde_json::Value>,
prozessdaten: Option<serde_json::Value>,
}
#[test]
fn test_typed_forward_deserializes_from_dynamic() {
let dynamic = DynamicInterchange {
interchangedaten: Interchangedaten {
absender_code: Some("9900123".into()),
..Default::default()
},
nachrichten: vec![Nachricht {
nachrichtendaten: Nachrichtendaten {
unh_referenz: "00001".into(),
nachrichten_typ: "UTILMD".into(),
},
stammdaten: serde_json::json!({
"marktteilnehmer": [{"rollencodenummer": "9900123"}]
}),
transaktionen: vec![serde_json::json!({
"marktlokation": {"marktlokationsId": "DE000111"},
"prozessdaten": {"transaktionsgrund": "E01"}
})],
}],
};
let value = serde_json::to_value(&dynamic).unwrap();
let typed: Interchange<TestMsg, TestTx> = serde_json::from_value(value).unwrap();
assert_eq!(
typed.interchangedaten.absender_code.as_deref(),
Some("9900123")
);
assert_eq!(typed.nachrichten.len(), 1);
let msg = &typed.nachrichten[0];
assert_eq!(msg.nachrichtendaten.unh_referenz, "00001");
assert_eq!(msg.nachrichtendaten.nachrichten_typ, "UTILMD");
let teilnehmer = msg.stammdaten.marktteilnehmer.as_ref().unwrap();
assert_eq!(teilnehmer.len(), 1);
assert_eq!(
teilnehmer[0]["rollencodenummer"].as_str().unwrap(),
"9900123"
);
assert_eq!(msg.transaktionen.len(), 1);
let tx = &msg.transaktionen[0];
assert!(tx.marktlokation.is_some());
assert!(tx.prozessdaten.is_some());
assert_eq!(
tx.marktlokation.as_ref().unwrap()["marktlokationsId"]
.as_str()
.unwrap(),
"DE000111"
);
}
#[test]
fn test_typed_reverse_serializes_to_dynamic() {
let nachricht: Nachricht<TestMsg, TestTx> = Nachricht {
nachrichtendaten: Nachrichtendaten {
unh_referenz: "00002".into(),
nachrichten_typ: "UTILMD".into(),
},
stammdaten: TestMsg {
marktteilnehmer: Some(vec![serde_json::json!({"rollencodenummer": "9900456"})]),
},
transaktionen: vec![TestTx {
marktlokation: Some(serde_json::json!({"marktlokationsId": "DE000222"})),
prozessdaten: Some(serde_json::json!({"transaktionsgrund": "E03"})),
}],
};
let stammdaten_value = serde_json::to_value(&nachricht.stammdaten).unwrap();
assert!(stammdaten_value["marktteilnehmer"].is_array());
let tx_value = serde_json::to_value(&nachricht.transaktionen[0]).unwrap();
assert_eq!(
tx_value["marktlokation"]["marktlokationsId"]
.as_str()
.unwrap(),
"DE000222"
);
assert_eq!(
tx_value["prozessdaten"]["transaktionsgrund"]
.as_str()
.unwrap(),
"E03"
);
}
#[test]
fn test_typed_interchange_full_roundtrip_via_json() {
let original: Interchange<TestMsg, TestTx> = Interchange {
interchangedaten: Interchangedaten {
absender_code: Some("9900111".into()),
empfaenger_code: Some("9900222".into()),
..Default::default()
},
nachrichten: vec![Nachricht {
nachrichtendaten: Nachrichtendaten {
unh_referenz: "00003".into(),
nachrichten_typ: "UTILMD".into(),
},
stammdaten: TestMsg {
marktteilnehmer: Some(vec![serde_json::json!({"marktrolle": "LF"})]),
},
transaktionen: vec![
TestTx {
marktlokation: Some(serde_json::json!({"marktlokationsId": "DE000AAA"})),
prozessdaten: Some(serde_json::json!({"transaktionsgrund": "E01"})),
},
TestTx {
marktlokation: Some(serde_json::json!({"marktlokationsId": "DE000BBB"})),
prozessdaten: None,
},
],
}],
};
let json = serde_json::to_string(&original).unwrap();
let restored: Interchange<TestMsg, TestTx> = serde_json::from_str(&json).unwrap();
assert_eq!(
restored.interchangedaten.absender_code.as_deref(),
Some("9900111")
);
assert_eq!(restored.nachrichten[0].transaktionen.len(), 2);
assert!(restored.nachrichten[0].transaktionen[1]
.prozessdaten
.is_none());
assert_eq!(
restored.nachrichten[0].transaktionen[0]
.marktlokation
.as_ref()
.unwrap()["marktlokationsId"]
.as_str()
.unwrap(),
"DE000AAA"
);
}
#[test]
fn test_map_interchange_typed_method_exists() {
use mig_assembly::assembler::AssembledTree;
use std::collections::BTreeMap;
let tree = AssembledTree {
segments: vec![],
groups: vec![],
post_group_start: 0,
inter_group_segments: BTreeMap::new(),
};
let dir = tempfile::tempdir().unwrap();
let msg_engine = MappingEngine::load(dir.path()).unwrap();
let tx_engine = MappingEngine::load(dir.path()).unwrap();
let result = MappingEngine::map_interchange_typed::<TestMsg, TestTx>(
&msg_engine,
&tx_engine,
&tree,
"SG4",
false,
Nachrichtendaten {
unh_referenz: "00001".into(),
nachrichten_typ: "UTILMD".into(),
},
Interchangedaten::default(),
);
let interchange = result.unwrap();
assert_eq!(interchange.nachrichten.len(), 1);
assert!(interchange.nachrichten[0]
.stammdaten
.marktteilnehmer
.is_none());
assert!(interchange.nachrichten[0].transaktionen.is_empty());
}
#[test]
fn test_map_interchange_reverse_typed_method_exists() {
let nachricht: Nachricht<TestMsg, TestTx> = Nachricht {
nachrichtendaten: Nachrichtendaten {
unh_referenz: "00001".into(),
nachrichten_typ: "UTILMD".into(),
},
stammdaten: TestMsg {
marktteilnehmer: Some(vec![serde_json::json!({"rollencodenummer": "9900123"})]),
},
transaktionen: vec![TestTx {
marktlokation: Some(serde_json::json!({"marktlokationsId": "DE000111"})),
prozessdaten: Some(serde_json::json!({"transaktionsgrund": "E01"})),
}],
};
let dir = tempfile::tempdir().unwrap();
let msg_engine = MappingEngine::load(dir.path()).unwrap();
let tx_engine = MappingEngine::load(dir.path()).unwrap();
let tree =
MappingEngine::map_interchange_reverse_typed(&msg_engine, &tx_engine, &nachricht, "SG4")
.unwrap();
assert!(tree.segments.is_empty());
let sg4 = tree.groups.iter().find(|g| g.group_id == "SG4");
assert!(sg4.is_some(), "Expected SG4 group from the one transaction");
assert_eq!(sg4.unwrap().repetitions.len(), 1);
}