Skip to main content

automapper_validation/generated/fv2504/
ordchg_conditions_fv2504.rs

1// <auto-generated>
2// Generated by automapper-generator generate-conditions
3// AHB: xml-migs-and-ahbs/FV2504/ORDCHG_AHB_1_0a_20241001.xml
4// Generated: 2026-03-12T10:14:16Z
5// </auto-generated>
6
7// LLM-produced bodies aren't idiomatic Rust — silence stylistic lints at
8// file scope so `cargo clippy -D warnings` stays green. Correctness,
9// suspicious, and perf categories stay on so real bugs still surface.
10#![allow(clippy::style, clippy::complexity)]
11
12#[allow(unused_imports)]
13use crate::eval::format_validators::*;
14use crate::eval::{ConditionEvaluator, ConditionResult, EvaluationContext};
15
16/// Generated condition evaluator for ORDCHG FV2504.
17pub struct OrdchgConditionEvaluatorFV2504 {
18    // External condition IDs that require runtime context.
19    external_conditions: std::collections::HashSet<u32>,
20}
21
22impl Default for OrdchgConditionEvaluatorFV2504 {
23    fn default() -> Self {
24        let mut external_conditions = std::collections::HashSet::new();
25        external_conditions.insert(1);
26        external_conditions.insert(494);
27        Self {
28            external_conditions,
29        }
30    }
31}
32
33impl ConditionEvaluator for OrdchgConditionEvaluatorFV2504 {
34    fn message_type(&self) -> &str {
35        "ORDCHG"
36    }
37
38    fn format_version(&self) -> &str {
39        "FV2504"
40    }
41
42    fn evaluate(&self, condition: u32, ctx: &EvaluationContext) -> ConditionResult {
43        match condition {
44            1 => self.evaluate_1(ctx),
45            2 => self.evaluate_2(ctx),
46            3 => self.evaluate_3(ctx),
47            4 => self.evaluate_4(ctx),
48            5 => self.evaluate_5(ctx),
49            494 => self.evaluate_494(ctx),
50            500 => self.evaluate_500(ctx),
51            501 => self.evaluate_501(ctx),
52            502 => self.evaluate_502(ctx),
53            503 => self.evaluate_503(ctx),
54            931 => self.evaluate_931(ctx),
55            939 => self.evaluate_939(ctx),
56            940 => self.evaluate_940(ctx),
57            _ => ConditionResult::Unknown,
58        }
59    }
60
61    fn is_external(&self, condition: u32) -> bool {
62        self.external_conditions.contains(&condition)
63    }
64    fn is_known(&self, condition: u32) -> bool {
65        matches!(
66            condition,
67            1 | 2 | 3 | 4 | 5 | 494 | 500 | 501 | 502 | 503 | 931 | 939 | 940
68        )
69    }
70}
71
72impl OrdchgConditionEvaluatorFV2504 {
73    /// [1] MP-ID nur aus Sparte Strom
74    /// EXTERNAL: Requires context from outside the message.
75    fn evaluate_1(&self, ctx: &EvaluationContext) -> ConditionResult {
76        ctx.external.evaluate("mp_id_only_strom")
77    }
78
79    /// [2] Wenn BGM+Z51 (Sperrung) vorhanden
80    fn evaluate_2(&self, ctx: &EvaluationContext) -> ConditionResult {
81        ctx.has_qualifier("BGM", 0, "Z51")
82    }
83
84    /// [3] Wenn BGM+Z52 (Entsperrung) vorhanden
85    fn evaluate_3(&self, ctx: &EvaluationContext) -> ConditionResult {
86        ctx.has_qualifier("BGM", 0, "Z52")
87    }
88
89    /// [4] wenn im DE3155 in demselben COM der Code EM vorhanden ist
90    fn evaluate_4(&self, ctx: &EvaluationContext) -> ConditionResult {
91        let coms = ctx.find_segments("COM");
92        ConditionResult::from(coms.iter().any(|com| {
93            com.elements
94                .first()
95                .and_then(|e| e.get(1))
96                .is_some_and(|v| v == "EM")
97        }))
98    }
99
100    /// [5] wenn im DE3155 in demselben COM der Code TE / FX / AJ / AL vorhanden ist
101    fn evaluate_5(&self, ctx: &EvaluationContext) -> ConditionResult {
102        let coms = ctx.find_segments("COM");
103        ConditionResult::from(coms.iter().any(|com| {
104            com.elements
105                .first()
106                .and_then(|e| e.get(1))
107                .is_some_and(|v| matches!(v.as_str(), "TE" | "FX" | "AJ" | "AL"))
108        }))
109    }
110
111    /// [494] Das hier genannte Datum muss der Zeitpunkt sein, zu dem das Dokument erstellt wurde, oder ein Zeitpunkt, der davor liegt.
112    /// EXTERNAL: Requires context from outside the message.
113    // REVIEW: Das hier genannte Datum muss der Zeitpunkt sein, zu dem das Dokument erstellt wurde, oder ein Zeitpunkt, der davor liegt — the date must be the document creation time or earlier. Verifying this requires knowing the actual document creation timestamp at runtime (i.e., 'now' or an authoritative creation time external to the message), which is not derivable from the EDIFACT segments alone. (medium confidence)
114    fn evaluate_494(&self, ctx: &EvaluationContext) -> ConditionResult {
115        ctx.external.evaluate("document_date_not_after_creation")
116    }
117
118    /// [500] Hinweis: Dokumentennummer aus BGM DE1004 der ORDERS
119    fn evaluate_500(&self, _ctx: &EvaluationContext) -> ConditionResult {
120        // Hinweis: Dokumentennummer aus BGM DE1004 der ORDERS — informational note, always applies
121        ConditionResult::True
122    }
123
124    /// [501] Hinweis: Wert aus BGM+Z33 DE1004 der IFTSTA mit der die Information über den Entsperrauftrag übermittelt wurde
125    fn evaluate_501(&self, _ctx: &EvaluationContext) -> ConditionResult {
126        // Hinweis: Wert aus BGM+Z33 DE1004 der IFTSTA mit der die Information über den Entsperrauftrag übermittelt wurde — informational note, always applies
127        ConditionResult::True
128    }
129
130    /// [502] Hinweis: Vorgangsnummer aus CNI DE1490 der IFTSTA mit BGM+Z33 mit der die Information über den Entsperrauftrag übermittelt wurde
131    fn evaluate_502(&self, _ctx: &EvaluationContext) -> ConditionResult {
132        // Hinweis: Vorgangsnummer aus CNI DE1490 der IFTSTA mit BGM+Z33 mit der die Information über den Entsperrauftrag übermittelt wurde — informational note, always applies
133        ConditionResult::True
134    }
135
136    /// [503] Hinweis: Es darf nur eine Information im DE3148 übermittelt werden
137    fn evaluate_503(&self, _ctx: &EvaluationContext) -> ConditionResult {
138        // Hinweis: Es darf nur eine Information im DE3148 übermittelt werden — informational note, always applies
139        ConditionResult::True
140    }
141
142    /// [931] Format: ZZZ = +00
143    // REVIEW: Format constraint: ZZZ (timezone) must be '+00' (UTC). DTM elements[0][1] contains the datetime value including timezone suffix. Checks all DTM segments to ensure their datetime values end with '+00'. Returns Unknown when no DTM segments present, False if any DTM violates the constraint. (medium confidence)
144    fn evaluate_931(&self, ctx: &EvaluationContext) -> ConditionResult {
145        let dtms = ctx.find_segments("DTM");
146        if dtms.is_empty() {
147            return ConditionResult::Unknown;
148        }
149        for dtm in &dtms {
150            if let Some(value) = dtm.elements.first().and_then(|e| e.get(1)) {
151                if !value.is_empty() && !value.ends_with("+00") {
152                    return ConditionResult::False;
153                }
154            }
155        }
156        ConditionResult::True
157    }
158
159    /// [939] Format: Die Zeichenkette muss die Zeichen @ und . enthalten
160    // REVIEW: Format check: the email address string in COM DE3148 (elements[0][0]) when DE3155 (elements[0][1]) is 'EM' must contain both '@' and '.'. Returns Unknown if no EM-typed COM segment is found. (medium confidence)
161    fn evaluate_939(&self, ctx: &EvaluationContext) -> ConditionResult {
162        let coms = ctx.find_segments("COM");
163        for com in &coms {
164            let is_email = com
165                .elements
166                .first()
167                .and_then(|e| e.get(1))
168                .is_some_and(|v| v == "EM");
169            if is_email {
170                let value = com
171                    .elements
172                    .first()
173                    .and_then(|e| e.first())
174                    .cloned()
175                    .unwrap_or_default();
176                return ConditionResult::from(value.contains('@') && value.contains('.'));
177            }
178        }
179        ConditionResult::Unknown
180    }
181
182    /// [940] Format: Die Zeichenkette muss mit dem Zeichen + beginnen und danach dürfen nur noch Ziffern folgen
183    // REVIEW: Format check: the phone/fax number string in COM DE3148 (elements[0][0]) when DE3155 (elements[0][1]) is TE/FX/AJ/AL must start with '+' followed by digits only. Returns Unknown if no phone-typed COM segment is found. (medium confidence)
184    fn evaluate_940(&self, ctx: &EvaluationContext) -> ConditionResult {
185        let coms = ctx.find_segments("COM");
186        for com in &coms {
187            let is_phone = com
188                .elements
189                .first()
190                .and_then(|e| e.get(1))
191                .is_some_and(|v| matches!(v.as_str(), "TE" | "FX" | "AJ" | "AL"));
192            if is_phone {
193                let value = com
194                    .elements
195                    .first()
196                    .and_then(|e| e.first())
197                    .cloned()
198                    .unwrap_or_default();
199                let mut chars = value.chars();
200                let starts_with_plus = chars.next() == Some('+');
201                let rest_all_digits = chars.all(|c| c.is_ascii_digit());
202                return ConditionResult::from(starts_with_plus && rest_all_digits);
203            }
204        }
205        ConditionResult::Unknown
206    }
207}