Skip to main content

automapper_validation/generated/fv2604/
partin_conditions_fv2604.rs

1// <auto-generated>
2// Generated by automapper-generator generate-conditions
3// AHB: xml-migs-and-ahbs/FV2604/PARTIN_AHB_1_0f_Fehlerkorrektur_20251211.xml
4// Generated: 2026-03-12T11:36:50Z
5// </auto-generated>
6
7#[allow(unused_imports)]
8use crate::eval::format_validators::*;
9use crate::eval::{ConditionEvaluator, ConditionResult, EvaluationContext};
10
11/// Generated condition evaluator for PARTIN FV2604.
12pub struct PartinConditionEvaluatorFV2604 {
13    // External condition IDs that require runtime context.
14    external_conditions: std::collections::HashSet<u32>,
15}
16
17impl Default for PartinConditionEvaluatorFV2604 {
18    fn default() -> Self {
19        let mut external_conditions = std::collections::HashSet::new();
20        external_conditions.insert(1);
21        external_conditions.insert(2);
22        external_conditions.insert(4);
23        external_conditions.insert(5);
24        external_conditions.insert(9);
25        external_conditions.insert(17);
26        external_conditions.insert(18);
27        external_conditions.insert(19);
28        external_conditions.insert(20);
29        external_conditions.insert(21);
30        external_conditions.insert(22);
31        external_conditions.insert(23);
32        external_conditions.insert(24);
33        external_conditions.insert(25);
34        external_conditions.insert(26);
35        external_conditions.insert(35);
36        external_conditions.insert(36);
37        external_conditions.insert(41);
38        external_conditions.insert(45);
39        external_conditions.insert(46);
40        external_conditions.insert(49);
41        external_conditions.insert(50);
42        Self {
43            external_conditions,
44        }
45    }
46}
47
48impl ConditionEvaluator for PartinConditionEvaluatorFV2604 {
49    fn message_type(&self) -> &str {
50        "PARTIN"
51    }
52
53    fn format_version(&self) -> &str {
54        "FV2604"
55    }
56
57    fn evaluate(&self, condition: u32, ctx: &EvaluationContext) -> ConditionResult {
58        match condition {
59            1 => self.evaluate_1(ctx),
60            2 => self.evaluate_2(ctx),
61            3 => self.evaluate_3(ctx),
62            4 => self.evaluate_4(ctx),
63            5 => self.evaluate_5(ctx),
64            6 => self.evaluate_6(ctx),
65            7 => self.evaluate_7(ctx),
66            8 => self.evaluate_8(ctx),
67            9 => self.evaluate_9(ctx),
68            10 => self.evaluate_10(ctx),
69            11 => self.evaluate_11(ctx),
70            12 => self.evaluate_12(ctx),
71            13 => self.evaluate_13(ctx),
72            14 => self.evaluate_14(ctx),
73            15 => self.evaluate_15(ctx),
74            16 => self.evaluate_16(ctx),
75            17 => self.evaluate_17(ctx),
76            18 => self.evaluate_18(ctx),
77            19 => self.evaluate_19(ctx),
78            20 => self.evaluate_20(ctx),
79            21 => self.evaluate_21(ctx),
80            22 => self.evaluate_22(ctx),
81            23 => self.evaluate_23(ctx),
82            24 => self.evaluate_24(ctx),
83            25 => self.evaluate_25(ctx),
84            26 => self.evaluate_26(ctx),
85            27 => self.evaluate_27(ctx),
86            28 => self.evaluate_28(ctx),
87            29 => self.evaluate_29(ctx),
88            30 => self.evaluate_30(ctx),
89            31 => self.evaluate_31(ctx),
90            32 => self.evaluate_32(ctx),
91            33 => self.evaluate_33(ctx),
92            34 => self.evaluate_34(ctx),
93            35 => self.evaluate_35(ctx),
94            36 => self.evaluate_36(ctx),
95            41 => self.evaluate_41(ctx),
96            43 => self.evaluate_43(ctx),
97            44 => self.evaluate_44(ctx),
98            45 => self.evaluate_45(ctx),
99            46 => self.evaluate_46(ctx),
100            49 => self.evaluate_49(ctx),
101            50 => self.evaluate_50(ctx),
102            490 => self.evaluate_490(ctx),
103            491 => self.evaluate_491(ctx),
104            494 => self.evaluate_494(ctx),
105            500 => self.evaluate_500(ctx),
106            501 => self.evaluate_501(ctx),
107            502 => self.evaluate_502(ctx),
108            503 => self.evaluate_503(ctx),
109            504 => self.evaluate_504(ctx),
110            505 => self.evaluate_505(ctx),
111            506 => self.evaluate_506(ctx),
112            508 => self.evaluate_508(ctx),
113            908 => self.evaluate_908(ctx),
114            931 => self.evaluate_931(ctx),
115            932 => self.evaluate_932(ctx),
116            933 => self.evaluate_933(ctx),
117            939 => self.evaluate_939(ctx),
118            940 => self.evaluate_940(ctx),
119            _ => ConditionResult::Unknown,
120        }
121    }
122
123    fn is_external(&self, condition: u32) -> bool {
124        self.external_conditions.contains(&condition)
125    }
126    fn is_known(&self, condition: u32) -> bool {
127        matches!(
128            condition,
129            1 | 2
130                | 3
131                | 4
132                | 5
133                | 6
134                | 7
135                | 8
136                | 9
137                | 10
138                | 11
139                | 12
140                | 13
141                | 14
142                | 15
143                | 16
144                | 17
145                | 18
146                | 19
147                | 20
148                | 21
149                | 22
150                | 23
151                | 24
152                | 25
153                | 26
154                | 27
155                | 28
156                | 29
157                | 30
158                | 31
159                | 32
160                | 33
161                | 34
162                | 35
163                | 36
164                | 41
165                | 43
166                | 44
167                | 45
168                | 46
169                | 49
170                | 50
171                | 490
172                | 491
173                | 494
174                | 500
175                | 501
176                | 502
177                | 503
178                | 504
179                | 505
180                | 506
181                | 508
182                | 908
183                | 931
184                | 932
185                | 933
186                | 939
187                | 940
188        )
189    }
190}
191
192impl PartinConditionEvaluatorFV2604 {
193    /// [9] Wenn die Kommunikationsdaten vom Absender nicht mehr aktiv sind.
194    /// EXTERNAL: Requires context from outside the message.
195    fn evaluate_9(&self, ctx: &EvaluationContext) -> ConditionResult {
196        ctx.external.evaluate("sender_communication_inactive")
197    }
198
199    /// [41] Nur MP-ID aus Sparte Gas
200    /// EXTERNAL: Requires context from outside the message.
201    fn evaluate_41(&self, ctx: &EvaluationContext) -> ConditionResult {
202        ctx.external.evaluate("mp_id_is_gas_sector")
203    }
204
205    /// [43] Wenn SG4 NAD+Z71 (Marktgebietsverantwortlicher) DE3207 mit Code „DE“ vorhanden
206    fn evaluate_43(&self, ctx: &EvaluationContext) -> ConditionResult {
207        // NAD+Z71 with DE3207 (elements[8][0]) = "DE"
208        ctx.has_segment_matching("NAD", &[(0, 0, "Z71"), (8, 0, "DE")])
209    }
210
211    /// [44] Wenn SG4 NAD+Z71 (Marktgebietsverantwortlicher) DE3207 mit Code „DE“ nicht vorhanden
212    fn evaluate_44(&self, ctx: &EvaluationContext) -> ConditionResult {
213        // Negation of condition 43: NAD+Z71 with DE3207="DE" NOT present
214        match ctx.has_segment_matching("NAD", &[(0, 0, "Z71"), (8, 0, "DE")]) {
215            ConditionResult::True => ConditionResult::False,
216            ConditionResult::False => ConditionResult::True,
217            ConditionResult::Unknown => ConditionResult::Unknown,
218        }
219    }
220
221    /// [45] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle LF/NB
222    /// EXTERNAL: Requires context from outside the message.
223    fn evaluate_45(&self, ctx: &EvaluationContext) -> ConditionResult {
224        ctx.external.evaluate("recipient_is_lf_or_nb")
225    }
226
227    /// [46] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle LF/MSB/MGV
228    /// EXTERNAL: Requires context from outside the message.
229    fn evaluate_46(&self, ctx: &EvaluationContext) -> ConditionResult {
230        ctx.external.evaluate("recipient_is_lf_msb_mgv")
231    }
232
233    /// [49] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle LF/MGV
234    /// EXTERNAL: Requires context from outside the message.
235    fn evaluate_49(&self, ctx: &EvaluationContext) -> ConditionResult {
236        ctx.external.evaluate("recipient_is_lf_mgv")
237    }
238
239    /// [50] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle LF/MGV/NB
240    /// EXTERNAL: Requires context from outside the message.
241    fn evaluate_50(&self, ctx: &EvaluationContext) -> ConditionResult {
242        ctx.external.evaluate("recipient_is_lf_mgv_nb")
243    }
244
245    /// [500] Hinweis: Es kann der Firmenname eines Dienstleisters oder die identische Firmenbezeichnung aus SG4 NAD+SU / DDM / DEB / Z31 / Z34 / Z35 / Z36 / Z71 eingetragen werden.
246    fn evaluate_500(&self, _ctx: &EvaluationContext) -> ConditionResult {
247        // Hinweis: Es kann der Firmenname eines Dienstleisters oder die identische Firmenbezeichnung aus SG4 NAD+SU / DDM / DEB / Z31 / Z34 / Z35 / Z36 / Z71 eingetragen werden.
248        ConditionResult::True
249    }
250
251    /// [1] Nur MP-ID aus Sparte Strom
252    /// EXTERNAL: Requires context from outside the message.
253    fn evaluate_1(&self, ctx: &EvaluationContext) -> ConditionResult {
254        ctx.external.evaluate("mp_id_is_strom")
255    }
256
257    /// [2] Wenn der Code im DE3207 in der "EDI@Energy Codeliste der europäischen Ländercodes" in der Spalte "PLZ vorhanden" ein "X" enthält
258    /// EXTERNAL: Requires context from outside the message.
259    fn evaluate_2(&self, ctx: &EvaluationContext) -> ConditionResult {
260        ctx.external.evaluate("country_has_postal_code")
261    }
262
263    /// [3] wenn vorhanden
264    fn evaluate_3(&self, _ctx: &EvaluationContext) -> ConditionResult {
265        // Hinweis: wenn vorhanden — informational annotation indicating the element is conditional/optional; always applies when evaluated
266        ConditionResult::True
267    }
268
269    /// [4] Wenn Vorgängerversion vorhanden
270    /// EXTERNAL: Requires context from outside the message.
271    fn evaluate_4(&self, ctx: &EvaluationContext) -> ConditionResult {
272        ctx.external.evaluate("predecessor_version_exists")
273    }
274
275    /// [5] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle LF
276    /// EXTERNAL: Requires context from outside the message.
277    fn evaluate_5(&self, ctx: &EvaluationContext) -> ConditionResult {
278        ctx.external.evaluate("recipient_is_lf")
279    }
280
281    /// [6] wenn im DE3155 im demselben COM der Code EM vorhanden ist
282    fn evaluate_6(&self, ctx: &EvaluationContext) -> ConditionResult {
283        let coms = ctx.find_segments("COM");
284        if coms.is_empty() {
285            return ConditionResult::Unknown;
286        }
287        ConditionResult::from(coms.iter().any(|s| {
288            s.elements
289                .first()
290                .and_then(|e| e.get(1))
291                .is_some_and(|v| v == "EM")
292        }))
293    }
294
295    /// [7] wenn im DE3155 im demselben COM der Code TE / FX / AJ / AL vorhanden ist
296    fn evaluate_7(&self, ctx: &EvaluationContext) -> ConditionResult {
297        let coms = ctx.find_segments("COM");
298        if coms.is_empty() {
299            return ConditionResult::Unknown;
300        }
301        ConditionResult::from(coms.iter().any(|s| {
302            s.elements
303                .first()
304                .and_then(|e| e.get(1))
305                .is_some_and(|v| matches!(v.as_str(), "TE" | "FX" | "AJ" | "AL"))
306        }))
307    }
308
309    /// [8] wenn im DE3155 im demselben COM der Code TE / FX vorhanden ist
310    fn evaluate_8(&self, ctx: &EvaluationContext) -> ConditionResult {
311        let coms = ctx.find_segments("COM");
312        if coms.is_empty() {
313            return ConditionResult::Unknown;
314        }
315        ConditionResult::from(coms.iter().any(|s| {
316            s.elements
317                .first()
318                .and_then(|e| e.get(1))
319                .is_some_and(|v| matches!(v.as_str(), "TE" | "FX"))
320        }))
321    }
322
323    /// [10] Wenn BGM DE1373 = 11 (Dokument nicht verfügbar) nicht vorhanden
324    fn evaluate_10(&self, ctx: &EvaluationContext) -> ConditionResult {
325        match ctx.find_segment("BGM") {
326            None => ConditionResult::False, // segment absent → condition not applicable
327            Some(bgm) => ConditionResult::from(
328                bgm.elements
329                    .get(4)
330                    .and_then(|e| e.first())
331                    .map(|v| v != "11")
332                    .unwrap_or(true),
333            ),
334        }
335    }
336
337    /// [11] Wenn SG4 NAD+SU (Lieferant) DE3207 mit Code „DE“ vorhanden
338    fn evaluate_11(&self, ctx: &EvaluationContext) -> ConditionResult {
339        let nads = ctx.find_segments_with_qualifier("NAD", 0, "SU");
340        match nads.first() {
341            None => ConditionResult::False, // segment absent → condition not applicable
342            Some(nad) => ConditionResult::from(
343                nad.elements
344                    .get(8)
345                    .and_then(|e| e.first())
346                    .is_some_and(|v| v == "DE"),
347            ),
348        }
349    }
350
351    /// [12] Wenn SG4 NAD+DDM (Netzbetreiber) DE3207 mit Code „DE“ vorhanden
352    fn evaluate_12(&self, ctx: &EvaluationContext) -> ConditionResult {
353        let nads = ctx.find_segments_with_qualifier("NAD", 0, "DDM");
354        match nads.first() {
355            None => ConditionResult::False, // segment absent → condition not applicable
356            Some(nad) => ConditionResult::from(
357                nad.elements
358                    .get(8)
359                    .and_then(|e| e.first())
360                    .is_some_and(|v| v == "DE"),
361            ),
362        }
363    }
364
365    /// [13] Wenn SG4 NAD+DEB (Messstellenbetreiber) DE3207 mit Code „DE“ vorhanden
366    fn evaluate_13(&self, ctx: &EvaluationContext) -> ConditionResult {
367        let nads = ctx.find_segments_with_qualifier("NAD", 0, "DEB");
368        match nads.first() {
369            None => ConditionResult::False, // segment absent → condition not applicable
370            Some(nad) => ConditionResult::from(
371                nad.elements
372                    .get(8)
373                    .and_then(|e| e.first())
374                    .is_some_and(|v| v == "DE"),
375            ),
376        }
377    }
378
379    /// [14] Wenn SG4 NAD+SU (Lieferant) DE3207 der Code „DE“ nicht vorhanden
380    fn evaluate_14(&self, ctx: &EvaluationContext) -> ConditionResult {
381        let nads = ctx.find_segments_with_qualifier("NAD", 0, "SU");
382        match nads.first() {
383            None => ConditionResult::False, // segment absent → condition not applicable
384            Some(nad) => ConditionResult::from(
385                nad.elements
386                    .get(8)
387                    .and_then(|e| e.first())
388                    .map(|v| v != "DE")
389                    .unwrap_or(true),
390            ),
391        }
392    }
393
394    /// [15] Wenn SG4 NAD+DDM (Netzbetreiber) DE3207 der Code „DE“ nicht vorhanden
395    fn evaluate_15(&self, ctx: &EvaluationContext) -> ConditionResult {
396        let nads = ctx.find_segments_with_qualifier("NAD", 0, "DDM");
397        match nads.first() {
398            None => ConditionResult::False, // segment absent → condition not applicable
399            Some(nad) => ConditionResult::from(
400                nad.elements
401                    .get(8)
402                    .and_then(|e| e.first())
403                    .map(|v| v != "DE")
404                    .unwrap_or(true),
405            ),
406        }
407    }
408
409    /// [16] Wenn SG4 NAD+DEB (Messstellenbetreiber) DE3207 der Code „DE“ nicht vorhanden
410    fn evaluate_16(&self, ctx: &EvaluationContext) -> ConditionResult {
411        let nads = ctx.find_segments_with_qualifier("NAD", 0, "DEB");
412        match nads.first() {
413            None => ConditionResult::False, // segment absent → condition not applicable
414            Some(nad) => ConditionResult::from(
415                nad.elements
416                    .get(8)
417                    .and_then(|e| e.first())
418                    .map(|v| v != "DE")
419                    .unwrap_or(true),
420            ),
421        }
422    }
423
424    /// [17] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle LF/NB/MSB
425    /// EXTERNAL: Requires context from outside the message.
426    fn evaluate_17(&self, ctx: &EvaluationContext) -> ConditionResult {
427        ctx.external.evaluate("recipient_is_lf_nb_msb")
428    }
429
430    /// [18] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle LF/MSB
431    /// EXTERNAL: Requires context from outside the message.
432    fn evaluate_18(&self, ctx: &EvaluationContext) -> ConditionResult {
433        ctx.external.evaluate("recipient_is_lf_msb")
434    }
435
436    /// [19] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle LF/MSB/NB/ÜNB
437    /// EXTERNAL: Requires context from outside the message.
438    fn evaluate_19(&self, ctx: &EvaluationContext) -> ConditionResult {
439        ctx.external.evaluate("recipient_is_lf_msb_nb_uenb")
440    }
441
442    /// [20] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle LF/MSB/ÜNB
443    /// EXTERNAL: Requires context from outside the message.
444    fn evaluate_20(&self, ctx: &EvaluationContext) -> ConditionResult {
445        ctx.external.evaluate("recipient_is_lf_msb_uenb")
446    }
447
448    /// [21] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle LF/NB/ESA
449    /// EXTERNAL: Requires context from outside the message.
450    fn evaluate_21(&self, ctx: &EvaluationContext) -> ConditionResult {
451        ctx.external.evaluate("recipient_is_lf_nb_esa")
452    }
453
454    /// [22] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle MSB
455    /// EXTERNAL: Requires context from outside the message.
456    fn evaluate_22(&self, ctx: &EvaluationContext) -> ConditionResult {
457        ctx.external.evaluate("recipient_is_msb")
458    }
459
460    /// [23] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle NB/ÜNB
461    /// EXTERNAL: Requires context from outside the message.
462    fn evaluate_23(&self, ctx: &EvaluationContext) -> ConditionResult {
463        ctx.external.evaluate("recipient_is_nb_uenb")
464    }
465
466    /// [24] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle NB/LF/MSB/ESA
467    /// EXTERNAL: Requires context from outside the message.
468    fn evaluate_24(&self, ctx: &EvaluationContext) -> ConditionResult {
469        ctx.external.evaluate("recipient_is_nb_lf_msb_esa")
470    }
471
472    /// [25] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle NB
473    /// EXTERNAL: Requires context from outside the message.
474    fn evaluate_25(&self, ctx: &EvaluationContext) -> ConditionResult {
475        ctx.external.evaluate("recipient_is_nb")
476    }
477
478    /// [26] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle NB/LF/BKV/BIKO
479    /// EXTERNAL: Requires context from outside the message.
480    fn evaluate_26(&self, ctx: &EvaluationContext) -> ConditionResult {
481        ctx.external.evaluate("recipient_is_nb_lf_bkv_biko")
482    }
483
484    /// [27] Wenn SG4 NAD+Z31 (Übertragungsnetzbetreiber) DE3207 mit Code „DE“ vorhanden
485    fn evaluate_27(&self, ctx: &EvaluationContext) -> ConditionResult {
486        ctx.has_qualified_value("NAD", 0, "Z31", 8, 0, &["DE"])
487    }
488
489    /// [28] Wenn SG4 NAD+Z34 (Bilanzkoordinator) DE3207 mit Code „DE“ vorhanden
490    fn evaluate_28(&self, ctx: &EvaluationContext) -> ConditionResult {
491        ctx.has_qualified_value("NAD", 0, "Z34", 8, 0, &["DE"])
492    }
493
494    /// [29] Wenn SG4 NAD+Z35 (Bilanzkreisverantwortlicher) DE3207 mit Code „DE“ vorhanden
495    fn evaluate_29(&self, ctx: &EvaluationContext) -> ConditionResult {
496        ctx.has_qualified_value("NAD", 0, "Z35", 8, 0, &["DE"])
497    }
498
499    /// [30] Wenn SG4 NAD+Z36 (Energieserviceanbieter) DE3207 mit Code „DE“ vorhanden
500    fn evaluate_30(&self, ctx: &EvaluationContext) -> ConditionResult {
501        ctx.has_qualified_value("NAD", 0, "Z36", 8, 0, &["DE"])
502    }
503
504    /// [31] Wenn SG4 NAD+Z31 (Übertragungsnetzbetreiber) DE3207 mit Code „DE“ nicht vorhanden
505    fn evaluate_31(&self, ctx: &EvaluationContext) -> ConditionResult {
506        match ctx.has_qualified_value("NAD", 0, "Z31", 8, 0, &["DE"]) {
507            ConditionResult::True => ConditionResult::False,
508            ConditionResult::False => ConditionResult::True,
509            ConditionResult::Unknown => ConditionResult::Unknown,
510        }
511    }
512
513    /// [32] Wenn SG4 NAD+Z34 (Bilanzkoordinator) DE3207 mit Code „DE“ nicht vorhanden
514    fn evaluate_32(&self, ctx: &EvaluationContext) -> ConditionResult {
515        let nads = ctx.find_segments_with_qualifier("NAD", 0, "Z34");
516        if nads.is_empty() {
517            return ConditionResult::True;
518        }
519        let has_de = nads.iter().any(|s| {
520            s.elements
521                .get(8)
522                .and_then(|e| e.first())
523                .is_some_and(|v| v == "DE")
524        });
525        ConditionResult::from(!has_de)
526    }
527
528    /// [33] Wenn SG4 NAD+Z35 (Bilanzkreisverantwortlicher) DE3207 mit Code „DE“ nicht vorhanden
529    fn evaluate_33(&self, ctx: &EvaluationContext) -> ConditionResult {
530        let nads = ctx.find_segments_with_qualifier("NAD", 0, "Z35");
531        if nads.is_empty() {
532            return ConditionResult::True;
533        }
534        let has_de = nads.iter().any(|s| {
535            s.elements
536                .get(8)
537                .and_then(|e| e.first())
538                .is_some_and(|v| v == "DE")
539        });
540        ConditionResult::from(!has_de)
541    }
542
543    /// [34] Wenn SG4 NAD+Z36 (Energieserviceanbieter) DE3207 mit Code „DE“ nicht vorhanden
544    fn evaluate_34(&self, ctx: &EvaluationContext) -> ConditionResult {
545        let nads = ctx.find_segments_with_qualifier("NAD", 0, "Z36");
546        if nads.is_empty() {
547            return ConditionResult::True;
548        }
549        let has_de = nads.iter().any(|s| {
550            s.elements
551                .get(8)
552                .and_then(|e| e.first())
553                .is_some_and(|v| v == "DE")
554        });
555        ConditionResult::from(!has_de)
556    }
557
558    /// [35] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle ÜNB
559    /// EXTERNAL: Requires context from outside the message.
560    fn evaluate_35(&self, ctx: &EvaluationContext) -> ConditionResult {
561        ctx.external.evaluate("recipient_is_uenb")
562    }
563
564    /// [36] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle BKV
565    /// EXTERNAL: Requires context from outside the message.
566    fn evaluate_36(&self, ctx: &EvaluationContext) -> ConditionResult {
567        ctx.external.evaluate("recipient_is_bkv")
568    }
569
570    /// [490] wenn Wert in diesem DE, an der Stelle CCYYMMDD ein Datum aus dem angegeben Zeitraum der Tabelle Kapitel 3.5 „Prozesszeitpunkt bei MESZ mit UTC“ ist
571    fn evaluate_490(&self, ctx: &EvaluationContext) -> ConditionResult {
572        // wenn Wert in diesem DE an Stelle CCYYMMDD ein Datum aus Tabelle Kapitel 3.5 'Prozesszeitpunkt bei MESZ mit UTC' ist
573        let dtm_segs = ctx.find_segments("DTM");
574        match dtm_segs
575            .first()
576            .and_then(|s| s.elements.first())
577            .and_then(|e| e.get(1))
578        {
579            Some(val) => is_mesz_utc(val),
580            None => ConditionResult::False, // segment absent → condition not applicable
581        }
582    }
583
584    /// [491] wenn Wert in diesem DE, an der Stelle CCYYMMDD ein Datum aus dem angegeben Zeitraum der Tabelle Kapitel 3.6 „Prozesszeitpunkt bei MEZ mit UTC“ ist
585    fn evaluate_491(&self, ctx: &EvaluationContext) -> ConditionResult {
586        let dtm_segs = ctx.find_segments("DTM");
587        match dtm_segs
588            .first()
589            .and_then(|s| s.elements.first())
590            .and_then(|e| e.get(1))
591        {
592            Some(val) => is_mez_utc(val),
593            None => ConditionResult::False, // segment absent → condition not applicable
594        }
595    }
596
597    /// [494] Das hier genannte Datum muss der Zeitpunkt sein, zu dem das Dokument erstellt wurde, oder ein Zeitpunkt, der davor liegt.
598    // REVIEW: This condition states the referenced date must be the document creation timestamp or earlier. Verifying this would require knowing the actual document creation time as an external reference point, which is not present in the EDIFACT message itself. The phrasing describes a semantic constraint on the field's value origin rather than a checkable boolean predicate from message content. Treated as an always-true informational annotation similar to a Hinweis, since the field by definition carries the value the sender chose as the document date. (medium confidence)
599    fn evaluate_494(&self, _ctx: &EvaluationContext) -> ConditionResult {
600        // Hinweis: Das hier genannte Datum muss der Zeitpunkt sein, zu dem das Dokument erstellt wurde, oder ein Zeitpunkt, der davor liegt.
601        // This is a semantic annotation about what the date field must represent (document creation time or earlier).
602        // It cannot be evaluated as a boolean predicate from the EDIFACT message content alone.
603        ConditionResult::True
604    }
605
606    /// [501] Hinweis: Es darf kein Name einer natürlichen Person übermittelt werden, stattdessen ist die organisatorische Einheit im Unternehmen zu nennen.
607    fn evaluate_501(&self, _ctx: &EvaluationContext) -> ConditionResult {
608        // Hinweis: Es darf kein Name einer natürlichen Person übermittelt werden, stattdessen ist die organisatorische Einheit im Unternehmen zu nennen.
609        // Informational note about data privacy — no natural person names, use organisational unit — always applies.
610        ConditionResult::True
611    }
612
613    /// [502] Hinweis: Es darf nur eine Information im DE3148 übermittelt werden
614    fn evaluate_502(&self, _ctx: &EvaluationContext) -> ConditionResult {
615        // Hinweis: Es darf nur eine Information im DE3148 übermittelt werden.
616        // Informational note about cardinality of DE3148 — only one value may be transmitted — always applies.
617        ConditionResult::True
618    }
619
620    /// [503] Hinweis: Angabe erfolgt in gesetzlicher deutscher Zeit
621    fn evaluate_503(&self, _ctx: &EvaluationContext) -> ConditionResult {
622        // Hinweis: Angabe erfolgt in gesetzlicher deutscher Zeit — informational note, always applies
623        ConditionResult::True
624    }
625
626    /// [504] Hinweis: Es ist mindestens die Umsatzsteuer- bzw. Steuernummer zu nennen, die in der INVOIC genutzt wird.
627    fn evaluate_504(&self, _ctx: &EvaluationContext) -> ConditionResult {
628        // Hinweis: Es ist mindestens die Umsatzsteuer- bzw. Steuernummer zu nennen — informational note, always applies
629        ConditionResult::True
630    }
631
632    /// [505] Wenn eine Vorgängerversion (RFF+ACW) angegeben ist, so muss der Wert in diesem DE1056 mindestens um 1 höher sein, als der Wert aus DE1056 der Vorgängerversion (RFF+ACW).
633    // REVIEW: When RFF+ACW (predecessor version) is present, compare DE1056 (elements[0][3]) of RFF+AGK (current version) against DE1056 of RFF+ACW. Condition is True when current version is at least 1 higher than predecessor. Returns False when no ACW present (condition does not apply), Unknown if version numbers cannot be parsed. (medium confidence)
634    fn evaluate_505(&self, ctx: &EvaluationContext) -> ConditionResult {
635        let acw_segments = ctx.find_segments_with_qualifier("RFF", 0, "ACW");
636        if acw_segments.is_empty() {
637            return ConditionResult::False;
638        }
639        let agk_segments = ctx.find_segments_with_qualifier("RFF", 0, "AGK");
640        let current_version = agk_segments
641            .first()
642            .and_then(|s| s.elements.first())
643            .and_then(|e| e.get(3))
644            .and_then(|v| v.parse::<i64>().ok());
645        let predecessor_version = acw_segments
646            .first()
647            .and_then(|s| s.elements.first())
648            .and_then(|e| e.get(3))
649            .and_then(|v| v.parse::<i64>().ok());
650        match (current_version, predecessor_version) {
651            (Some(cur), Some(pred)) => ConditionResult::from(cur >= pred + 1),
652            _ => ConditionResult::Unknown,
653        }
654    }
655
656    /// [506] Hinweis: Das Datenelement ist so zu füllen, dass sein Inhalt den Vorgaben des USt.-Gesetzes genügt, so dass der Empfänger diese Daten in einer INVOIC nutzen kann.
657    fn evaluate_506(&self, _ctx: &EvaluationContext) -> ConditionResult {
658        // Hinweis: Das Datenelement ist so zu füllen, dass sein Inhalt den Vorgaben des USt.-Gesetzes genügt — informational note, always applies
659        ConditionResult::True
660    }
661
662    /// [508] Hinweis: Der LF in seiner Funktion als Grund- und Ersatzversorger muss den NB, in deren Netzgebiet der LF als Grund- und Ersatzversorger ist, einen Bilanzkreis für verbrauchende Marktlokationen ü...
663    fn evaluate_508(&self, _ctx: &EvaluationContext) -> ConditionResult {
664        // Hinweis: Der LF als Grund- und Ersatzversorger muss dem NB einen Bilanzkreis übermitteln — informational note, always applies
665        ConditionResult::True
666    }
667
668    /// [908] Format: Mögliche Werte: 1 bis n
669    fn evaluate_908(&self, _ctx: &EvaluationContext) -> ConditionResult {
670        // Format: Mögliche Werte: 1 bis n — informational cardinality note, always applies
671        ConditionResult::True
672    }
673
674    /// [931] Format: ZZZ = +00
675    fn evaluate_931(&self, ctx: &EvaluationContext) -> ConditionResult {
676        // Format: ZZZ = +00 — DTM timezone must be UTC
677        let dtm_segs = ctx.find_segments("DTM");
678        match dtm_segs
679            .first()
680            .and_then(|s| s.elements.first())
681            .and_then(|e| e.get(1))
682        {
683            Some(val) => validate_timezone_utc(val),
684            None => ConditionResult::False, // segment absent → condition not applicable
685        }
686    }
687
688    /// [932] Format: HHMM = 2200
689    fn evaluate_932(&self, ctx: &EvaluationContext) -> ConditionResult {
690        // Format: HHMM = 2200 — time portion of DTM value must be 2200
691        let dtm_segs = ctx.find_segments("DTM");
692        match dtm_segs
693            .first()
694            .and_then(|s| s.elements.first())
695            .and_then(|e| e.get(1))
696        {
697            Some(val) => validate_hhmm_equals(val, "2200"),
698            None => ConditionResult::False, // segment absent → condition not applicable
699        }
700    }
701
702    /// [933] Format: HHMM = 2300
703    fn evaluate_933(&self, ctx: &EvaluationContext) -> ConditionResult {
704        // Format: HHMM = 2300 — time portion of DTM value must be 2300
705        let dtm_segs = ctx.find_segments("DTM");
706        match dtm_segs
707            .first()
708            .and_then(|s| s.elements.first())
709            .and_then(|e| e.get(1))
710        {
711            Some(val) => validate_hhmm_equals(val, "2300"),
712            None => ConditionResult::False, // segment absent → condition not applicable
713        }
714    }
715
716    /// [939] Format: Die Zeichenkette muss die Zeichen @ und . enthalten
717    fn evaluate_939(&self, ctx: &EvaluationContext) -> ConditionResult {
718        // Format: string must contain @ and . — email address validation
719        let segs = ctx.find_segments("COM");
720        match segs
721            .first()
722            .and_then(|s| s.elements.first())
723            .and_then(|e| e.first())
724        {
725            Some(val) => validate_email(val),
726            None => ConditionResult::False, // segment absent → condition not applicable
727        }
728    }
729
730    /// [940] Format: Die Zeichenkette muss mit dem Zeichen + beginnen und danach dürfen nur noch Ziffern folgen
731    fn evaluate_940(&self, ctx: &EvaluationContext) -> ConditionResult {
732        // Format: string must start with + followed only by digits — phone number validation
733        let segs = ctx.find_segments("COM");
734        match segs
735            .first()
736            .and_then(|s| s.elements.first())
737            .and_then(|e| e.first())
738        {
739            Some(val) => validate_phone(val),
740            None => ConditionResult::False, // segment absent → condition not applicable
741        }
742    }
743}