use std::path::PathBuf;
use edifact_mapper::{DataDir, Mapper};
use serde_json::Value;
fn mapper(fv: &str) -> Option<Mapper> {
let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..");
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"))
}
#[test]
fn a_merged_group_has_one_requirement_set_per_variant() {
let Some(m) = mapper("FV2610") else {
return;
};
let orders = m.pid_requirements("FV2610", "ORDERS", "17009").unwrap();
let mt = orders
.entities
.iter()
.find(|e| e.entity == "Marktteilnehmer")
.unwrap();
let variant = |code: &str| {
mt.variants
.iter()
.find(|v| v.code == code)
.unwrap_or_else(|| panic!("variant {code}: {:?}", mt.variants))
};
let has = |code: &str, field: &str| variant(code).fields.iter().any(|f| f.bo4e_name == field);
assert!(has("DP", "ortQualifier") && has("DP", "meldepunktId"));
assert!(!has("MS", "ortQualifier") && !has("MR", "ortQualifier"));
let reqote = m.pid_requirements("FV2610", "REQOTE", "35001").unwrap();
let mt = reqote
.entities
.iter()
.find(|e| e.entity == "Marktteilnehmer")
.unwrap();
let contact = mt
.nested
.iter()
.find(|n| n.field == "ansprechpartner")
.unwrap();
let selected: Vec<&str> = contact
.parent_selector
.iter()
.filter(|s| s.field == "marktrolle")
.flat_map(|s| s.codes.iter().map(|c| c.code.as_str()))
.collect();
assert_eq!(selected, ["MS"], "{:?}", contact.parent_selector);
let ordrsp = m.pid_requirements("FV2610", "ORDRSP", "19015").unwrap();
let referenz = ordrsp
.entities
.iter()
.find(|e| e.entity == "Referenz")
.unwrap();
let codes_of = |code: &str| {
referenz
.variants
.iter()
.find(|v| v.code == code)
.and_then(|v| v.fields.iter().find(|f| f.bo4e_name == "referenz"))
.map(|f| f.valid_codes.len())
};
assert_eq!(codes_of("ON"), Some(0));
assert_eq!(codes_of("Z13"), Some(1));
}
#[test]
fn geraetewechsel_and_geraeteuebernahme_samples_pass_the_bo4e_gate() {
let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..");
let pids = [
("ORDERS", "17009"),
("ORDRSP", "19015"),
("ORDRSP", "19016"),
("IFTSTA", "21010"),
("IFTSTA", "21036"),
("MSCONS", "13017"),
("REQOTE", "35001"),
("QUOTES", "15001"),
("ORDERS", "17001"),
("ORDRSP", "19001"),
("ORDRSP", "19002"),
];
for fv in ["FV2604", "FV2610"] {
let Some(m) = mapper(fv) else {
continue;
};
for (variant, pid) in pids {
let sample = root.join(format!(
"fixtures/generated/{}/{}/{pid}.edi",
fv.to_lowercase(),
variant.to_lowercase()
));
let edi = std::fs::read_to_string(&sample).expect("sample");
let interchange = m
.from_edifact::<Value, Value>(&edi, fv, variant, pid)
.expect("parse");
let nachricht = &interchange.nachrichten[0];
let transactions: Vec<Option<&Value>> = if nachricht.transaktionen.is_empty() {
vec![None]
} else {
nachricht.transaktionen.iter().map(Some).collect()
};
for tx in transactions {
let mut entities = nachricht.stammdaten.clone();
let map = entities.as_object_mut().expect("message stammdaten");
map.insert(
"nachricht".into(),
Value::Object(nachricht.nachrichtendaten.nachricht.clone()),
);
if let Some(tx) = tx {
for (k, v) in tx["stammdaten"].as_object().into_iter().flatten() {
map.insert(k.clone(), v.clone());
}
if !tx["transaktionsdaten"].is_null() {
map.insert("prozessdaten".into(), tx["transaktionsdaten"].clone());
}
}
let hard: Vec<String> = m
.validate_pid_with_conditions(&entities, fv, variant, pid)
.expect("validate")
.iter()
.map(|e| e.to_string())
.filter(|e| e.starts_with("ERROR") || e.starts_with("INVALID"))
.collect();
assert!(hard.is_empty(), "{fv} {variant} {pid}: {hard:#?}");
}
}
}
}
#[test]
fn whether_the_transaction_repeats_follows_the_ahb() {
for fv in ["FV2604", "FV2610"] {
let Some(m) = mapper(fv) else {
continue;
};
let repeats = |variant: &str, pid: &str| {
m.pid_requirements(fv, variant, pid)
.unwrap()
.transaktion_wiederholbar
};
for (variant, pid) in [
("QUOTES", "15001"),
("ORDERS", "17001"),
("ORDERS", "17009"),
] {
assert!(repeats(variant, pid), "{fv} {pid}");
}
for (variant, pid) in [
("REQOTE", "35001"),
("ORDRSP", "19001"),
("ORDRSP", "19002"),
("ORDRSP", "19015"),
("ORDRSP", "19016"),
("MSCONS", "13017"),
] {
assert!(!repeats(variant, pid), "{fv} {pid}");
}
}
}