use std::path::PathBuf;
use edifact_mapper::{DataDir, Mapper};
use mig_bo4e::PidValidationError;
use serde_json::Value;
type Dynamic = mig_bo4e::model::Interchange<Value, Value>;
const FV: &str = "FV2604";
const VARIANT: &str = "UTILMD_Strom";
const PID: &str = "55043";
fn load() -> Option<(Mapper, Value)> {
let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..");
let fixture = root.join("fixtures/generated/fv2604/utilmd/55043.edi");
if !root.join(format!("dist/edifact-data-{FV}.bin")).exists() || !fixture.exists() {
eprintln!("skipping: regenerate the {FV} bundle + fixture first");
return None;
}
let mapper =
Mapper::from_data_dir(DataDir::path(root.join("dist")).eager(&[FV])).expect("bundle");
let edifact = std::fs::read_to_string(&fixture).expect("fixture");
let ic: Dynamic = mapper
.from_edifact(&edifact, FV, VARIANT, PID)
.expect("convert fixture");
let raw = ic.nachrichten[0].transaktionen[0].clone();
let mut tx = raw["stammdaten"].clone();
mig_bo4e::model::restore_entity(
&mut tx,
mig_bo4e::model::TX_METADATA_ENTITY,
raw.get("transaktionsdaten").unwrap_or(&Value::Null),
);
Some((mapper, tx))
}
fn tranche_findings(mapper: &Mapper, tx: &Value) -> (Vec<String>, Vec<String>) {
let about_lists = |errors: Vec<PidValidationError>| -> Vec<String> {
errors
.iter()
.map(|e| e.to_string())
.filter(|e| e.contains("TrancheDaten.mengen") || e.contains("TrancheDaten.zuordnungen"))
.collect()
};
(
about_lists(mapper.validate_pid(tx, FV, VARIANT, PID).unwrap()),
about_lists(
mapper
.validate_pid_with_conditions(tx, FV, VARIANT, PID)
.unwrap(),
),
)
}
#[test]
fn a_complete_tranche_has_no_list_findings() {
let Some((mapper, tx)) = load() else { return };
assert!(
tx["trancheDaten"]["mengen"].is_array(),
"the fixture has a Tranche with mengen"
);
let (basic, conditional) = tranche_findings(&mapper, &tx);
assert!(basic.is_empty(), "{basic:#?}");
assert!(conditional.is_empty(), "{conditional:#?}");
}
#[test]
fn a_tranche_without_its_menge_is_reported_when_384_holds() {
let Some((mapper, mut tx)) = load() else {
return;
};
tx["trancheDaten"]
.as_object_mut()
.expect("trancheDaten")
.remove("mengen");
let (_, conditional) = tranche_findings(&mapper, &tx);
assert!(
conditional
.iter()
.any(|e| e.contains("TrancheDaten.mengen[]")),
"{conditional:#?}"
);
}
#[test]
fn a_missing_kind_of_zuordnung_is_reported() {
let Some((mapper, mut tx)) = load() else {
return;
};
let zuordnungen = tx["trancheDaten"]["zuordnungen"]
.as_array_mut()
.expect("zuordnungen");
zuordnungen.retain(|z| z["merkmal"]["art"] != "zugeordneterMarktpartner");
let (_, conditional) = tranche_findings(&mapper, &tx);
assert!(
conditional
.iter()
.any(|e| e.contains("TrancheDaten.zuordnungen[zugeordneterMarktpartner]")),
"{conditional:#?}"
);
}
#[test]
fn every_cav_code_is_checked() {
let Some((mapper, mut tx)) = load() else {
return;
};
let werte = tx["trancheDaten"]["zuordnungen"][0]["werte"]
.as_array_mut()
.expect("werte");
werte.push(serde_json::json!({ "code": "Z99" }));
let (basic, conditional) = tranche_findings(&mapper, &tx);
for findings in [&basic, &conditional] {
assert!(
findings
.iter()
.any(|e| e.contains("zuordnungen[].werte[].code") && e.contains("Z99")),
"{findings:#?}"
);
}
}