automapper-validation 0.41.2

AHB condition expression parsing, evaluation, and EDIFACT validation
Documentation
//! Zeiträume of a transaction: its SG6 groups, each naming a Zeitraum-ID in
//! RFF DE1156 (UTILMD SG4, UTILTS SG5).

use crate::eval::{ConditionResult, EvaluationContext};

/// Whether the SG6 in scope (RFF with one of `qualifiers`) names a Zeitraum-ID
/// smaller than another SG6 of the same transaction with one of them — whether
/// a later Zeitraum follows it. UTILMD [471]/[472], UTILTS [58]: DTM+Z26 closes
/// such a Zeitraum, the last one may stay open (#476). False for an SG6 of
/// another kind. Without a scope: whether any SG6 is followed so.
pub fn followed_by_later_period(
    ctx: &EvaluationContext,
    tx_group: &str,
    qualifiers: &[&str],
) -> ConditionResult {
    let id = |path: &[(&str, usize)]| -> Option<u32> {
        ctx.find_segments_at(path, "RFF").iter().find_map(|rff| {
            qualifiers
                .contains(&rff.get_component(0, 0))
                .then(|| rff.get_component(0, 2).parse::<u32>().ok())
                .flatten()
        })
    };
    let followed = |tx: usize, sg6: usize| -> bool {
        let Some(own) = id(&[(tx_group, tx), ("SG6", sg6)]) else {
            return false;
        };
        (0..ctx.child_group_instance_count(&[tx_group], tx, "SG6"))
            .filter(|other| *other != sg6)
            .filter_map(|other| id(&[(tx_group, tx), ("SG6", other)]))
            .any(|other| other > own)
    };
    if let Some(scope) = ctx.enclosing_scope("SG6") {
        let at = |id: &str| scope.iter().find(|(g, _)| *g == id).map(|(_, i)| *i);
        return match (at(tx_group), at("SG6")) {
            (Some(tx), Some(sg6)) => ConditionResult::from(followed(tx, sg6)),
            _ => ConditionResult::Unknown,
        };
    }
    if ctx.navigator().is_none() {
        return ConditionResult::Unknown;
    }
    ConditionResult::from((0..ctx.group_instance_count(&[tx_group])).any(|tx| {
        (0..ctx.child_group_instance_count(&[tx_group], tx, "SG6")).any(|sg6| followed(tx, sg6))
    }))
}