Skip to main content

automapper_validation/generated/fv2510/
ordrsp_conditions_fv2510.rs

1// <auto-generated>
2// Generated by automapper-generator generate-conditions
3// AHB: xml-migs-and-ahbs/FV2510/ORDRSP_AHB_1_1_Fehlerkorrektur_20250417.xml
4// Generated: 2026-03-12T10:41:52Z
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::{Cluster, ConditionEvaluator, ConditionResult, EvaluationContext};
15// HAND-EDITED: shared cluster helpers for conditions [17]/[18].
16// Preserve across regeneration — see CLAUDE.md "Codelist Providers".
17use crate::eval::ebd_cluster::resolved_sts_code_in_cluster;
18
19/// Generated condition evaluator for ORDRSP FV2510.
20pub struct OrdrspConditionEvaluatorFV2510 {
21    // External condition IDs that require runtime context.
22    external_conditions: std::collections::HashSet<u32>,
23}
24
25impl Default for OrdrspConditionEvaluatorFV2510 {
26    fn default() -> Self {
27        let mut external_conditions = std::collections::HashSet::new();
28        external_conditions.insert(3);
29        external_conditions.insert(4);
30        external_conditions.insert(5);
31        external_conditions.insert(7);
32        external_conditions.insert(9);
33        external_conditions.insert(10);
34        external_conditions.insert(12);
35        external_conditions.insert(13);
36        external_conditions.insert(14);
37        external_conditions.insert(15);
38        external_conditions.insert(16);
39        // HAND-EDITED: [17]/[18] are no longer external — they now read
40        // the EBD cluster lookup directly. See FV2504 counterpart.
41        // external_conditions.insert(17);
42        // external_conditions.insert(18);
43        external_conditions.insert(29);
44        external_conditions.insert(30);
45        external_conditions.insert(31);
46        external_conditions.insert(32);
47        external_conditions.insert(40);
48        external_conditions.insert(49);
49        external_conditions.insert(52);
50        external_conditions.insert(60);
51        external_conditions.insert(70);
52        external_conditions.insert(71);
53        external_conditions.insert(75);
54        external_conditions.insert(492);
55        external_conditions.insert(493);
56        Self {
57            external_conditions,
58        }
59    }
60}
61
62impl ConditionEvaluator for OrdrspConditionEvaluatorFV2510 {
63    fn message_type(&self) -> &str {
64        "ORDRSP"
65    }
66
67    fn format_version(&self) -> &str {
68        "FV2510"
69    }
70
71    fn evaluate(&self, condition: u32, ctx: &EvaluationContext) -> ConditionResult {
72        match condition {
73            1 => self.evaluate_1(ctx),
74            3 => self.evaluate_3(ctx),
75            4 => self.evaluate_4(ctx),
76            5 => self.evaluate_5(ctx),
77            7 => self.evaluate_7(ctx),
78            9 => self.evaluate_9(ctx),
79            10 => self.evaluate_10(ctx),
80            11 => self.evaluate_11(ctx),
81            12 => self.evaluate_12(ctx),
82            13 => self.evaluate_13(ctx),
83            14 => self.evaluate_14(ctx),
84            15 => self.evaluate_15(ctx),
85            16 => self.evaluate_16(ctx),
86            17 => self.evaluate_17(ctx),
87            18 => self.evaluate_18(ctx),
88            21 => self.evaluate_21(ctx),
89            22 => self.evaluate_22(ctx),
90            23 => self.evaluate_23(ctx),
91            24 => self.evaluate_24(ctx),
92            25 => self.evaluate_25(ctx),
93            27 => self.evaluate_27(ctx),
94            28 => self.evaluate_28(ctx),
95            29 => self.evaluate_29(ctx),
96            30 => self.evaluate_30(ctx),
97            31 => self.evaluate_31(ctx),
98            32 => self.evaluate_32(ctx),
99            33 => self.evaluate_33(ctx),
100            34 => self.evaluate_34(ctx),
101            37 => self.evaluate_37(ctx),
102            38 => self.evaluate_38(ctx),
103            39 => self.evaluate_39(ctx),
104            40 => self.evaluate_40(ctx),
105            41 => self.evaluate_41(ctx),
106            42 => self.evaluate_42(ctx),
107            43 => self.evaluate_43(ctx),
108            44 => self.evaluate_44(ctx),
109            45 => self.evaluate_45(ctx),
110            46 => self.evaluate_46(ctx),
111            47 => self.evaluate_47(ctx),
112            48 => self.evaluate_48(ctx),
113            49 => self.evaluate_49(ctx),
114            50 => self.evaluate_50(ctx),
115            51 => self.evaluate_51(ctx),
116            52 => self.evaluate_52(ctx),
117            53 => self.evaluate_53(ctx),
118            54 => self.evaluate_54(ctx),
119            55 => self.evaluate_55(ctx),
120            56 => self.evaluate_56(ctx),
121            57 => self.evaluate_57(ctx),
122            58 => self.evaluate_58(ctx),
123            59 => self.evaluate_59(ctx),
124            60 => self.evaluate_60(ctx),
125            61 => self.evaluate_61(ctx),
126            62 => self.evaluate_62(ctx),
127            63 => self.evaluate_63(ctx),
128            64 => self.evaluate_64(ctx),
129            65 => self.evaluate_65(ctx),
130            66 => self.evaluate_66(ctx),
131            67 => self.evaluate_67(ctx),
132            68 => self.evaluate_68(ctx),
133            69 => self.evaluate_69(ctx),
134            70 => self.evaluate_70(ctx),
135            71 => self.evaluate_71(ctx),
136            72 => self.evaluate_72(ctx),
137            73 => self.evaluate_73(ctx),
138            74 => self.evaluate_74(ctx),
139            75 => self.evaluate_75(ctx),
140            76 => self.evaluate_76(ctx),
141            77 => self.evaluate_77(ctx),
142            78 => self.evaluate_78(ctx),
143            79 => self.evaluate_79(ctx),
144            80 => self.evaluate_80(ctx),
145            81 => self.evaluate_81(ctx),
146            82 => self.evaluate_82(ctx),
147            83 => self.evaluate_83(ctx),
148            490 => self.evaluate_490(ctx),
149            491 => self.evaluate_491(ctx),
150            492 => self.evaluate_492(ctx),
151            493 => self.evaluate_493(ctx),
152            494 => self.evaluate_494(ctx),
153            500 => self.evaluate_500(ctx),
154            503 => self.evaluate_503(ctx),
155            504 => self.evaluate_504(ctx),
156            513 => self.evaluate_513(ctx),
157            518 => self.evaluate_518(ctx),
158            519 => self.evaluate_519(ctx),
159            520 => self.evaluate_520(ctx),
160            521 => self.evaluate_521(ctx),
161            522 => self.evaluate_522(ctx),
162            523 => self.evaluate_523(ctx),
163            524 => self.evaluate_524(ctx),
164            525 => self.evaluate_525(ctx),
165            526 => self.evaluate_526(ctx),
166            527 => self.evaluate_527(ctx),
167            529 => self.evaluate_529(ctx),
168            530 => self.evaluate_530(ctx),
169            533 => self.evaluate_533(ctx),
170            534 => self.evaluate_534(ctx),
171            535 => self.evaluate_535(ctx),
172            536 => self.evaluate_536(ctx),
173            537 => self.evaluate_537(ctx),
174            538 => self.evaluate_538(ctx),
175            539 => self.evaluate_539(ctx),
176            540 => self.evaluate_540(ctx),
177            542 => self.evaluate_542(ctx),
178            543 => self.evaluate_543(ctx),
179            544 => self.evaluate_544(ctx),
180            545 => self.evaluate_545(ctx),
181            546 => self.evaluate_546(ctx),
182            547 => self.evaluate_547(ctx),
183            548 => self.evaluate_548(ctx),
184            902 => self.evaluate_902(ctx),
185            903 => self.evaluate_903(ctx),
186            930 => self.evaluate_930(ctx),
187            931 => self.evaluate_931(ctx),
188            932 => self.evaluate_932(ctx),
189            933 => self.evaluate_933(ctx),
190            934 => self.evaluate_934(ctx),
191            935 => self.evaluate_935(ctx),
192            939 => self.evaluate_939(ctx),
193            940 => self.evaluate_940(ctx),
194            2036 => self.evaluate_2036(ctx),
195            _ => ConditionResult::Unknown,
196        }
197    }
198
199    fn is_external(&self, condition: u32) -> bool {
200        self.external_conditions.contains(&condition)
201    }
202    fn is_known(&self, condition: u32) -> bool {
203        matches!(
204            condition,
205            1 | 3
206                | 4
207                | 5
208                | 7
209                | 9
210                | 10
211                | 11
212                | 12
213                | 13
214                | 14
215                | 15
216                | 16
217                | 17
218                | 18
219                | 21
220                | 22
221                | 23
222                | 24
223                | 25
224                | 27
225                | 28
226                | 29
227                | 30
228                | 31
229                | 32
230                | 33
231                | 34
232                | 37
233                | 38
234                | 39
235                | 40
236                | 41
237                | 42
238                | 43
239                | 44
240                | 45
241                | 46
242                | 47
243                | 48
244                | 49
245                | 50
246                | 51
247                | 52
248                | 53
249                | 54
250                | 55
251                | 56
252                | 57
253                | 58
254                | 59
255                | 60
256                | 61
257                | 62
258                | 63
259                | 64
260                | 65
261                | 66
262                | 67
263                | 68
264                | 69
265                | 70
266                | 71
267                | 72
268                | 73
269                | 74
270                | 75
271                | 76
272                | 77
273                | 78
274                | 79
275                | 80
276                | 81
277                | 82
278                | 83
279                | 490
280                | 491
281                | 492
282                | 493
283                | 494
284                | 500
285                | 503
286                | 504
287                | 513
288                | 518
289                | 519
290                | 520
291                | 521
292                | 522
293                | 523
294                | 524
295                | 525
296                | 526
297                | 527
298                | 529
299                | 530
300                | 533
301                | 534
302                | 535
303                | 536
304                | 537
305                | 538
306                | 539
307                | 540
308                | 542
309                | 543
310                | 544
311                | 545
312                | 546
313                | 547
314                | 548
315                | 902
316                | 903
317                | 930
318                | 931
319                | 932
320                | 933
321                | 934
322                | 935
323                | 939
324                | 940
325                | 2036
326        )
327    }
328}
329
330impl OrdrspConditionEvaluatorFV2510 {
331    /// [7] Wenn MP-ID in SG3 NAD+MR aus Sparte Strom
332    /// EXTERNAL: Requires context from outside the message.
333    fn evaluate_7(&self, ctx: &EvaluationContext) -> ConditionResult {
334        ctx.external.evaluate("recipient_is_strom")
335    }
336
337    /// [13] Wenn MP-ID in SG3 NAD+MR aus Sparte Gas
338    /// EXTERNAL: Requires context from outside the message.
339    fn evaluate_13(&self, ctx: &EvaluationContext) -> ConditionResult {
340        ctx.external.evaluate("recipient_is_gas")
341    }
342
343    /// [52] wenn es sich bei der Reklamation um die Reklamation der ausgerollten Leistungskurvendefinitionen handelte
344    /// EXTERNAL: Requires context from outside the message.
345    fn evaluate_52(&self, ctx: &EvaluationContext) -> ConditionResult {
346        ctx.external
347            .evaluate("reklamation_ausgerollte_leistungskurvendefinitionen")
348    }
349
350    /// [60] wenn es sich bei der Reklamation um die Reklamation der Übersicht der Zählzeitdefinitionen handelte
351    /// EXTERNAL: Requires context from outside the message.
352    fn evaluate_60(&self, ctx: &EvaluationContext) -> ConditionResult {
353        ctx.external
354            .evaluate("reklamation_uebersicht_zaehlzeitdefinitionen")
355    }
356
357    /// [70] wenn es sich bei der Reklamation um die Reklamation der ausgerollten Zählzeitdefinitionen handelte
358    /// EXTERNAL: Requires context from outside the message.
359    fn evaluate_70(&self, ctx: &EvaluationContext) -> ConditionResult {
360        ctx.external
361            .evaluate("reklamation_ausgerollte_zaehlzeitdefinitionen")
362    }
363
364    /// [71] wenn es sich bei der Reklamation um die Reklamation der ausgerollten Schaltzeitdefinitionen handelte
365    /// EXTERNAL: Requires context from outside the message.
366    fn evaluate_71(&self, ctx: &EvaluationContext) -> ConditionResult {
367        ctx.external
368            .evaluate("complaint_is_about_rolled_out_switch_time_definitions")
369    }
370
371    /// [75] Wenn es sich um die Antwort auf eine Bestellung handelt in der ein Messprodukt der Codeliste der Konfigurationen aus dem Kapitel 4.6.2 „Werte nach Typ 2 aus SMGW“ bestellt wurde.
372    /// EXTERNAL: Requires context from outside the message.
373    fn evaluate_75(&self, ctx: &EvaluationContext) -> ConditionResult {
374        ctx.external
375            .evaluate("order_contains_smgw_type2_messprodukt")
376    }
377
378    /// [78] Wenn AJT+A04+E_0279 vorhanden
379    fn evaluate_78(&self, ctx: &EvaluationContext) -> ConditionResult {
380        ctx.has_segment_matching("AJT", &[(0, 0, "A04"), (1, 0, "E_0279")])
381    }
382
383    /// [79] Wenn AJT+A04+E_0283 vorhanden
384    fn evaluate_79(&self, ctx: &EvaluationContext) -> ConditionResult {
385        ctx.has_segment_matching("AJT", &[(0, 0, "A04"), (1, 0, "E_0283")])
386    }
387
388    /// [80] Wenn AJT+A05+E_0279 vorhanden
389    fn evaluate_80(&self, ctx: &EvaluationContext) -> ConditionResult {
390        ctx.has_segment_matching("AJT", &[(0, 0, "A05"), (1, 0, "E_0279")])
391    }
392
393    /// [81] Wenn AJT+A05+E_0283 vorhanden
394    fn evaluate_81(&self, ctx: &EvaluationContext) -> ConditionResult {
395        ctx.has_segment_matching("AJT", &[(0, 0, "A05"), (1, 0, "E_0283")])
396    }
397
398    /// [82] Wenn BGM+Z93 (Bestellung eines Angebots Änderung der Technik der Lokation) vorhanden
399    fn evaluate_82(&self, ctx: &EvaluationContext) -> ConditionResult {
400        ctx.has_qualifier("BGM", 0, "Z93")
401    }
402
403    /// [83] Wenn BGM+Z12 (Änderung der Technik der Lokation) vorhanden
404    fn evaluate_83(&self, ctx: &EvaluationContext) -> ConditionResult {
405        ctx.has_qualifier("BGM", 0, "Z12")
406    }
407
408    /// [513] Hinweis: Wert aus BGM+Z12 (Änderung der Technik der Lokation) DE1004 der ORDERS, mit der die Bestellung erfolgt ist.
409    fn evaluate_513(&self, _ctx: &EvaluationContext) -> ConditionResult {
410        // Hinweis: Wert aus BGM+Z12 (Änderung der Technik der Lokation) DE1004 der ORDERS — informational note, always applies
411        ConditionResult::True
412    }
413
414    /// [543] Hinweis: Wert aus BGM+Z93 (Bestellung eines Angebots Änderung der Technik der Lokation) DE1004 der ORDERS, mit der die Bestellung erfolgt ist.
415    fn evaluate_543(&self, _ctx: &EvaluationContext) -> ConditionResult {
416        // Hinweis: Wert aus BGM+Z93 (Bestellung eines Angebots Änderung der Technik der Lokation) DE1004 der ORDERS — informational note, always applies
417        ConditionResult::True
418    }
419
420    /// [544] Hinweis: Wert aus BGM DE1004 der PRICAT mit der das Preisblatt B des MSB, auf die aus Sicht des MSB das Angebot basiert, übermittelt wurde.
421    fn evaluate_544(&self, _ctx: &EvaluationContext) -> ConditionResult {
422        // Hinweis: Wert aus BGM DE1004 der PRICAT mit der das Preisblatt B des MSB — informational note, always applies
423        ConditionResult::True
424    }
425
426    /// [545] Hinweis: Angabe des Beginnzeitpunkts des realistisch möglichen Umsetzungstermins der zum Zeitpunkt der Ablehnung ermittelt werden kann.
427    fn evaluate_545(&self, _ctx: &EvaluationContext) -> ConditionResult {
428        // Hinweis: Angabe des Beginnzeitpunkts des realistisch möglichen Umsetzungstermins — informational note, always applies
429        ConditionResult::True
430    }
431
432    /// [546] Hinweis: Angabe des Endezeitpunkts des realistisch möglichen Umsetzungstermins der zum Zeitpunkt der Ablehnung ermittelt werden kann.
433    fn evaluate_546(&self, _ctx: &EvaluationContext) -> ConditionResult {
434        // Hinweis: Angabe des Endezeitpunkts des realistisch möglichen Umsetzungstermins — informational note, always applies
435        ConditionResult::True
436    }
437
438    /// [547] Hinweis: Wenn es sich um die Bestellung eines vorherigen Angebots im Rahmen der BDEW Anwendungshilfe "Prozesse zur Änderung der Technik an Lokationen" handelt.
439    fn evaluate_547(&self, _ctx: &EvaluationContext) -> ConditionResult {
440        // Hinweis: Bestellung eines vorherigen Angebots im Rahmen der BDEW Anwendungshilfe 'Prozesse zur Änderung der Technik an Lokationen' — informational note, always applies
441        ConditionResult::True
442    }
443
444    /// [548] Hinweis: Hinweis: wenn es sich um die Beauftragung einer Änderung gemäß WiM Teil1 UC "Messlokationsänderung" handelt.
445    fn evaluate_548(&self, _ctx: &EvaluationContext) -> ConditionResult {
446        // Hinweis: Beauftragung einer Änderung gemäß WiM Teil1 UC 'Messlokationsänderung' — informational note, always applies
447        ConditionResult::True
448    }
449
450    /// [1] Wenn BGM+7 vorhanden
451    fn evaluate_1(&self, ctx: &EvaluationContext) -> ConditionResult {
452        ctx.has_qualifier("BGM", 0, "7")
453    }
454
455    /// [3] Wenn MP-ID in SG3 NAD+MS mit Rolle NB vorhanden
456    /// EXTERNAL: Requires context from outside the message.
457    fn evaluate_3(&self, ctx: &EvaluationContext) -> ConditionResult {
458        ctx.external.evaluate("sender_is_nb")
459    }
460
461    /// [4] Wenn MP-ID in SG3 NAD+MR mit Rolle LF vorhanden
462    /// EXTERNAL: Requires context from outside the message.
463    fn evaluate_4(&self, ctx: &EvaluationContext) -> ConditionResult {
464        ctx.external.evaluate("recipient_is_lf")
465    }
466
467    /// [5] Wenn MP-ID in SG3 NAD+MS mit Rolle LF vorhanden
468    /// EXTERNAL: Requires context from outside the message.
469    fn evaluate_5(&self, ctx: &EvaluationContext) -> ConditionResult {
470        ctx.external.evaluate("sender_is_lf")
471    }
472
473    /// [9] Wenn MP-ID in SG3 NAD+MS mit Rolle LF vorhanden
474    /// EXTERNAL: Requires context from outside the message.
475    fn evaluate_9(&self, ctx: &EvaluationContext) -> ConditionResult {
476        ctx.external.evaluate("sender_is_lf")
477    }
478
479    /// [10] Wenn MP-ID in SG3 NAD+MS mit Rolle MSB vorhanden
480    /// EXTERNAL: Requires context from outside the message.
481    fn evaluate_10(&self, ctx: &EvaluationContext) -> ConditionResult {
482        ctx.external.evaluate("sender_is_msb")
483    }
484
485    /// [11] Wenn AJT+A09+E_0470 vorhanden
486    fn evaluate_11(&self, ctx: &EvaluationContext) -> ConditionResult {
487        ctx.has_qualified_value("AJT", 0, "A09", 1, 0, &["E_0470"])
488    }
489
490    /// [12] Wenn der NB eine unverbindliche Preisinformation angeben kann
491    /// EXTERNAL: Requires context from outside the message.
492    fn evaluate_12(&self, ctx: &EvaluationContext) -> ConditionResult {
493        ctx.external.evaluate("nb_can_provide_price_info")
494    }
495
496    /// [14] Wenn MP-ID in SG3 NAD+MR mit Rolle MSB vorhanden
497    /// EXTERNAL: Requires context from outside the message.
498    fn evaluate_14(&self, ctx: &EvaluationContext) -> ConditionResult {
499        ctx.external.evaluate("recipient_is_msb")
500    }
501
502    /// [15] Wenn MP-ID in SG3 NAD+MR mit Rolle NB vorhanden
503    /// EXTERNAL: Requires context from outside the message.
504    fn evaluate_15(&self, ctx: &EvaluationContext) -> ConditionResult {
505        ctx.external.evaluate("recipient_is_nb")
506    }
507
508    /// [16] Wenn MP-ID in SG3 NAD+MR mit Rolle ÜNB vorhanden
509    /// EXTERNAL: Requires context from outside the message.
510    fn evaluate_16(&self, ctx: &EvaluationContext) -> ConditionResult {
511        ctx.external.evaluate("recipient_is_uenb")
512    }
513
514    /// [17] Der hier angegebene Code des Prüfschritts muss im EBD dem Cluster Zustimmung zugeordnet sein
515    // HAND-EDITED: driven by per-EBD cluster data (mako_prozesse).
516    fn evaluate_17(&self, ctx: &EvaluationContext) -> ConditionResult {
517        resolved_sts_code_in_cluster(ctx, Cluster::is_zustimmung)
518    }
519
520    /// [18] Der hier angegebene Code des Prüfschritts muss im EBD dem Cluster Ablehnung zugeordnet sein
521    // HAND-EDITED: driven by per-EBD cluster data (mako_prozesse).
522    fn evaluate_18(&self, ctx: &EvaluationContext) -> ConditionResult {
523        resolved_sts_code_in_cluster(ctx, Cluster::is_ablehnung)
524    }
525
526    /// [21] Wenn IMD++Z01 vorhanden
527    fn evaluate_21(&self, ctx: &EvaluationContext) -> ConditionResult {
528        ctx.has_qualifier("IMD", 1, "Z01")
529    }
530
531    /// [22] Wenn IMD++Z02 vorhanden
532    fn evaluate_22(&self, ctx: &EvaluationContext) -> ConditionResult {
533        ctx.has_qualifier("IMD", 1, "Z02")
534    }
535
536    /// [23] Wenn IMD++Z03 vorhanden
537    fn evaluate_23(&self, ctx: &EvaluationContext) -> ConditionResult {
538        let segments = ctx.find_segments("IMD");
539        ConditionResult::from(segments.iter().any(|s| {
540            s.elements
541                .get(1)
542                .and_then(|e| e.first())
543                .is_some_and(|v| v == "Z03")
544        }))
545    }
546
547    /// [24] Wenn BGM+Z51 vorhanden
548    fn evaluate_24(&self, ctx: &EvaluationContext) -> ConditionResult {
549        ctx.has_qualifier("BGM", 0, "Z51")
550    }
551
552    /// [25] Wenn BGM+Z52 vorhanden
553    fn evaluate_25(&self, ctx: &EvaluationContext) -> ConditionResult {
554        ctx.has_qualifier("BGM", 0, "Z52")
555    }
556
557    /// [27] Wenn AJT+A05+E_0470 vorhanden
558    fn evaluate_27(&self, ctx: &EvaluationContext) -> ConditionResult {
559        let segments = ctx.find_segments_with_qualifier("AJT", 0, "A05");
560        ConditionResult::from(segments.iter().any(|s| {
561            s.elements
562                .get(1)
563                .and_then(|e| e.first())
564                .is_some_and(|v| v == "E_0470")
565        }))
566    }
567
568    /// [28] Wenn AJT+A99 vorhanden
569    fn evaluate_28(&self, ctx: &EvaluationContext) -> ConditionResult {
570        ctx.has_qualifier("AJT", 0, "A99")
571    }
572
573    /// [29] MP-ID nur aus Sparte Gas
574    /// EXTERNAL: Requires context from outside the message.
575    fn evaluate_29(&self, ctx: &EvaluationContext) -> ConditionResult {
576        ctx.external.evaluate("mp_id_is_gas")
577    }
578
579    /// [30] MP-ID nur aus Sparte Strom
580    /// EXTERNAL: Requires context from outside the message.
581    fn evaluate_30(&self, ctx: &EvaluationContext) -> ConditionResult {
582        ctx.external.evaluate("mp_id_is_strom")
583    }
584
585    /// [31] MP-ID mit Rolle MSB
586    /// EXTERNAL: Requires context from outside the message.
587    fn evaluate_31(&self, ctx: &EvaluationContext) -> ConditionResult {
588        ctx.external.evaluate("mp_id_role_is_msb")
589    }
590
591    /// [32] MP-ID mit Rolle NB
592    /// EXTERNAL: Requires context from outside the message.
593    fn evaluate_32(&self, ctx: &EvaluationContext) -> ConditionResult {
594        ctx.external.evaluate("mp_id_role_is_nb")
595    }
596
597    /// [33] Wenn AJT+A02/A03+E_0488 vorhanden
598    fn evaluate_33(&self, ctx: &EvaluationContext) -> ConditionResult {
599        let segments = ctx.find_segments("AJT");
600        ConditionResult::from(segments.iter().any(|s| {
601            let qual = s
602                .elements
603                .first()
604                .and_then(|e| e.first())
605                .map(|v| v.as_str());
606            let val = s
607                .elements
608                .get(1)
609                .and_then(|e| e.first())
610                .map(|v| v.as_str());
611            matches!(qual, Some("A02") | Some("A03")) && matches!(val, Some("E_0488"))
612        }))
613    }
614
615    /// [34] wenn vorhanden
616    // REVIEW: 'wenn vorhanden' is a generic conditional-use annotation meaning the element should be included whenever the relevant data is available. As a standalone condition without a specific segment target, it functions as a Hinweis-like unconditional True. (medium confidence)
617    fn evaluate_34(&self, _ctx: &EvaluationContext) -> ConditionResult {
618        // 'wenn vorhanden' — generic availability condition: element is conditional on presence of the data
619        // Without a specific segment reference this acts as an unconditional note
620        ConditionResult::True
621    }
622
623    /// [37] Wenn in dieser Nachricht das SG8 CUX+2 vorhanden
624    fn evaluate_37(&self, ctx: &EvaluationContext) -> ConditionResult {
625        ctx.has_qualifier("CUX", 0, "2")
626    }
627
628    /// [38] Möglicher Wert: ZB4 oder ZB5
629    fn evaluate_38(&self, _ctx: &EvaluationContext) -> ConditionResult {
630        // Hinweis: Möglicher Wert: ZB4 oder ZB5 — informational note documenting permitted values
631        ConditionResult::True
632    }
633
634    /// [39] Möglicher Wert: E17 oder Z07
635    fn evaluate_39(&self, _ctx: &EvaluationContext) -> ConditionResult {
636        // Hinweis: Möglicher Wert: E17 oder Z07 — informational note documenting permitted values
637        ConditionResult::True
638    }
639
640    /// [40] Wenn der Code im DE3207 in der "EDI@Energy Codeliste der europäischen Ländercodes" in der Spalte "PLZ vorhanden" ein "X" enthält
641    /// EXTERNAL: Requires context from outside the message.
642    fn evaluate_40(&self, ctx: &EvaluationContext) -> ConditionResult {
643        ctx.external.evaluate("country_has_postal_code")
644    }
645
646    /// [41] wenn SG2 AJT (Einzelheiten zu einer Anpassung/Änderung) DE4465 mit Wert ZB5 vorhanden
647    fn evaluate_41(&self, ctx: &EvaluationContext) -> ConditionResult {
648        ctx.has_qualifier("AJT", 0, "ZB5")
649    }
650
651    /// [42] Wenn SG2 AJT+Z07 (Antwortkategorie: Ablehnung (Keine Berechtigung)) vorhanden
652    fn evaluate_42(&self, ctx: &EvaluationContext) -> ConditionResult {
653        ctx.has_qualifier("AJT", 0, "Z07")
654    }
655
656    /// [43] Wenn AJT+A02/A03+E_1001 vorhanden
657    fn evaluate_43(&self, ctx: &EvaluationContext) -> ConditionResult {
658        let ajts = ctx.find_segments("AJT");
659        let found = ajts.iter().any(|s| {
660            let code = s
661                .elements
662                .first()
663                .and_then(|e| e.first())
664                .map(|v| v.as_str());
665            let pos = s
666                .elements
667                .get(1)
668                .and_then(|e| e.first())
669                .map(|v| v.as_str());
670            matches!(code, Some("A02") | Some("A03")) && matches!(pos, Some("E_1001"))
671        });
672        ConditionResult::from(found)
673    }
674
675    /// [44] Wenn AJT+A05+E_1000 vorhanden
676    fn evaluate_44(&self, ctx: &EvaluationContext) -> ConditionResult {
677        let ajts = ctx.find_segments("AJT");
678        let found = ajts.iter().any(|s| {
679            let code = s
680                .elements
681                .first()
682                .and_then(|e| e.first())
683                .map(|v| v.as_str());
684            let pos = s
685                .elements
686                .get(1)
687                .and_then(|e| e.first())
688                .map(|v| v.as_str());
689            matches!(code, Some("A05")) && matches!(pos, Some("E_1000"))
690        });
691        ConditionResult::from(found)
692    }
693
694    /// [45] Wenn AJT+A09+E_1000 vorhanden
695    fn evaluate_45(&self, ctx: &EvaluationContext) -> ConditionResult {
696        let ajts = ctx.find_segments("AJT");
697        let found = ajts.iter().any(|s| {
698            let code = s
699                .elements
700                .first()
701                .and_then(|e| e.first())
702                .map(|v| v.as_str());
703            let pos = s
704                .elements
705                .get(1)
706                .and_then(|e| e.first())
707                .map(|v| v.as_str());
708            matches!(code, Some("A09")) && matches!(pos, Some("E_1000"))
709        });
710        ConditionResult::from(found)
711    }
712
713    /// [46] Wenn AJT+A06+E_0552 vorhanden
714    fn evaluate_46(&self, ctx: &EvaluationContext) -> ConditionResult {
715        let ajts = ctx.find_segments("AJT");
716        let found = ajts.iter().any(|s| {
717            let code = s
718                .elements
719                .first()
720                .and_then(|e| e.first())
721                .map(|v| v.as_str());
722            let pos = s
723                .elements
724                .get(1)
725                .and_then(|e| e.first())
726                .map(|v| v.as_str());
727            matches!(code, Some("A06")) && matches!(pos, Some("E_0552"))
728        });
729        ConditionResult::from(found)
730    }
731
732    /// [47] Wenn AJT+A06+E_0553 vorhanden
733    fn evaluate_47(&self, ctx: &EvaluationContext) -> ConditionResult {
734        let ajts = ctx.find_segments("AJT");
735        let found = ajts.iter().any(|s| {
736            let code = s
737                .elements
738                .first()
739                .and_then(|e| e.first())
740                .map(|v| v.as_str());
741            let pos = s
742                .elements
743                .get(1)
744                .and_then(|e| e.first())
745                .map(|v| v.as_str());
746            matches!(code, Some("A06")) && matches!(pos, Some("E_0553"))
747        });
748        ConditionResult::from(found)
749    }
750
751    /// [48] Wenn AJT+A06+E_0554 vorhanden
752    fn evaluate_48(&self, ctx: &EvaluationContext) -> ConditionResult {
753        let ajts = ctx.find_segments("AJT");
754        let found = ajts.iter().any(|s| {
755            let code = s
756                .elements
757                .first()
758                .and_then(|e| e.first())
759                .map(|v| v.as_str());
760            let pos = s
761                .elements
762                .get(1)
763                .and_then(|e| e.first())
764                .map(|v| v.as_str());
765            matches!(code, Some("A06")) && matches!(pos, Some("E_0554"))
766        });
767        ConditionResult::from(found)
768    }
769
770    /// [49] nur, wenn in ursprünglicher Nachricht IMD++Z60 (Abbestellung Messprodukt mit Zählzeitdefinition des LF) vorhanden war
771    /// EXTERNAL: Requires context from outside the message.
772    fn evaluate_49(&self, ctx: &EvaluationContext) -> ConditionResult {
773        ctx.external.evaluate("original_order_had_imd_z60")
774    }
775
776    /// [50] wenn im DE3155 in demselben COM der Code EM vorhanden ist
777    fn evaluate_50(&self, ctx: &EvaluationContext) -> ConditionResult {
778        let coms = ctx.find_segments("COM");
779        ConditionResult::from(coms.iter().any(|s| {
780            s.elements
781                .first()
782                .and_then(|e| e.get(1))
783                .map(|v| v == "EM")
784                .unwrap_or(false)
785        }))
786    }
787
788    /// [51] wenn im DE3155 in demselben COM der Code TE / FX / AJ / AL vorhanden ist
789    fn evaluate_51(&self, ctx: &EvaluationContext) -> ConditionResult {
790        let coms = ctx.find_segments("COM");
791        ConditionResult::from(coms.iter().any(|s| {
792            matches!(
793                s.elements
794                    .first()
795                    .and_then(|e| e.get(1))
796                    .map(|v| v.as_str()),
797                Some("TE") | Some("FX") | Some("AJ") | Some("AL")
798            )
799        }))
800    }
801
802    /// [53] Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z59
803    fn evaluate_53(&self, _ctx: &EvaluationContext) -> ConditionResult {
804        // Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z59 — informational note about value origin, always applies
805        ConditionResult::True
806    }
807
808    /// [54] Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z80
809    fn evaluate_54(&self, _ctx: &EvaluationContext) -> ConditionResult {
810        // Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z80 — informational note about value origin, always applies
811        ConditionResult::True
812    }
813
814    /// [55] Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z81
815    fn evaluate_55(&self, _ctx: &EvaluationContext) -> ConditionResult {
816        // Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z81 — informational note about value origin, always applies
817        ConditionResult::True
818    }
819
820    /// [56] wenn SG2 AJT+A02/A03/A06/A07/A10/A11+E_0548 vorhanden
821    fn evaluate_56(&self, ctx: &EvaluationContext) -> ConditionResult {
822        let ajts = ctx.find_segments("AJT");
823        ConditionResult::from(ajts.iter().any(|s| {
824            let de4465 = s
825                .elements
826                .first()
827                .and_then(|e| e.first())
828                .map(|s| s.as_str());
829            let de1082 = s
830                .elements
831                .get(1)
832                .and_then(|e| e.first())
833                .map(|s| s.as_str());
834            matches!(
835                de4465,
836                Some("A02") | Some("A03") | Some("A06") | Some("A07") | Some("A10") | Some("A11")
837            ) && de1082 == Some("E_0548")
838        }))
839    }
840
841    /// [57] wenn SG2 AJT+A02/A03/A06/A07/A10/A11+E_0549 vorhanden
842    fn evaluate_57(&self, ctx: &EvaluationContext) -> ConditionResult {
843        let ajts = ctx.find_segments("AJT");
844        ConditionResult::from(ajts.iter().any(|s| {
845            let de4465 = s
846                .elements
847                .first()
848                .and_then(|e| e.first())
849                .map(|s| s.as_str());
850            let de1082 = s
851                .elements
852                .get(1)
853                .and_then(|e| e.first())
854                .map(|s| s.as_str());
855            matches!(
856                de4465,
857                Some("A02") | Some("A03") | Some("A06") | Some("A07") | Some("A10") | Some("A11")
858            ) && de1082 == Some("E_0549")
859        }))
860    }
861
862    /// [58] wenn SG2 AJT+A02/A03/A06/A07+E_0550 vorhanden
863    fn evaluate_58(&self, ctx: &EvaluationContext) -> ConditionResult {
864        let ajts = ctx.find_segments("AJT");
865        ConditionResult::from(ajts.iter().any(|s| {
866            let de4465 = s
867                .elements
868                .first()
869                .and_then(|e| e.first())
870                .map(|s| s.as_str());
871            let de1082 = s
872                .elements
873                .get(1)
874                .and_then(|e| e.first())
875                .map(|s| s.as_str());
876            matches!(
877                de4465,
878                Some("A02") | Some("A03") | Some("A06") | Some("A07")
879            ) && de1082 == Some("E_0550")
880        }))
881    }
882
883    /// [59] wenn SG2 AJT+A02/A03/A06/A07/A10/A11+E_0551 vorhanden
884    fn evaluate_59(&self, ctx: &EvaluationContext) -> ConditionResult {
885        let ajts = ctx.find_segments("AJT");
886        ConditionResult::from(ajts.iter().any(|s| {
887            let de4465 = s
888                .elements
889                .first()
890                .and_then(|e| e.first())
891                .map(|s| s.as_str());
892            let de1082 = s
893                .elements
894                .get(1)
895                .and_then(|e| e.first())
896                .map(|s| s.as_str());
897            matches!(
898                de4465,
899                Some("A02") | Some("A03") | Some("A06") | Some("A07") | Some("A10") | Some("A11")
900            ) && de1082 == Some("E_0551")
901        }))
902    }
903
904    /// [61] wenn es sich bei der Reklamation um die Reklamation der Übersicht der Schaltzeitdefinitionen handelte
905    // REVIEW: The condition checks whether the complaint concerned the overview of switching time definitions (Schaltzeitdefinitionen). Condition 63 establishes that BGM+Z60 is the code for Schaltzeitdefinitionen in UTILTS, and the ORDRSP BGM code mirrors this type. Checking BGM elements[0][0] == 'Z60' identifies this complaint type. (medium confidence)
906    fn evaluate_61(&self, ctx: &EvaluationContext) -> ConditionResult {
907        // Reklamation der Übersicht der Schaltzeitdefinitionen → ORDRSP with BGM+Z60
908        ctx.has_qualifier("BGM", 0, "Z60")
909    }
910
911    /// [62] wenn es sich bei der Reklamation um die Reklamation der Übersicht der Leistungskurvendefinitionen handelte
912    // REVIEW: The condition checks whether the complaint concerned the overview of load curve definitions (Leistungskurvendefinitionen). Conditions 64 and 65 establish BGM+Z78 and BGM+Z79 as the two related UTILTS codes for Leistungskurven types, so both are checked. (medium confidence)
913    fn evaluate_62(&self, ctx: &EvaluationContext) -> ConditionResult {
914        // Reklamation der Übersicht der Leistungskurvendefinitionen → BGM+Z78 or BGM+Z79
915        let bgm_segs = ctx.find_segments("BGM");
916        match bgm_segs.first() {
917            Some(s) => {
918                let code = s
919                    .elements
920                    .first()
921                    .and_then(|e| e.first())
922                    .map(|v| v.as_str());
923                ConditionResult::from(matches!(code, Some("Z78") | Some("Z79")))
924            }
925            None => ConditionResult::False, // segment absent → condition not applicable
926        }
927    }
928
929    /// [63] Dokumentennummer aus BGM+Z60 DE1004 der UTILTS
930    fn evaluate_63(&self, _ctx: &EvaluationContext) -> ConditionResult {
931        // Hinweis: Dokumentennummer aus BGM+Z60 DE1004 der UTILTS — informational note, always applies
932        ConditionResult::True
933    }
934
935    /// [64] Dokumentennummer aus BGM+Z78 DE1004 der UTILTS
936    fn evaluate_64(&self, _ctx: &EvaluationContext) -> ConditionResult {
937        // Hinweis: Dokumentennummer aus BGM+Z78 DE1004 der UTILTS — informational note, always applies
938        ConditionResult::True
939    }
940
941    /// [65] Dokumentennummer aus BGM+Z79 DE1004 der UTILTS
942    fn evaluate_65(&self, _ctx: &EvaluationContext) -> ConditionResult {
943        // Hinweis: Dokumentennummer aus BGM+Z79 DE1004 der UTILTS — informational note, always applies
944        ConditionResult::True
945    }
946
947    /// [66] wenn SG2 AJT+A01/A02/A03+E_0544 vorhanden
948    fn evaluate_66(&self, ctx: &EvaluationContext) -> ConditionResult {
949        let ajts = ctx.find_segments("AJT");
950        ConditionResult::from(ajts.iter().any(|s| {
951            let de4465 = s
952                .elements
953                .first()
954                .and_then(|e| e.first())
955                .map(|s| s.as_str());
956            let de1082 = s
957                .elements
958                .get(1)
959                .and_then(|e| e.first())
960                .map(|s| s.as_str());
961            matches!(de4465, Some("A01") | Some("A02") | Some("A03")) && de1082 == Some("E_0544")
962        }))
963    }
964
965    /// [67] wenn SG2 AJT+A01/A02/A03+E_0545 vorhanden
966    fn evaluate_67(&self, ctx: &EvaluationContext) -> ConditionResult {
967        let ajts = ctx.find_segments("AJT");
968        ConditionResult::from(ajts.iter().any(|s| {
969            let de4465 = s
970                .elements
971                .first()
972                .and_then(|e| e.first())
973                .map(|s| s.as_str());
974            let de1082 = s
975                .elements
976                .get(1)
977                .and_then(|e| e.first())
978                .map(|s| s.as_str());
979            matches!(de4465, Some("A01") | Some("A02") | Some("A03")) && de1082 == Some("E_0545")
980        }))
981    }
982
983    /// [68] wenn SG2 AJT+A02/A03+E_0546 vorhanden
984    fn evaluate_68(&self, ctx: &EvaluationContext) -> ConditionResult {
985        let ajts = ctx.find_segments("AJT");
986        ConditionResult::from(ajts.iter().any(|s| {
987            let de4465 = s
988                .elements
989                .first()
990                .and_then(|e| e.first())
991                .map(|s| s.as_str());
992            let de1082 = s
993                .elements
994                .get(1)
995                .and_then(|e| e.first())
996                .map(|s| s.as_str());
997            matches!(de4465, Some("A02") | Some("A03")) && de1082 == Some("E_0546")
998        }))
999    }
1000
1001    /// [69] wenn SG2 AJT+A01/A02/A03+E_0547 vorhanden
1002    fn evaluate_69(&self, ctx: &EvaluationContext) -> ConditionResult {
1003        let ajts = ctx.find_segments("AJT");
1004        ConditionResult::from(ajts.iter().any(|s| {
1005            let de4465 = s
1006                .elements
1007                .first()
1008                .and_then(|e| e.first())
1009                .map(|s| s.as_str());
1010            let de1082 = s
1011                .elements
1012                .get(1)
1013                .and_then(|e| e.first())
1014                .map(|s| s.as_str());
1015            matches!(de4465, Some("A01") | Some("A02") | Some("A03")) && de1082 == Some("E_0547")
1016        }))
1017    }
1018
1019    /// [72] wenn AJT+A04+E_0552 vorhanden
1020    fn evaluate_72(&self, ctx: &EvaluationContext) -> ConditionResult {
1021        ctx.has_qualified_value("AJT", 0, "A04", 1, 0, &["E_0552"])
1022    }
1023
1024    /// [73] wenn AJT+A04+E_0553 vorhanden
1025    fn evaluate_73(&self, ctx: &EvaluationContext) -> ConditionResult {
1026        ctx.has_qualified_value("AJT", 0, "A04", 1, 0, &["E_0553"])
1027    }
1028
1029    /// [74] wenn AJT+A04+E_0554 vorhanden
1030    fn evaluate_74(&self, ctx: &EvaluationContext) -> ConditionResult {
1031        ctx.has_qualified_value("AJT", 0, "A04", 1, 0, &["E_0554"])
1032    }
1033
1034    /// [76] Wenn FTX+Z27 (IP-Adresse des Absenders) nicht vorhanden
1035    fn evaluate_76(&self, ctx: &EvaluationContext) -> ConditionResult {
1036        ctx.lacks_qualifier("FTX", 0, "Z27")
1037    }
1038
1039    /// [77] Wenn FTX+Z28 (IP-Range des Absenders) nicht vorhanden
1040    fn evaluate_77(&self, ctx: &EvaluationContext) -> ConditionResult {
1041        ctx.lacks_qualifier("FTX", 0, "Z28")
1042    }
1043
1044    /// [490] wenn Wert in diesem DE, an der Stelle CCYYMMDDHHMM ein Zeitpunkt aus dem angegeben Zeitraum der Tabelle Kapitel 3.5 „Übersicht gesetzliche deutsche Sommerzeit (MESZ)“ der Spalten: „Sommerzei...
1045    fn evaluate_490(&self, ctx: &EvaluationContext) -> ConditionResult {
1046        match ctx.resolved_value {
1047            Some(val) => is_mesz_utc(val),
1048            None => ConditionResult::False,
1049        }
1050    }
1051
1052    /// [491] wenn Wert in diesem DE, an der Stelle CCYYMMDDHHMM ein Zeitpunkt aus dem angegeben Zeitraum der Tabelle Kapitel 3.6 „Übersicht gesetzliche deutsche Zeit (MEZ)“ der Spalten: „Winterzeit (MEZ)...
1053    fn evaluate_491(&self, ctx: &EvaluationContext) -> ConditionResult {
1054        match ctx.resolved_value {
1055            Some(val) => is_mez_utc(val),
1056            None => ConditionResult::False,
1057        }
1058    }
1059
1060    /// [492] wenn MP-ID in NAD+MR aus Sparte Strom
1061    /// EXTERNAL: Requires context from outside the message.
1062    fn evaluate_492(&self, ctx: &EvaluationContext) -> ConditionResult {
1063        ctx.external.evaluate("recipient_is_strom")
1064    }
1065
1066    /// [493] wenn MP-ID in NAD+MR aus Sparte Gas
1067    /// EXTERNAL: Requires context from outside the message.
1068    fn evaluate_493(&self, ctx: &EvaluationContext) -> ConditionResult {
1069        ctx.external.evaluate("recipient_is_gas")
1070    }
1071
1072    /// [494] Das hier genannte Datum muss der Zeitpunkt sein, zu dem das Dokument erstellt wurde, oder ein Zeitpunkt, der davor liegt.
1073    // REVIEW: 'Das hier genannte Datum muss der Zeitpunkt sein, zu dem das Dokument erstellt wurde, oder ein Zeitpunkt, der davor liegt.' This is a constraint description stating the date must be the document creation time or earlier. It functions as an unconditional validation rule (always applies) rather than a conditional trigger. Without knowing which specific DTM qualifier 'here' refers to in the calling context, and since the constraint itself is always applicable, returning True is appropriate. (medium confidence)
1074    fn evaluate_494(&self, _ctx: &EvaluationContext) -> ConditionResult {
1075        ConditionResult::True
1076    }
1077
1078    /// [500] Hinweis: Angabe eines technischen Ansprechpartners für die Geräteübernahme
1079    fn evaluate_500(&self, _ctx: &EvaluationContext) -> ConditionResult {
1080        ConditionResult::True
1081    }
1082
1083    /// [503] Hinweis: Datum, bis zu dem der MSBA zur Fortführung verpflichtet wurde
1084    fn evaluate_503(&self, _ctx: &EvaluationContext) -> ConditionResult {
1085        ConditionResult::True
1086    }
1087
1088    /// [504] Hinweis: Ggf. korrigiert bei einer Zeitangabe in der ORDERS, die außerhalb des max. möglichen Weiterverpflichtungszeitraums ist. Als Antwort wird dann in SG2 AJT Zustimmung mit Terminänderung an...
1089    fn evaluate_504(&self, _ctx: &EvaluationContext) -> ConditionResult {
1090        // Hinweis: Ggf. korrigiert bei einer Zeitangabe in der ORDERS, die außerhalb des max. möglichen Weiterverpflichtungszeitraums ist. Als Antwort wird dann in SG2 AJT Zustimmung mit Terminänderung angegeben.
1091        ConditionResult::True
1092    }
1093
1094    /// [518] Hinweis: Wert aus BGM+Z10 DE1004 der ORDERS, mit der die Bestellung erfolgt ist
1095    fn evaluate_518(&self, _ctx: &EvaluationContext) -> ConditionResult {
1096        // Hinweis: Wert aus BGM+Z10 DE1004 der ORDERS, mit der die Bestellung erfolgt ist.
1097        ConditionResult::True
1098    }
1099
1100    /// [519] Hinweis: Wert aus BGM+7 DE1004 der ORDERS, mit der die Bestellung erfolgt ist.
1101    fn evaluate_519(&self, _ctx: &EvaluationContext) -> ConditionResult {
1102        // Hinweis: Wert aus BGM+7 DE1004 der ORDERS, mit der die Bestellung erfolgt ist.
1103        ConditionResult::True
1104    }
1105
1106    /// [520] Hinweis: Wert aus BGM+Z29 DE1004 der ORDERS, mit der die Anfrage zur Beendigung der Rechnungsabwicklung erfolgt ist.
1107    fn evaluate_520(&self, _ctx: &EvaluationContext) -> ConditionResult {
1108        // Hinweis: Wert aus BGM+Z29 DE1004 der ORDERS, mit der die Anfrage zur Beendigung der Rechnungsabwicklung erfolgt ist.
1109        ConditionResult::True
1110    }
1111
1112    /// [521] Hinweis: Wert aus BGM+Z14/Z61/Z62 DE1004 der ORDERS, mit der die Anforderung von Stammdaten erfolgt ist
1113    fn evaluate_521(&self, _ctx: &EvaluationContext) -> ConditionResult {
1114        // Hinweis: Wert aus BGM+Z14/Z61/Z62 DE1004 der ORDERS, mit der die Anforderung von Stammdaten erfolgt ist
1115        // Informational note — documents that the BGM DE1004 value originates from the original ORDERS request.
1116        ConditionResult::True
1117    }
1118
1119    /// [522] Hinweis: Wert aus BGM+7/Z28/Z48 DE1004 der ORDERS, mit der die Anforderung von Werten erfolgt ist.
1120    fn evaluate_522(&self, _ctx: &EvaluationContext) -> ConditionResult {
1121        // Hinweis: Wert aus BGM+7/Z28/Z48 DE1004 der ORDERS — informational note, always applies
1122        ConditionResult::True
1123    }
1124
1125    /// [523] Hinweis: Wert aus BGM+7 DE1004 der ORDERS, mit der die Anforderung Anforderung von Brennwert und Zustandszahl erfolgt ist.
1126    fn evaluate_523(&self, _ctx: &EvaluationContext) -> ConditionResult {
1127        // Hinweis: Wert aus BGM+7 DE1004 der ORDERS — informational note, always applies
1128        ConditionResult::True
1129    }
1130
1131    /// [524] Hinweis: Wert aus BGM+Z14 DE1004 der ORDERS, mit der die Anfrage vom MSB Gas erfolgt ist.
1132    fn evaluate_524(&self, _ctx: &EvaluationContext) -> ConditionResult {
1133        // Hinweis: Wert aus BGM+Z14 DE1004 der ORDERS — informational note, always applies
1134        ConditionResult::True
1135    }
1136
1137    /// [525] Hinweis: Wert aus BGM+Z24 DE1004 der ORDERS, mit der die Anforderung Allokationsliste erfolgt ist
1138    fn evaluate_525(&self, _ctx: &EvaluationContext) -> ConditionResult {
1139        // Hinweis: Wert aus BGM+Z24 DE1004 der ORDERS — informational note, always applies
1140        ConditionResult::True
1141    }
1142
1143    /// [526] Hinweis: Wert aus BGM+Z23 DE1004 der ORDERS, mit der die Anforderung bilanzierte Menge erfolgt ist
1144    fn evaluate_526(&self, _ctx: &EvaluationContext) -> ConditionResult {
1145        // Hinweis: Wert aus BGM+Z23 DE1004 der ORDERS — informational note, always applies
1146        ConditionResult::True
1147    }
1148
1149    /// [527] Hinweis: Wert aus BGM+Z34 DE1004 der ORDERS, mit der die Reklamation von Werten erfolgt ist.
1150    fn evaluate_527(&self, _ctx: &EvaluationContext) -> ConditionResult {
1151        // Hinweis: Wert aus BGM+Z34 DE1004 der ORDERS, mit der die Reklamation von Werten erfolgt ist. — informational note, always applies
1152        ConditionResult::True
1153    }
1154
1155    /// [529] Hinweis: Dokumentennummer aus BGM DE1004 der ORDERS
1156    fn evaluate_529(&self, _ctx: &EvaluationContext) -> ConditionResult {
1157        // Hinweis: Dokumentennummer aus BGM DE1004 der ORDERS — informational note, always applies
1158        ConditionResult::True
1159    }
1160
1161    /// [530] Hinweis: Dokumentennummer aus BGM DE1004 der ORDCHG
1162    fn evaluate_530(&self, _ctx: &EvaluationContext) -> ConditionResult {
1163        // Hinweis: Dokumentennummer aus BGM DE1004 der ORDCHG — informational note, always applies
1164        ConditionResult::True
1165    }
1166
1167    /// [533] Hinweis: Wert aus BGM+Z51 DE1004 der ORDCHG
1168    fn evaluate_533(&self, _ctx: &EvaluationContext) -> ConditionResult {
1169        // Hinweis: Wert aus BGM+Z51 DE1004 der ORDCHG — informational note, always applies
1170        ConditionResult::True
1171    }
1172
1173    /// [534] Hinweis: Wert aus BGM+Z52 DE1004 der ORDCHG
1174    fn evaluate_534(&self, _ctx: &EvaluationContext) -> ConditionResult {
1175        // Hinweis: Wert aus BGM+Z52 DE1004 der ORDCHG — informational note, always applies
1176        ConditionResult::True
1177    }
1178
1179    /// [535] Hinweis: Wert aus BGM+Z13 DE1004 der ORDERS, mit der die Ankündigung Gerätewechselabsicht erfolgt ist.
1180    fn evaluate_535(&self, _ctx: &EvaluationContext) -> ConditionResult {
1181        // Hinweis: Wert aus BGM+Z13 DE1004 der ORDERS — informational note, always applies
1182        ConditionResult::True
1183    }
1184
1185    /// [536] Hinweis: Es ist die MP-ID des Eigentümers (MSB) zur bilateralen Klärung anzugeben, wenn der angefragte MSB nicht selber der Eigentümer ist.
1186    fn evaluate_536(&self, _ctx: &EvaluationContext) -> ConditionResult {
1187        // Hinweis: MP-ID des Eigentümers (MSB) angeben — informational note, always applies
1188        ConditionResult::True
1189    }
1190
1191    /// [537] Hinweis: Wert aus BGM+Z72 DE1004 der ORDERS, mit der die Bestellung Beendigung der Konfiguration erfolgt ist.
1192    fn evaluate_537(&self, _ctx: &EvaluationContext) -> ConditionResult {
1193        // Hinweis: Wert aus BGM+Z72 DE1004 der ORDERS — informational note, always applies
1194        ConditionResult::True
1195    }
1196
1197    /// [538] Hinweis: Wert aus BGM+Z76 DE1004 der ORDERS, mit der die Reklamation der Konfiguration erfolgt ist.
1198    fn evaluate_538(&self, _ctx: &EvaluationContext) -> ConditionResult {
1199        // Hinweis: Wert aus BGM+Z76 DE1004 der ORDERS — informational note, always applies
1200        ConditionResult::True
1201    }
1202
1203    /// [539] Hinweis: Wert aus BGM+Z73/Z74 DE1004 der ORDERS, mit der die Bestellung der Konfiguration erfolgt ist.
1204    fn evaluate_539(&self, _ctx: &EvaluationContext) -> ConditionResult {
1205        // Hinweis: Wert aus BGM+Z73/Z74 DE1004 der ORDERS — informational note, always applies
1206        ConditionResult::True
1207    }
1208
1209    /// [540] Hinweis: Es darf nur eine Information im DE3148 übermittelt werden
1210    fn evaluate_540(&self, _ctx: &EvaluationContext) -> ConditionResult {
1211        // Hinweis: Es darf nur eine Information im DE3148 übermittelt werden — informational note, always applies
1212        ConditionResult::True
1213    }
1214
1215    /// [542] Hinweis: Wert aus BGM+Z91 DE1004 der ORDERS, mit der die Bestellung Änderung der Abrechnungsdaten erfolgt ist.
1216    fn evaluate_542(&self, _ctx: &EvaluationContext) -> ConditionResult {
1217        // Hinweis: Wert aus BGM+Z91 DE1004 der ORDERS — informational note about value origin, always applies
1218        ConditionResult::True
1219    }
1220
1221    /// [902] Format: Format: Möglicher Wert: ≥ 0
1222    // REVIEW: Format condition requiring numeric value >= 0. Applied to QTY segment value (elements[0][1]) by convention matching the example pattern. Medium confidence because the exact segment this applies to is not specified in the condition text, but QTY is the standard target for quantity format conditions. (medium confidence)
1223    fn evaluate_902(&self, ctx: &EvaluationContext) -> ConditionResult {
1224        ctx.format_check("QTY", 0, 1, |val| validate_numeric(val, ">=", 0.0))
1225    }
1226
1227    /// [903] Format: Möglicher Wert: 1
1228    // REVIEW: Format condition requiring the value to equal exactly 1. Applied to QTY segment value (elements[0][1]) by convention. Medium confidence as the exact target segment is not stated, but QTY quantity value is the standard target for this kind of format constraint. (medium confidence)
1229    fn evaluate_903(&self, ctx: &EvaluationContext) -> ConditionResult {
1230        ctx.format_check("QTY", 0, 1, |val| validate_numeric(val, "==", 1.0))
1231    }
1232
1233    /// [930] Format: max. 2 Nachkommastellen
1234    // REVIEW: Format condition requiring at most 2 decimal places. Applied to QTY segment value (elements[0][1]) following the standard pattern from example 19. Medium confidence as the exact target segment is not specified in the condition text, but QTY quantity value is the canonical target for decimal place constraints. (medium confidence)
1235    fn evaluate_930(&self, ctx: &EvaluationContext) -> ConditionResult {
1236        ctx.format_check("QTY", 0, 1, |val| validate_max_decimal_places(val, 2))
1237    }
1238
1239    /// [931] Format: ZZZ = +00
1240    fn evaluate_931(&self, ctx: &EvaluationContext) -> ConditionResult {
1241        ctx.format_check("DTM", 0, 1, validate_timezone_utc)
1242    }
1243
1244    /// [932] Format: HHMM = 2200
1245    fn evaluate_932(&self, ctx: &EvaluationContext) -> ConditionResult {
1246        ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "2200"))
1247    }
1248
1249    /// [933] Format: HHMM = 2300
1250    fn evaluate_933(&self, ctx: &EvaluationContext) -> ConditionResult {
1251        ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "2300"))
1252    }
1253
1254    /// [934] Format: HHMM = 0400
1255    fn evaluate_934(&self, ctx: &EvaluationContext) -> ConditionResult {
1256        ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "0400"))
1257    }
1258
1259    /// [935] Format: HHMM = 0500
1260    fn evaluate_935(&self, ctx: &EvaluationContext) -> ConditionResult {
1261        ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "0500"))
1262    }
1263
1264    /// [939] Format: Die Zeichenkette muss die Zeichen @ und . enthalten
1265    // REVIEW: Format condition checking that the string contains '@' and '.' — characteristic of an email address format requirement. Applied to COM segment with EM (Electronic Mail) qualifier where elements[0][0] is the address and elements[0][1] is the communication means type code. Returns Unknown when no COM+EM segment is found (condition not applicable). (medium confidence)
1266    fn evaluate_939(&self, ctx: &EvaluationContext) -> ConditionResult {
1267        // Format: string must contain '@' and '.' — email address format check
1268        // Applied to COM segment with EM (Electronic Mail) qualifier
1269        // COM+address:qualifier → elements[0] = ["address", "qualifier"]
1270        let com_segs = ctx.find_segments("COM");
1271        for seg in &com_segs {
1272            if let Some(elem0) = seg.elements.first() {
1273                if elem0.get(1).map(|q| q == "EM").unwrap_or(false) {
1274                    let value = elem0.first().map(|s| s.as_str()).unwrap_or("");
1275                    if value.is_empty() {
1276                        return ConditionResult::Unknown;
1277                    }
1278                    return ConditionResult::from(value.contains('@') && value.contains('.'));
1279                }
1280            }
1281        }
1282        ConditionResult::Unknown
1283    }
1284
1285    /// [940] Format: Die Zeichenkette muss mit dem Zeichen + beginnen und danach dürfen nur noch Ziffern folgen
1286    // REVIEW: Format condition checking that the string starts with '+' and contains only digits afterwards — the international phone number format (e.g. +4912345678). Applied to COM segments with phone-type qualifiers (TE=Telephone, FX=Telefax, AH=After Hours). Returns Unknown when no COM segment with a phone qualifier is found. Requires at least one digit after '+' (len > 1) since a bare '+' is not a valid phone number. (medium confidence)
1287    fn evaluate_940(&self, ctx: &EvaluationContext) -> ConditionResult {
1288        // Format: string must start with '+' and be followed only by digits — international phone number format
1289        // Applied to COM segments with phone-type qualifiers: TE (Telephone), FX (Telefax), AH (After Hours)
1290        // COM+number:qualifier → elements[0] = ["number", "qualifier"]
1291        let com_segs = ctx.find_segments("COM");
1292        for seg in &com_segs {
1293            if let Some(elem0) = seg.elements.first() {
1294                let qualifier = elem0.get(1).map(|s| s.as_str()).unwrap_or("");
1295                if matches!(qualifier, "TE" | "FX" | "AH") {
1296                    let value = elem0.first().map(|s| s.as_str()).unwrap_or("");
1297                    if value.is_empty() {
1298                        return ConditionResult::Unknown;
1299                    }
1300                    return ConditionResult::from(
1301                        value.starts_with('+')
1302                            && value.len() > 1
1303                            && value[1..].chars().all(|c| c.is_ascii_digit()),
1304                    );
1305                }
1306            }
1307        }
1308        ConditionResult::Unknown
1309    }
1310
1311    /// [2036] Pro Nachricht ist die SG27 genau einmal anzugeben
1312    // REVIEW: Cardinality condition requiring SG27 to appear exactly once per message. SG27 is the transaction group (tx_group) in ORDRSP FV2510. Uses the group navigator to count SG27 instances at the top level. Falls back to Unknown when no navigator is available (e.g., when context is used without a pre-assembled tree). This is a structural cardinality rule rather than a content condition. (medium confidence)
1313    fn evaluate_2036(&self, ctx: &EvaluationContext) -> ConditionResult {
1314        // SG27 must appear exactly once per message
1315        // SG27 is the transaction group (tx_group) in ORDRSP
1316        if let Some(nav) = ctx.navigator() {
1317            let count = nav.group_instance_count(&["SG27"]);
1318            ConditionResult::from(count == 1)
1319        } else {
1320            ConditionResult::Unknown
1321        }
1322    }
1323}