Skip to main content

automapper_validation/generated/fv2510/
partin_conditions_fv2510.rs

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