use std::path::PathBuf;
use edifact_mapper::{DataDir, Mapper};
use serde_json::Value;
fn root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..")
}
fn mapper(fv: &str) -> Option<Mapper> {
if !root().join(format!("dist/edifact-data-{fv}.bin")).exists() {
eprintln!("skipping {fv}: build the bundle first");
return None;
}
Some(Mapper::from_data_dir(DataDir::path(root().join("dist")).eager(&[fv])).expect("bundle"))
}
fn bo4e_errors(m: &Mapper, fv: &str, pid: &str, edi: &str) -> Vec<String> {
let ic = m
.from_edifact::<Value, Value>(edi, fv, "UTILMD_Strom", pid)
.expect("parse");
let n = &ic.nachrichten[0];
let mut entities = n.stammdaten.clone();
let map = entities.as_object_mut().expect("stammdaten");
map.insert(
"nachricht".into(),
Value::Object(n.nachrichtendaten.nachricht.clone()),
);
let tx = &n.transaktionen[0];
for (k, v) in tx["stammdaten"].as_object().into_iter().flatten() {
map.insert(k.clone(), v.clone());
}
map.insert("prozessdaten".into(), tx["transaktionsdaten"].clone());
m.validate_pid_with_conditions(&entities, fv, "UTILMD_Strom", pid)
.expect("validate")
.iter()
.map(|e| e.to_string())
.filter(|e| e.starts_with("ERROR") || e.starts_with("INVALID"))
.collect()
}
#[test]
fn the_transaktionsgrund_is_judged_by_its_own_code() {
for fv in ["FV2510", "FV2604", "FV2610"] {
let Some(m) = mapper(fv) else {
continue;
};
let sample = root().join(format!(
"fixtures/generated/{}/utilmd/55010__ZW3.edi",
fv.to_lowercase()
));
let edi = std::fs::read_to_string(&sample).expect("sample");
assert!(edi.contains("STS+7++E03+ZW3'"), "{fv}: {edi}");
let found = bo4e_errors(&m, fv, "55010", &edi);
assert!(found.is_empty(), "{fv} E03: {found:#?}");
let e01 = edi.replace("STS+7++E03+ZW3'", "STS+7++E01+ZW3'");
let found = bo4e_errors(&m, fv, "55010", &e01);
assert!(
found
.iter()
.any(|e| e.contains("transaktionsgrund") && e.contains("[192]")),
"{fv} E01: {found:#?}"
);
}
}