Skip to main content

automapper_validation/generated/fv2604/
orders_conditions_fv2604.rs

1// <auto-generated>
2// Generated by automapper-generator generate-conditions
3// AHB: xml-migs-and-ahbs/FV2604/ORDERS_AHB_1_1a_20251001.xml
4// Generated: 2026-03-12T11:38:53Z
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 ORDERS FV2604.
12pub struct OrdersConditionEvaluatorFV2604 {
13    // External condition IDs that require runtime context.
14    external_conditions: std::collections::HashSet<u32>,
15}
16
17impl Default for OrdersConditionEvaluatorFV2604 {
18    fn default() -> Self {
19        let mut external_conditions = std::collections::HashSet::new();
20        external_conditions.insert(6);
21        external_conditions.insert(7);
22        external_conditions.insert(9);
23        external_conditions.insert(15);
24        external_conditions.insert(16);
25        external_conditions.insert(17);
26        external_conditions.insert(23);
27        external_conditions.insert(26);
28        external_conditions.insert(27);
29        external_conditions.insert(28);
30        external_conditions.insert(29);
31        external_conditions.insert(36);
32        external_conditions.insert(45);
33        external_conditions.insert(60);
34        external_conditions.insert(61);
35        external_conditions.insert(62);
36        external_conditions.insert(63);
37        external_conditions.insert(76);
38        external_conditions.insert(78);
39        external_conditions.insert(82);
40        external_conditions.insert(86);
41        external_conditions.insert(91);
42        external_conditions.insert(95);
43        external_conditions.insert(96);
44        external_conditions.insert(100);
45        external_conditions.insert(101);
46        external_conditions.insert(104);
47        external_conditions.insert(105);
48        external_conditions.insert(125);
49        external_conditions.insert(126);
50        external_conditions.insert(127);
51        external_conditions.insert(128);
52        external_conditions.insert(129);
53        external_conditions.insert(131);
54        external_conditions.insert(132);
55        external_conditions.insert(133);
56        external_conditions.insert(140);
57        external_conditions.insert(141);
58        external_conditions.insert(142);
59        external_conditions.insert(143);
60        external_conditions.insert(152);
61        external_conditions.insert(153);
62        external_conditions.insert(154);
63        external_conditions.insert(155);
64        external_conditions.insert(156);
65        external_conditions.insert(157);
66        external_conditions.insert(158);
67        external_conditions.insert(159);
68        external_conditions.insert(160);
69        external_conditions.insert(162);
70        external_conditions.insert(164);
71        external_conditions.insert(165);
72        external_conditions.insert(166);
73        external_conditions.insert(178);
74        external_conditions.insert(180);
75        external_conditions.insert(183);
76        external_conditions.insert(492);
77        external_conditions.insert(493);
78        Self {
79            external_conditions,
80        }
81    }
82}
83
84impl ConditionEvaluator for OrdersConditionEvaluatorFV2604 {
85    fn message_type(&self) -> &str {
86        "ORDERS"
87    }
88
89    fn format_version(&self) -> &str {
90        "FV2604"
91    }
92
93    fn evaluate(&self, condition: u32, ctx: &EvaluationContext) -> ConditionResult {
94        match condition {
95            1 => self.evaluate_1(ctx),
96            2 => self.evaluate_2(ctx),
97            6 => self.evaluate_6(ctx),
98            7 => self.evaluate_7(ctx),
99            9 => self.evaluate_9(ctx),
100            12 => self.evaluate_12(ctx),
101            13 => self.evaluate_13(ctx),
102            15 => self.evaluate_15(ctx),
103            16 => self.evaluate_16(ctx),
104            17 => self.evaluate_17(ctx),
105            18 => self.evaluate_18(ctx),
106            19 => self.evaluate_19(ctx),
107            21 => self.evaluate_21(ctx),
108            23 => self.evaluate_23(ctx),
109            24 => self.evaluate_24(ctx),
110            26 => self.evaluate_26(ctx),
111            27 => self.evaluate_27(ctx),
112            28 => self.evaluate_28(ctx),
113            29 => self.evaluate_29(ctx),
114            33 => self.evaluate_33(ctx),
115            34 => self.evaluate_34(ctx),
116            35 => self.evaluate_35(ctx),
117            36 => self.evaluate_36(ctx),
118            38 => self.evaluate_38(ctx),
119            45 => self.evaluate_45(ctx),
120            46 => self.evaluate_46(ctx),
121            47 => self.evaluate_47(ctx),
122            51 => self.evaluate_51(ctx),
123            54 => self.evaluate_54(ctx),
124            55 => self.evaluate_55(ctx),
125            56 => self.evaluate_56(ctx),
126            57 => self.evaluate_57(ctx),
127            60 => self.evaluate_60(ctx),
128            61 => self.evaluate_61(ctx),
129            62 => self.evaluate_62(ctx),
130            63 => self.evaluate_63(ctx),
131            64 => self.evaluate_64(ctx),
132            65 => self.evaluate_65(ctx),
133            67 => self.evaluate_67(ctx),
134            68 => self.evaluate_68(ctx),
135            69 => self.evaluate_69(ctx),
136            70 => self.evaluate_70(ctx),
137            76 => self.evaluate_76(ctx),
138            77 => self.evaluate_77(ctx),
139            78 => self.evaluate_78(ctx),
140            79 => self.evaluate_79(ctx),
141            80 => self.evaluate_80(ctx),
142            81 => self.evaluate_81(ctx),
143            82 => self.evaluate_82(ctx),
144            83 => self.evaluate_83(ctx),
145            84 => self.evaluate_84(ctx),
146            85 => self.evaluate_85(ctx),
147            86 => self.evaluate_86(ctx),
148            87 => self.evaluate_87(ctx),
149            91 => self.evaluate_91(ctx),
150            93 => self.evaluate_93(ctx),
151            94 => self.evaluate_94(ctx),
152            95 => self.evaluate_95(ctx),
153            96 => self.evaluate_96(ctx),
154            97 => self.evaluate_97(ctx),
155            99 => self.evaluate_99(ctx),
156            100 => self.evaluate_100(ctx),
157            101 => self.evaluate_101(ctx),
158            102 => self.evaluate_102(ctx),
159            103 => self.evaluate_103(ctx),
160            104 => self.evaluate_104(ctx),
161            105 => self.evaluate_105(ctx),
162            106 => self.evaluate_106(ctx),
163            107 => self.evaluate_107(ctx),
164            108 => self.evaluate_108(ctx),
165            109 => self.evaluate_109(ctx),
166            110 => self.evaluate_110(ctx),
167            112 => self.evaluate_112(ctx),
168            113 => self.evaluate_113(ctx),
169            114 => self.evaluate_114(ctx),
170            115 => self.evaluate_115(ctx),
171            117 => self.evaluate_117(ctx),
172            118 => self.evaluate_118(ctx),
173            119 => self.evaluate_119(ctx),
174            120 => self.evaluate_120(ctx),
175            121 => self.evaluate_121(ctx),
176            122 => self.evaluate_122(ctx),
177            123 => self.evaluate_123(ctx),
178            124 => self.evaluate_124(ctx),
179            125 => self.evaluate_125(ctx),
180            126 => self.evaluate_126(ctx),
181            127 => self.evaluate_127(ctx),
182            128 => self.evaluate_128(ctx),
183            129 => self.evaluate_129(ctx),
184            130 => self.evaluate_130(ctx),
185            131 => self.evaluate_131(ctx),
186            132 => self.evaluate_132(ctx),
187            133 => self.evaluate_133(ctx),
188            134 => self.evaluate_134(ctx),
189            135 => self.evaluate_135(ctx),
190            136 => self.evaluate_136(ctx),
191            137 => self.evaluate_137(ctx),
192            138 => self.evaluate_138(ctx),
193            139 => self.evaluate_139(ctx),
194            140 => self.evaluate_140(ctx),
195            141 => self.evaluate_141(ctx),
196            142 => self.evaluate_142(ctx),
197            143 => self.evaluate_143(ctx),
198            147 => self.evaluate_147(ctx),
199            148 => self.evaluate_148(ctx),
200            152 => self.evaluate_152(ctx),
201            153 => self.evaluate_153(ctx),
202            154 => self.evaluate_154(ctx),
203            155 => self.evaluate_155(ctx),
204            156 => self.evaluate_156(ctx),
205            157 => self.evaluate_157(ctx),
206            158 => self.evaluate_158(ctx),
207            159 => self.evaluate_159(ctx),
208            160 => self.evaluate_160(ctx),
209            161 => self.evaluate_161(ctx),
210            162 => self.evaluate_162(ctx),
211            163 => self.evaluate_163(ctx),
212            164 => self.evaluate_164(ctx),
213            165 => self.evaluate_165(ctx),
214            166 => self.evaluate_166(ctx),
215            167 => self.evaluate_167(ctx),
216            168 => self.evaluate_168(ctx),
217            169 => self.evaluate_169(ctx),
218            170 => self.evaluate_170(ctx),
219            171 => self.evaluate_171(ctx),
220            172 => self.evaluate_172(ctx),
221            173 => self.evaluate_173(ctx),
222            174 => self.evaluate_174(ctx),
223            175 => self.evaluate_175(ctx),
224            176 => self.evaluate_176(ctx),
225            177 => self.evaluate_177(ctx),
226            178 => self.evaluate_178(ctx),
227            179 => self.evaluate_179(ctx),
228            180 => self.evaluate_180(ctx),
229            181 => self.evaluate_181(ctx),
230            182 => self.evaluate_182(ctx),
231            183 => self.evaluate_183(ctx),
232            490 => self.evaluate_490(ctx),
233            491 => self.evaluate_491(ctx),
234            492 => self.evaluate_492(ctx),
235            493 => self.evaluate_493(ctx),
236            494 => self.evaluate_494(ctx),
237            495 => self.evaluate_495(ctx),
238            500 => self.evaluate_500(ctx),
239            501 => self.evaluate_501(ctx),
240            503 => self.evaluate_503(ctx),
241            506 => self.evaluate_506(ctx),
242            507 => self.evaluate_507(ctx),
243            514 => self.evaluate_514(ctx),
244            515 => self.evaluate_515(ctx),
245            517 => self.evaluate_517(ctx),
246            518 => self.evaluate_518(ctx),
247            519 => self.evaluate_519(ctx),
248            521 => self.evaluate_521(ctx),
249            522 => self.evaluate_522(ctx),
250            523 => self.evaluate_523(ctx),
251            525 => self.evaluate_525(ctx),
252            527 => self.evaluate_527(ctx),
253            530 => self.evaluate_530(ctx),
254            531 => self.evaluate_531(ctx),
255            532 => self.evaluate_532(ctx),
256            533 => self.evaluate_533(ctx),
257            535 => self.evaluate_535(ctx),
258            536 => self.evaluate_536(ctx),
259            539 => self.evaluate_539(ctx),
260            540 => self.evaluate_540(ctx),
261            542 => self.evaluate_542(ctx),
262            543 => self.evaluate_543(ctx),
263            545 => self.evaluate_545(ctx),
264            547 => self.evaluate_547(ctx),
265            548 => self.evaluate_548(ctx),
266            549 => self.evaluate_549(ctx),
267            550 => self.evaluate_550(ctx),
268            551 => self.evaluate_551(ctx),
269            552 => self.evaluate_552(ctx),
270            553 => self.evaluate_553(ctx),
271            554 => self.evaluate_554(ctx),
272            555 => self.evaluate_555(ctx),
273            557 => self.evaluate_557(ctx),
274            558 => self.evaluate_558(ctx),
275            559 => self.evaluate_559(ctx),
276            560 => self.evaluate_560(ctx),
277            561 => self.evaluate_561(ctx),
278            562 => self.evaluate_562(ctx),
279            563 => self.evaluate_563(ctx),
280            564 => self.evaluate_564(ctx),
281            566 => self.evaluate_566(ctx),
282            567 => self.evaluate_567(ctx),
283            568 => self.evaluate_568(ctx),
284            569 => self.evaluate_569(ctx),
285            570 => self.evaluate_570(ctx),
286            571 => self.evaluate_571(ctx),
287            572 => self.evaluate_572(ctx),
288            573 => self.evaluate_573(ctx),
289            574 => self.evaluate_574(ctx),
290            575 => self.evaluate_575(ctx),
291            576 => self.evaluate_576(ctx),
292            577 => self.evaluate_577(ctx),
293            578 => self.evaluate_578(ctx),
294            579 => self.evaluate_579(ctx),
295            580 => self.evaluate_580(ctx),
296            591 => self.evaluate_591(ctx),
297            592 => self.evaluate_592(ctx),
298            903 => self.evaluate_903(ctx),
299            906 => self.evaluate_906(ctx),
300            911 => self.evaluate_911(ctx),
301            914 => self.evaluate_914(ctx),
302            922 => self.evaluate_922(ctx),
303            930 => self.evaluate_930(ctx),
304            931 => self.evaluate_931(ctx),
305            932 => self.evaluate_932(ctx),
306            933 => self.evaluate_933(ctx),
307            934 => self.evaluate_934(ctx),
308            935 => self.evaluate_935(ctx),
309            939 => self.evaluate_939(ctx),
310            940 => self.evaluate_940(ctx),
311            950 => self.evaluate_950(ctx),
312            951 => self.evaluate_951(ctx),
313            955 => self.evaluate_955(ctx),
314            960 => self.evaluate_960(ctx),
315            961 => self.evaluate_961(ctx),
316            962 => self.evaluate_962(ctx),
317            967 => self.evaluate_967(ctx),
318            2001 => self.evaluate_2001(ctx),
319            2002 => self.evaluate_2002(ctx),
320            2003 => self.evaluate_2003(ctx),
321            2004 => self.evaluate_2004(ctx),
322            2005 => self.evaluate_2005(ctx),
323            2006 => self.evaluate_2006(ctx),
324            2007 => self.evaluate_2007(ctx),
325            2044 => self.evaluate_2044(ctx),
326            2050 => self.evaluate_2050(ctx),
327            2060 => self.evaluate_2060(ctx),
328            2061 => self.evaluate_2061(ctx),
329            2062 => self.evaluate_2062(ctx),
330            2063 => self.evaluate_2063(ctx),
331            2064 => self.evaluate_2064(ctx),
332            2065 => self.evaluate_2065(ctx),
333            2066 => self.evaluate_2066(ctx),
334            2088 => self.evaluate_2088(ctx),
335            2089 => self.evaluate_2089(ctx),
336            2090 => self.evaluate_2090(ctx),
337            2092 => self.evaluate_2092(ctx),
338            2094 => self.evaluate_2094(ctx),
339            2095 => self.evaluate_2095(ctx),
340            2096 => self.evaluate_2096(ctx),
341            2097 => self.evaluate_2097(ctx),
342            2098 => self.evaluate_2098(ctx),
343            2099 => self.evaluate_2099(ctx),
344            _ => ConditionResult::Unknown,
345        }
346    }
347
348    fn is_external(&self, condition: u32) -> bool {
349        self.external_conditions.contains(&condition)
350    }
351    fn is_known(&self, condition: u32) -> bool {
352        matches!(
353            condition,
354            1 | 2
355                | 6
356                | 7
357                | 9
358                | 12
359                | 13
360                | 15
361                | 16
362                | 17
363                | 18
364                | 19
365                | 21
366                | 23
367                | 24
368                | 26
369                | 27
370                | 28
371                | 29
372                | 33
373                | 34
374                | 35
375                | 36
376                | 38
377                | 45
378                | 46
379                | 47
380                | 51
381                | 54
382                | 55
383                | 56
384                | 57
385                | 60
386                | 61
387                | 62
388                | 63
389                | 64
390                | 65
391                | 67
392                | 68
393                | 69
394                | 70
395                | 76
396                | 77
397                | 78
398                | 79
399                | 80
400                | 81
401                | 82
402                | 83
403                | 84
404                | 85
405                | 86
406                | 87
407                | 91
408                | 93
409                | 94
410                | 95
411                | 96
412                | 97
413                | 99
414                | 100
415                | 101
416                | 102
417                | 103
418                | 104
419                | 105
420                | 106
421                | 107
422                | 108
423                | 109
424                | 110
425                | 112
426                | 113
427                | 114
428                | 115
429                | 117
430                | 118
431                | 119
432                | 120
433                | 121
434                | 122
435                | 123
436                | 124
437                | 125
438                | 126
439                | 127
440                | 128
441                | 129
442                | 130
443                | 131
444                | 132
445                | 133
446                | 134
447                | 135
448                | 136
449                | 137
450                | 138
451                | 139
452                | 140
453                | 141
454                | 142
455                | 143
456                | 147
457                | 148
458                | 152
459                | 153
460                | 154
461                | 155
462                | 156
463                | 157
464                | 158
465                | 159
466                | 160
467                | 161
468                | 162
469                | 163
470                | 164
471                | 165
472                | 166
473                | 167
474                | 168
475                | 169
476                | 170
477                | 171
478                | 172
479                | 173
480                | 174
481                | 175
482                | 176
483                | 177
484                | 178
485                | 179
486                | 180
487                | 181
488                | 182
489                | 183
490                | 490
491                | 491
492                | 492
493                | 493
494                | 494
495                | 495
496                | 500
497                | 501
498                | 503
499                | 506
500                | 507
501                | 514
502                | 515
503                | 517
504                | 518
505                | 519
506                | 521
507                | 522
508                | 523
509                | 525
510                | 527
511                | 530
512                | 531
513                | 532
514                | 533
515                | 535
516                | 536
517                | 539
518                | 540
519                | 542
520                | 543
521                | 545
522                | 547
523                | 548
524                | 549
525                | 550
526                | 551
527                | 552
528                | 553
529                | 554
530                | 555
531                | 557
532                | 558
533                | 559
534                | 560
535                | 561
536                | 562
537                | 563
538                | 564
539                | 566
540                | 567
541                | 568
542                | 569
543                | 570
544                | 571
545                | 572
546                | 573
547                | 574
548                | 575
549                | 576
550                | 577
551                | 578
552                | 579
553                | 580
554                | 591
555                | 592
556                | 903
557                | 906
558                | 911
559                | 914
560                | 922
561                | 930
562                | 931
563                | 932
564                | 933
565                | 934
566                | 935
567                | 939
568                | 940
569                | 950
570                | 951
571                | 955
572                | 960
573                | 961
574                | 962
575                | 967
576                | 2001
577                | 2002
578                | 2003
579                | 2004
580                | 2005
581                | 2006
582                | 2007
583                | 2044
584                | 2050
585                | 2060
586                | 2061
587                | 2062
588                | 2063
589                | 2064
590                | 2065
591                | 2066
592                | 2088
593                | 2089
594                | 2090
595                | 2092
596                | 2094
597                | 2095
598                | 2096
599                | 2097
600                | 2098
601                | 2099
602        )
603    }
604}
605
606impl OrdersConditionEvaluatorFV2604 {
607    /// [86] Wenn in derselben SG29 mit Z19 in LIN DE1229 (Erforderliches Produkt der Messlokation) das PIA+5 DE7140 mit einem Messprodukt aus Codeliste der Konfigurationen Kapitel 2.3.1 "Standard-Messprodukt d...
608    /// EXTERNAL: Requires context from outside the message.
609    fn evaluate_86(&self, ctx: &EvaluationContext) -> ConditionResult {
610        ctx.external
611            .evaluate("lin_z19_has_zahlzeit_choice_messprodukt")
612    }
613
614    /// [91] Wenn in diesem Datenelement kein anderes Paket zur Möglichkeit der Angabe von mindestens einem anderen Code führt.
615    /// EXTERNAL: Requires context from outside the message.
616    fn evaluate_91(&self, ctx: &EvaluationContext) -> ConditionResult {
617        ctx.external
618            .evaluate("no_other_package_allows_additional_code")
619    }
620
621    /// [129] Es sind nur die Messprodukte erlaubt, die in der Codeliste der Konfigurationen im Kapitel 4.4 „Messprodukte mit Konfigurationserlaubnis für Werte nach Typ 2 aus SMGW“ enthalten sind.
622    /// EXTERNAL: Requires context from outside the message.
623    fn evaluate_129(&self, ctx: &EvaluationContext) -> ConditionResult {
624        ctx.external
625            .evaluate("is_smgw_typ2_konfigurationserlaubnis_messprodukt")
626    }
627
628    /// [141] Es sind nur die Messprodukt-Position-Codes erlaubt, die in der Codeliste der Konfigurationen im Kapitel 4.7 „Art der Werte für Messprodukte nach Typ 2“ enthalten sind.
629    /// EXTERNAL: Requires context from outside the message.
630    fn evaluate_141(&self, ctx: &EvaluationContext) -> ConditionResult {
631        ctx.external
632            .evaluate("is_valid_messprodukt_position_code_typ2")
633    }
634
635    /// [142] Wenn innerhalb derselben SG29 LIN im PIA+5 DE7140 (Erforderliches Produkt Konfigurationserlaubnis für Werte nach Typ 2 aus SMGW) ein Produkt angegeben ist, das in der Codeliste der Konfigurationen...
636    /// EXTERNAL: Requires context from outside the message.
637    fn evaluate_142(&self, ctx: &EvaluationContext) -> ConditionResult {
638        ctx.external
639            .evaluate("lin_z68_product_has_schwellwert_trigger")
640    }
641
642    /// [143] Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Steuerbaren Ressource angegeben ist
643    /// EXTERNAL: Requires context from outside the message.
644    fn evaluate_143(&self, ctx: &EvaluationContext) -> ConditionResult {
645        ctx.external
646            .evaluate("loc_meldepunkt_is_steuerbare_ressource_id")
647    }
648
649    /// [152] Wenn in SG29 LIN (Erforderliches Produkt der Messlokation) das PIA+5 DE7140 mit einem Produkt-Code vorhanden ist der in der Codeliste der Konfigurationen im Kapitel 7 "Produkte zur Bestellung einer...
650    /// EXTERNAL: Requires context from outside the message.
651    fn evaluate_152(&self, ctx: &EvaluationContext) -> ConditionResult {
652        ctx.external
653            .evaluate("pia_product_code_is_weitere_energieflussrichtung")
654    }
655
656    /// [165] Wenn die Konfiguration der in SG34 RFF+Z20 DE1154 (Referenz auf ID der Tranche) genannte Tranche innerhalb derselben SG29 LIN++Z16 (Erforderliches Produkt der Tranche) aufgrund einer Zuordnung eine...
657    /// EXTERNAL: Requires context from outside the message.
658    fn evaluate_165(&self, ctx: &EvaluationContext) -> ConditionResult {
659        ctx.external
660            .evaluate("tranche_neu_konfiguriert_wegen_lf_zuordnung_oder_neubildung")
661    }
662
663    /// [166] Wenn es sich um die Einrichtung der Konfigurationen aufgrund einer Zuordnung eines LF zu einer Tranche handelt
664    /// EXTERNAL: Requires context from outside the message.
665    fn evaluate_166(&self, ctx: &EvaluationContext) -> ConditionResult {
666        ctx.external
667            .evaluate("einrichtung_konfiguration_wegen_lf_zuordnung_zur_tranche")
668    }
669
670    /// [178] Wenn vom NB eine Abtretungserklärung vom Kunden gewünscht ist.
671    /// EXTERNAL: Requires context from outside the message.
672    fn evaluate_178(&self, ctx: &EvaluationContext) -> ConditionResult {
673        ctx.external.evaluate("nb_wuenscht_abtretungserklaerung")
674    }
675
676    /// [179] Wenn in derselben SG29 LIN im PIA+5 (Erforderliches Produkt Abrechnungsdaten) DE7140 das Produkt "Empfänger der Vergütung zur Einspeisung" aus der Codeliste der Konfigurationen im Kapitel 6.2 "Pr...
677    fn evaluate_179(&self, _ctx: &EvaluationContext) -> ConditionResult {
678        // TODO: Condition [179] requires manual implementation
679        // Reason: Condition requires knowing the specific product code for 'Empfänger der Vergütung zur Einspeisung' from chapter 6.2 product code list, which is not available in the condition text. The second part (CAV+ZH9 DE7110 = 'Lieferant') could be checked with any_group_has_qualified_value, but the PIA product code membership check against a Kapitel 6 code list cannot be implemented without the actual code values. Combined condition is too ambiguous to implement safely.
680        ConditionResult::Unknown
681    }
682
683    /// [180] Wenn in derselben SG29 LIN im PIA+5 (Erforderliches Produkt Abrechnungsdaten) DE7140 ein Produkt-Code genannt ist der in der Codeliste der Konfigurationen im Kapitel 6.2 "Produkte zur Bestellung ei...
684    /// EXTERNAL: Requires context from outside the message.
685    fn evaluate_180(&self, ctx: &EvaluationContext) -> ConditionResult {
686        ctx.external
687            .evaluate("product_code_in_chapter_6_2_abrechnungsdaten")
688    }
689
690    /// [183] Wenn MP-ID in NAD+MS aus Sparte Gas
691    /// EXTERNAL: Requires context from outside the message.
692    fn evaluate_183(&self, ctx: &EvaluationContext) -> ConditionResult {
693        ctx.external.evaluate("sender_is_gas_sector")
694    }
695
696    /// [967] Format: Zertifikatskörper gemäß X509.1, BSI TR-03109-4
697    fn evaluate_967(&self, _ctx: &EvaluationContext) -> ConditionResult {
698        // TODO: Condition [967] requires manual implementation
699        // Reason: Format validation requiring a valid X.509 certificate body per BSI TR-03109-4. This requires cryptographic parsing (DER/PEM ASN.1 structure) that cannot be expressed with the available string-based format validation helpers. Would need an external X.509 parsing library. Returning null — low confidence.
700        ConditionResult::Unknown
701    }
702
703    /// [1] Wenn IMD+Z03 vorhanden
704    fn evaluate_1(&self, ctx: &EvaluationContext) -> ConditionResult {
705        ctx.has_qualifier("IMD", 0, "Z03")
706    }
707
708    /// [2] Wenn BGM+7 vorhanden
709    fn evaluate_2(&self, ctx: &EvaluationContext) -> ConditionResult {
710        ctx.has_qualifier("BGM", 0, "7")
711    }
712
713    /// [6] Wenn MP-ID in SG2 NAD+MS mit Rolle LF vorhanden
714    /// EXTERNAL: Requires context from outside the message.
715    fn evaluate_6(&self, ctx: &EvaluationContext) -> ConditionResult {
716        ctx.external.evaluate("sender_is_lf")
717    }
718
719    /// [7] Wenn MP-ID in SG2 NAD+MS mit Rolle NB vorhanden
720    /// EXTERNAL: Requires context from outside the message.
721    fn evaluate_7(&self, ctx: &EvaluationContext) -> ConditionResult {
722        ctx.external.evaluate("sender_is_nb")
723    }
724
725    /// [9] Wenn bekannt
726    /// EXTERNAL: Requires context from outside the message.
727    // REVIEW: 'Wenn bekannt' (when known) depends on whether a value is known in the business context — cannot be derived from EDIFACT segments alone. (medium confidence)
728    fn evaluate_9(&self, ctx: &EvaluationContext) -> ConditionResult {
729        ctx.external.evaluate("information_is_known")
730    }
731
732    /// [12] Wenn vorhanden
733    // REVIEW: Condition 12 'Wenn vorhanden' is a generic self-referential meta-condition indicating that the attached validation rule applies whenever the field is populated. The validator framework handles actual presence detection; this evaluator simply returns True to indicate the rule is always applicable when invoked. (medium confidence)
734    fn evaluate_12(&self, _ctx: &EvaluationContext) -> ConditionResult {
735        // Wenn vorhanden — generic 'when present' meta-condition
736        // In AHB context this means: validation applies whenever the field is populated.
737        // Returning True here defers the presence check to the validator framework itself.
738        ConditionResult::True
739    }
740
741    /// [13] Wenn SG2 LOC+172 nicht vorhanden
742    fn evaluate_13(&self, ctx: &EvaluationContext) -> ConditionResult {
743        ctx.lacks_qualifier("LOC", 0, "172")
744    }
745
746    /// [15] Wenn MP-ID in SG2 NAD+MS mit Rolle MSB vorhanden
747    /// EXTERNAL: Requires context from outside the message.
748    fn evaluate_15(&self, ctx: &EvaluationContext) -> ConditionResult {
749        ctx.external.evaluate("sender_is_msb")
750    }
751
752    /// [16] Wenn eine untergeordnete SG vorhanden
753    /// EXTERNAL: Requires context from outside the message.
754    // REVIEW: Generic structural condition: 'if a subordinate SG is present'. Depends entirely on which child segment group is being checked in context — the condition number is reused across many segment rows with different child SGs. Cannot be resolved from the EDIFACT message content alone; requires the validation framework to supply structural position context. (medium confidence)
755    fn evaluate_16(&self, ctx: &EvaluationContext) -> ConditionResult {
756        ctx.external.evaluate("subordinate_sg_present")
757    }
758
759    /// [17] Wenn ein Segment innerhalb der SG vorhanden
760    /// EXTERNAL: Requires context from outside the message.
761    // REVIEW: Generic structural condition: 'if a segment within the SG is present'. Like [16], this condition number is reused across many rows and the specific segment being checked depends on the validation context. Cannot determine which segment to check without positional context supplied externally. (medium confidence)
762    fn evaluate_17(&self, ctx: &EvaluationContext) -> ConditionResult {
763        ctx.external.evaluate("segment_within_sg_present")
764    }
765
766    /// [18] Wenn IMD++Z11 vorhanden
767    fn evaluate_18(&self, ctx: &EvaluationContext) -> ConditionResult {
768        let imds = ctx.find_segments("IMD");
769        ConditionResult::from(imds.iter().any(|s| {
770            s.elements
771                .get(1)
772                .and_then(|e| e.first())
773                .is_some_and(|v| v == "Z11")
774        }))
775    }
776
777    /// [19] Wenn IMD++Z12 vorhanden
778    fn evaluate_19(&self, ctx: &EvaluationContext) -> ConditionResult {
779        let imds = ctx.find_segments("IMD");
780        ConditionResult::from(imds.iter().any(|s| {
781            s.elements
782                .get(1)
783                .and_then(|e| e.first())
784                .is_some_and(|v| v == "Z12")
785        }))
786    }
787
788    /// [21] Wenn BGM+Z28 vorhanden
789    fn evaluate_21(&self, ctx: &EvaluationContext) -> ConditionResult {
790        ctx.has_qualifier("BGM", 0, "Z28")
791    }
792
793    /// [23] Wenn MP-ID in SG2 NAD+MR mit Rolle NB vorhanden
794    /// EXTERNAL: Requires context from outside the message.
795    fn evaluate_23(&self, ctx: &EvaluationContext) -> ConditionResult {
796        ctx.external.evaluate("recipient_is_nb")
797    }
798
799    /// [24] Wenn IMD++Z35 vorhanden
800    fn evaluate_24(&self, ctx: &EvaluationContext) -> ConditionResult {
801        let imds = ctx.find_segments("IMD");
802        ConditionResult::from(imds.iter().any(|s| {
803            s.elements
804                .get(1)
805                .and_then(|e| e.first())
806                .is_some_and(|v| v == "Z35")
807        }))
808    }
809
810    /// [26] Wenn MP-ID in SG2 NAD+MS mit Rolle ÜNB vorhanden
811    /// EXTERNAL: Requires context from outside the message.
812    // REVIEW: Whether the NAD+MS market participant holds the role ÜNB (Übertragungsnetzbetreiber) cannot be determined from the EDIFACT message content alone. The role is a business context attribute of the MP-ID that requires an external master data lookup (e.g. Marktstammdatenregister or internal role registry). Marked external with name 'sender_is_uenb'. (medium confidence)
813    fn evaluate_26(&self, ctx: &EvaluationContext) -> ConditionResult {
814        ctx.external.evaluate("sender_is_uenb")
815    }
816
817    /// [27] Wenn MP-ID in SG2 NAD+MR mit Rolle MSB vorhanden
818    /// EXTERNAL: Requires context from outside the message.
819    // REVIEW: Whether the NAD+MR market participant holds the role MSB (Messstellenbetreiber) cannot be determined from the EDIFACT message content alone. The role is a business context attribute of the MP-ID requiring external master data. Marked external with name 'recipient_is_msb'. (medium confidence)
820    fn evaluate_27(&self, ctx: &EvaluationContext) -> ConditionResult {
821        ctx.external.evaluate("recipient_is_msb")
822    }
823
824    /// [28] Wenn MP-ID in SG2 NAD+MR aus Sparte Strom
825    /// EXTERNAL: Requires context from outside the message.
826    fn evaluate_28(&self, ctx: &EvaluationContext) -> ConditionResult {
827        ctx.external.evaluate("recipient_market_sector_is_strom")
828    }
829
830    /// [29] Wenn MP-ID in SG2 NAD+MR aus Sparte Gas
831    /// EXTERNAL: Requires context from outside the message.
832    fn evaluate_29(&self, ctx: &EvaluationContext) -> ConditionResult {
833        ctx.external.evaluate("recipient_market_sector_is_gas")
834    }
835
836    /// [33] Wenn IMD+Z01 vorhanden
837    fn evaluate_33(&self, ctx: &EvaluationContext) -> ConditionResult {
838        ctx.has_qualifier("IMD", 1, "Z01")
839    }
840
841    /// [34] Wenn IMD+Z02 vorhanden
842    fn evaluate_34(&self, ctx: &EvaluationContext) -> ConditionResult {
843        ctx.has_qualifier("IMD", 1, "Z02")
844    }
845
846    /// [35] IMD++Z14+Z06 vorhanden
847    fn evaluate_35(&self, ctx: &EvaluationContext) -> ConditionResult {
848        let imds = ctx.find_segments("IMD");
849        let found = imds.iter().any(|s| {
850            let has_z14 = s
851                .elements
852                .get(1)
853                .and_then(|e| e.first())
854                .is_some_and(|v| v == "Z14");
855            let has_z06 = s
856                .elements
857                .get(2)
858                .and_then(|e| e.first())
859                .is_some_and(|v| v == "Z06");
860            has_z14 && has_z06
861        });
862        ConditionResult::from(found)
863    }
864
865    /// [36] Wenn MP-ID in SG2 NAD+MR mit Rolle NB nicht vorhanden
866    /// EXTERNAL: Requires context from outside the message.
867    fn evaluate_36(&self, ctx: &EvaluationContext) -> ConditionResult {
868        ctx.external.evaluate("recipient_role_is_not_nb")
869    }
870
871    /// [38] Wenn FTX+Z04/Z05 vorhanden
872    fn evaluate_38(&self, ctx: &EvaluationContext) -> ConditionResult {
873        let found = ctx.find_segments("FTX").iter().any(|s| {
874            s.elements
875                .first()
876                .and_then(|e| e.first())
877                .is_some_and(|v| v == "Z04" || v == "Z05")
878        });
879        ConditionResult::from(found)
880    }
881
882    /// [45] Wenn MP-ID in SG2 NAD+MS mit Rolle MSB nicht vorhanden
883    /// EXTERNAL: Requires context from outside the message.
884    fn evaluate_45(&self, ctx: &EvaluationContext) -> ConditionResult {
885        ctx.external.evaluate("sender_role_is_not_msb")
886    }
887
888    /// [46] Wenn SG29 IMD++Z46 vorhanden
889    fn evaluate_46(&self, ctx: &EvaluationContext) -> ConditionResult {
890        ctx.has_qualifier("IMD", 1, "Z46")
891    }
892
893    /// [47] Wenn SG29 IMD++Z46  nicht vorhanden
894    fn evaluate_47(&self, ctx: &EvaluationContext) -> ConditionResult {
895        ctx.lacks_qualifier("IMD", 1, "Z46")
896    }
897
898    /// [51] Wenn BGM+Z48 vorhanden
899    fn evaluate_51(&self, ctx: &EvaluationContext) -> ConditionResult {
900        ctx.has_qualifier("BGM", 0, "Z48")
901    }
902
903    /// [54] Wenn FTX+Z06 vorhanden
904    fn evaluate_54(&self, ctx: &EvaluationContext) -> ConditionResult {
905        ctx.has_qualifier("FTX", 0, "Z06")
906    }
907
908    /// [55] Wenn DTM+469 (Beginn zum nächstmöglichen Termin) nicht vorhanden
909    fn evaluate_55(&self, ctx: &EvaluationContext) -> ConditionResult {
910        ctx.lacks_qualifier("DTM", 0, "469")
911    }
912
913    /// [56] Wenn DTM+203 (Ausführungsdatum) nicht vorhanden
914    fn evaluate_56(&self, ctx: &EvaluationContext) -> ConditionResult {
915        ctx.lacks_qualifier("DTM", 0, "203")
916    }
917
918    /// [57] Wenn im selben SG2 NAD DE3124 nicht vorhanden
919    // REVIEW: Checks if any NAD segment in the message lacks DE3124 (C058 at elements[2][0]). 'Im selben SG2' requires group context; falls back to message-wide check. DE3124 is the first component of C058 (Zeile für Name und Anschrift / Zusatzinfo). (medium confidence)
920    fn evaluate_57(&self, ctx: &EvaluationContext) -> ConditionResult {
921        let nads = ctx.find_segments("NAD");
922        if nads.is_empty() {
923            return ConditionResult::Unknown;
924        }
925        let any_without = nads.iter().any(|nad| {
926            nad.elements
927                .get(2)
928                .and_then(|e| e.first())
929                .map(|v| v.is_empty())
930                .unwrap_or(true)
931        });
932        ConditionResult::from(any_without)
933    }
934
935    /// [60] MP-ID nur aus Sparte Gas
936    /// EXTERNAL: Requires context from outside the message.
937    fn evaluate_60(&self, ctx: &EvaluationContext) -> ConditionResult {
938        ctx.external.evaluate("market_location_is_gas")
939    }
940
941    /// [61] MP-ID nur aus Sparte Strom
942    /// EXTERNAL: Requires context from outside the message.
943    fn evaluate_61(&self, ctx: &EvaluationContext) -> ConditionResult {
944        ctx.external.evaluate("market_location_is_electricity")
945    }
946
947    /// [62] MP-ID mit Rolle MSB
948    /// EXTERNAL: Requires context from outside the message.
949    fn evaluate_62(&self, ctx: &EvaluationContext) -> ConditionResult {
950        ctx.external.evaluate("sender_is_msb")
951    }
952
953    /// [63] MP-ID mit Rolle NB
954    /// EXTERNAL: Requires context from outside the message.
955    fn evaluate_63(&self, ctx: &EvaluationContext) -> ConditionResult {
956        ctx.external.evaluate("sender_is_nb")
957    }
958
959    /// [64] Wenn SG2 NAD+Z03 nicht vorhanden
960    fn evaluate_64(&self, ctx: &EvaluationContext) -> ConditionResult {
961        ctx.lacks_qualifier("NAD", 0, "Z03")
962    }
963
964    /// [65] Wenn FTX+Z08 vorhanden
965    fn evaluate_65(&self, ctx: &EvaluationContext) -> ConditionResult {
966        ctx.has_qualifier("FTX", 0, "Z08")
967    }
968
969    /// [67] Wenn DTM+163 nicht vorhanden
970    fn evaluate_67(&self, ctx: &EvaluationContext) -> ConditionResult {
971        ctx.lacks_qualifier("DTM", 0, "163")
972    }
973
974    /// [68] Wenn DTM+7 nicht vorhanden
975    fn evaluate_68(&self, ctx: &EvaluationContext) -> ConditionResult {
976        ctx.lacks_qualifier("DTM", 0, "7")
977    }
978
979    /// [69] Wenn NAD+Z23 nicht vorhanden
980    fn evaluate_69(&self, ctx: &EvaluationContext) -> ConditionResult {
981        ctx.lacks_qualifier("NAD", 0, "Z23")
982    }
983
984    /// [70] Wenn NAD+Z03 nicht vorhanden
985    fn evaluate_70(&self, ctx: &EvaluationContext) -> ConditionResult {
986        ctx.lacks_qualifier("NAD", 0, "Z03")
987    }
988
989    /// [76] Wenn in derselben SG29 mit Z54 in LIN DE1229 (Erforderliches Produkt der Marktlokation) das PIA+5 DE7140 mit einem Messprodukt aus Codeliste der Konfigurationen Kapitel 2.1.1 "Standard-Messprodukt ...
990    /// EXTERNAL: Requires context from outside the message.
991    fn evaluate_76(&self, ctx: &EvaluationContext) -> ConditionResult {
992        ctx.external
993            .evaluate("pia_product_in_standard_messprodukt_wahlmoeglichkeit_list")
994    }
995
996    /// [77] Wenn im selben CCI im DE7059 der Code Z39 (Code der Zählzeitdefinition) vorhanden ist
997    // REVIEW: Checks if a CCI segment in the same SG29 group has DE7059 == 'Z39' (Code der Zählzeitdefinition). DE7059 is the class/type code at elements[0][0] in CCI. Group-scoped to SG29 with message-wide fallback. (medium confidence)
998    fn evaluate_77(&self, ctx: &EvaluationContext) -> ConditionResult {
999        ctx.any_group_has_qualifier("CCI", 0, "Z39", &["SG29"])
1000    }
1001
1002    /// [78] Wenn in derselben SG29 mit Z55 in LIN DE1229 (Erforderliches Produkt der Netzlokation) das PIA+5 DE7140 mit einem Messprodukt aus Codeliste der Konfigurationen, Kapitel 2 „Codeliste der Standard-...
1003    /// EXTERNAL: Requires context from outside the message.
1004    // REVIEW: Requires checking PIA DE7140 against an external code list from 'Codeliste der Konfigurationen, Kapitel 2 – Codeliste der Standard-Messprodukt Strom für Werte nach Typ 1' filtered to those with the Werteigenschaft 'Blindarbeit'. The structural check (LIN Z55 + PIA+5 in same SG29) is possible via navigator, but the code list membership for 'Blindarbeit' products is an external reference that cannot be determined from the EDIFACT message alone. (medium confidence)
1005    fn evaluate_78(&self, ctx: &EvaluationContext) -> ConditionResult {
1006        ctx.external
1007            .evaluate("pia_has_blindarbeit_product_netzlokation")
1008    }
1009
1010    /// [79] Wenn eine andere SG29 mit Z54 in LIN DE1229 (Erforderliches Produkt der Marktlokation) mit PIA+5+9991000000078:Z11 (für Wirkarbeit Lastgang 1/4 stündlich) vorhanden ist
1011    // REVIEW: Checks if any SG29 instance contains both LIN with Z54 at elements[1][0] and PIA with product code 9991000000078 at elements[1][0]. The 'another SG29' nuance is approximated as 'any SG29' since we have no current-group context. (medium confidence)
1012    fn evaluate_79(&self, ctx: &EvaluationContext) -> ConditionResult {
1013        ctx.any_group_has_co_occurrence(
1014            "LIN",
1015            1,
1016            &["Z54"],
1017            "PIA",
1018            1,
1019            0,
1020            &["9991000000078"],
1021            &["SG29"],
1022        )
1023    }
1024
1025    /// [80] Wenn keine andere SG29 mit Z54 in LIN DE1229 (Erforderliches Produkt der Marktlokation) mit PIA+5+9991000000078:Z11 (Wirkarbeit Lastgang 1/4 stündlich) vorhanden ist
1026    // REVIEW: Negation of condition 79 — no SG29 with LIN+Z54 AND PIA product 9991000000078. (medium confidence)
1027    fn evaluate_80(&self, ctx: &EvaluationContext) -> ConditionResult {
1028        match ctx.any_group_has_co_occurrence(
1029            "LIN",
1030            1,
1031            &["Z54"],
1032            "PIA",
1033            1,
1034            0,
1035            &["9991000000078"],
1036            &["SG29"],
1037        ) {
1038            ConditionResult::True => ConditionResult::False,
1039            ConditionResult::False => ConditionResult::True,
1040            ConditionResult::Unknown => ConditionResult::Unknown,
1041        }
1042    }
1043
1044    /// [81] Wenn in derselben SG29 mit Z54 in LIN DE1229 (Erforderliches Produkt der Marktlokation), das PIA+5+9991000000078:Z11 (Wirkarbeit Lastgang 1/4 stündlich) vorhanden ist
1045    // REVIEW: Group-scoped co-occurrence in the same SG29: LIN with Z54 at elements[1][0] AND PIA with product code 9991000000078 at elements[1][0]. Functionally equivalent to condition 79 since the API checks within the same group instance. (medium confidence)
1046    fn evaluate_81(&self, ctx: &EvaluationContext) -> ConditionResult {
1047        ctx.any_group_has_co_occurrence(
1048            "LIN",
1049            1,
1050            &["Z54"],
1051            "PIA",
1052            1,
1053            0,
1054            &["9991000000078"],
1055            &["SG29"],
1056        )
1057    }
1058
1059    /// [82] Wenn eine andere SG29 mit Z54 in LIN DE1229 (Erforderliches Produkt der Marktlokation) mit PIA+5 DE7140 mit einem Messprodukt aus Codeliste der Konfigurationen, Kapitel 2.1.1 „Standard-Messproduk...
1060    /// EXTERNAL: Requires context from outside the message.
1061    // REVIEW: Requires: (1) finding ANOTHER SG29 (not the current one) where LIN DE1229 = Z54, (2) that SG29 also has PIA+5, and (3) PIA DE7140 is from 'Codeliste der Konfigurationen, Kapitel 2.1.1 – Standard-Messprodukt der Marktlokation mit der Wahlmöglichkeit der Zuordnung einer Zählzeit'. The code list membership is external and cannot be determined from the EDIFACT message alone. (medium confidence)
1062    fn evaluate_82(&self, ctx: &EvaluationContext) -> ConditionResult {
1063        ctx.external
1064            .evaluate("other_sg29_z54_with_zaehlzeit_product")
1065    }
1066
1067    /// [83] Wenn keine andere SG29 mit Z54 in LIN DE1229 (Erforderliches Produkt der Marktlokation) mit PIA+5 DE7140 mit einem Messprodukt aus Codeliste der Konfigurationen Kapitel 2.1.1 „Standard-Messproduk...
1068    // REVIEW: Logical negation of condition [82]: 'wenn KEINE andere SG29 mit Z54 ... vorhanden ist'. Implemented by inverting the external result for [82]. Returns Unknown when the underlying external condition is Unknown (e.g., code list not available). (medium confidence)
1069    fn evaluate_83(&self, ctx: &EvaluationContext) -> ConditionResult {
1070        match ctx
1071            .external
1072            .evaluate("other_sg29_z54_with_zaehlzeit_product")
1073        {
1074            ConditionResult::True => ConditionResult::False,
1075            ConditionResult::False => ConditionResult::True,
1076            ConditionResult::Unknown => ConditionResult::Unknown,
1077        }
1078    }
1079
1080    /// [84] IMD++Z14+Z07 vorhanden
1081    // REVIEW: Checks for IMD segment where elements[1][0]='Z14' (item characteristic) and elements[2][0]='Z07' (item description code). IMD++Z14+Z07 maps directly to these positions. (medium confidence)
1082    fn evaluate_84(&self, ctx: &EvaluationContext) -> ConditionResult {
1083        {
1084            let segments = ctx.find_segments("IMD");
1085            ConditionResult::from(segments.iter().any(|s| {
1086                s.elements
1087                    .get(1)
1088                    .and_then(|e| e.first())
1089                    .is_some_and(|v| v == "Z14")
1090                    && s.elements
1091                        .get(2)
1092                        .and_then(|e| e.first())
1093                        .is_some_and(|v| v == "Z07")
1094            }))
1095        }
1096    }
1097
1098    /// [85] Wenn in derselben SG29 mit Z54 in LIN DE1229 (Erforderliches Produkt der Marktlokation), das PIA+5+9991000000086:Z11 (Wirkarbeit höchste 1/4 Stunde im Monat) vorhanden ist
1099    // REVIEW: Group-scoped co-occurrence in SG29: LIN with Z54 at elements[1][0] AND PIA with product code 9991000000086 (Wirkarbeit höchste 1/4 Stunde im Monat) at elements[1][0]. (medium confidence)
1100    fn evaluate_85(&self, ctx: &EvaluationContext) -> ConditionResult {
1101        ctx.any_group_has_co_occurrence(
1102            "LIN",
1103            1,
1104            &["Z54"],
1105            "PIA",
1106            1,
1107            0,
1108            &["9991000000086"],
1109            &["SG29"],
1110        )
1111    }
1112
1113    /// [87] Wenn FTX+Z09/Z10 vorhanden
1114    fn evaluate_87(&self, ctx: &EvaluationContext) -> ConditionResult {
1115        {
1116            let segs = ctx.find_segments("FTX");
1117            ConditionResult::from(segs.iter().any(|s| {
1118                s.elements
1119                    .first()
1120                    .and_then(|e| e.first())
1121                    .is_some_and(|v| v == "Z09" || v == "Z10")
1122            }))
1123        }
1124    }
1125
1126    /// [93] Wenn in derselben Nachricht eine SG29 mit Z16 in LIN DE1229 (Erforderliches Produkt der Tranche) nicht vorhanden
1127    fn evaluate_93(&self, ctx: &EvaluationContext) -> ConditionResult {
1128        ctx.lacks_qualifier("LIN", 1, "Z16")
1129    }
1130
1131    /// [94] Wenn in derselben Nachricht eine SG29 mit Z54 in LIN DE1229 (Erforderliches Produkt der Marktlokation) nicht vorhanden
1132    fn evaluate_94(&self, ctx: &EvaluationContext) -> ConditionResult {
1133        ctx.lacks_qualifier("LIN", 1, "Z54")
1134    }
1135
1136    /// [95] Messprodukt-Code aus dem Kapitel 2.1 "Standard-Messprodukte der Marktlokation" der Codeliste der Konfigurationen
1137    /// EXTERNAL: Requires context from outside the message.
1138    fn evaluate_95(&self, ctx: &EvaluationContext) -> ConditionResult {
1139        ctx.external.evaluate("messprodukt_standard_marktlokation")
1140    }
1141
1142    /// [96] Messprodukt-Code aus dem Kapitel 2.2 "Standard-Messprodukte der Tranche" der Codeliste der Konfigurationen
1143    /// EXTERNAL: Requires context from outside the message.
1144    fn evaluate_96(&self, ctx: &EvaluationContext) -> ConditionResult {
1145        ctx.external.evaluate("messprodukt_standard_tranche")
1146    }
1147
1148    /// [97] Wenn FTX+Z10 vorhanden
1149    fn evaluate_97(&self, ctx: &EvaluationContext) -> ConditionResult {
1150        ctx.has_qualifier("FTX", 0, "Z10")
1151    }
1152
1153    /// [99] Wenn FTX+Z08/Z10 vorhanden
1154    fn evaluate_99(&self, ctx: &EvaluationContext) -> ConditionResult {
1155        ctx.any_group_has_any_qualifier("FTX", 0, &["Z08", "Z10"], &["SG29"])
1156    }
1157
1158    /// [100] Messprodukt-Code aus dem Kapitel 2.3 "Standard-Messprodukte der Messlokation" der Codeliste der Konfigurationen
1159    /// EXTERNAL: Requires context from outside the message.
1160    fn evaluate_100(&self, ctx: &EvaluationContext) -> ConditionResult {
1161        ctx.external.evaluate("messprodukt_standard_messlokation")
1162    }
1163
1164    /// [101] Wenn MP-ID in SG2 NAD+MR mit Rolle MSB in der Sparte Gas nicht vorhanden
1165    /// EXTERNAL: Requires context from outside the message.
1166    // REVIEW: Checking whether the NAD+MR recipient has role MSB in Sparte Gas requires external business context about market participant roles — not determinable from message content alone. (medium confidence)
1167    fn evaluate_101(&self, ctx: &EvaluationContext) -> ConditionResult {
1168        ctx.external.evaluate("recipient_is_msb_gas")
1169    }
1170
1171    /// [102] Wenn in derselben SG29 LIN das CCI+++Z25 (Geräteart Wandler) vorhanden
1172    fn evaluate_102(&self, ctx: &EvaluationContext) -> ConditionResult {
1173        ctx.any_group_has_qualifier("CCI", 2, "Z25", &["SG29"])
1174    }
1175
1176    /// [103] Wenn in derselben SG29 LIN das CCI+++Z25 (Geräteart Wandler) nicht vorhanden
1177    fn evaluate_103(&self, ctx: &EvaluationContext) -> ConditionResult {
1178        match ctx.any_group_has_qualifier("CCI", 2, "Z25", &["SG29"]) {
1179            ConditionResult::True => ConditionResult::False,
1180            ConditionResult::False => ConditionResult::True,
1181            ConditionResult::Unknown => ConditionResult::Unknown,
1182        }
1183    }
1184
1185    /// [104] Wenn MP-ID in SG2 NAD+VY mit Rolle LF vorhanden
1186    /// EXTERNAL: Requires context from outside the message.
1187    // REVIEW: Checking whether the NAD+VY party has role LF requires external market participant role context — cannot be determined from the EDIFACT message alone. (medium confidence)
1188    fn evaluate_104(&self, ctx: &EvaluationContext) -> ConditionResult {
1189        ctx.external.evaluate("nad_vy_is_lf")
1190    }
1191
1192    /// [105] Wenn die bisherige Konfiguration mit Zählzeiten des LF vom LF beendet werden soll
1193    /// EXTERNAL: Requires context from outside the message.
1194    fn evaluate_105(&self, ctx: &EvaluationContext) -> ConditionResult {
1195        ctx.external
1196            .evaluate("bisherige_konfiguration_zaehltzeiten_lf_beenden")
1197    }
1198
1199    /// [106] wenn IMD++Z60 (Abbestellung Messprodukt mit Zählzeitdefinition des LF) nicht vorhanden
1200    fn evaluate_106(&self, ctx: &EvaluationContext) -> ConditionResult {
1201        ctx.lacks_qualifier("IMD", 1, "Z60")
1202    }
1203
1204    /// [107] Wenn IMD++Z57 (Abbestellung Zählzeitdefinition) nicht vorhanden
1205    fn evaluate_107(&self, ctx: &EvaluationContext) -> ConditionResult {
1206        ctx.lacks_qualifier("IMD", 1, "Z57")
1207    }
1208
1209    /// [108] Wenn RFF+AGK (Konfigurations-ID) nicht vorhanden
1210    fn evaluate_108(&self, ctx: &EvaluationContext) -> ConditionResult {
1211        ctx.lacks_qualifier("RFF", 0, "AGK")
1212    }
1213
1214    /// [109] Wenn LOC+172 (Meldepunkt) nicht vorhanden
1215    fn evaluate_109(&self, ctx: &EvaluationContext) -> ConditionResult {
1216        ctx.lacks_qualifier("LOC", 0, "172")
1217    }
1218
1219    /// [110] wenn DTM+163 (Beginn Zeitraum für Wertanfrage) vorhanden
1220    fn evaluate_110(&self, ctx: &EvaluationContext) -> ConditionResult {
1221        ctx.has_qualifier("DTM", 0, "163")
1222    }
1223
1224    /// [112] Wenn in derselben SG29 LIN++Z54 (Erforderliches Produkt der Marktlokation), das PIA+5+9991000000078: Z11 (Wirkarbeit Lastgang 1/4 stündlich) vorhanden ist
1225    // REVIEW: In same SG29: LIN with elements[1][0]=Z54 (Erforderliches Produkt der Marktlokation) co-occurs with PIA where elements[1][0]=9991000000078 (Wirkarbeit Lastgang 1/4h, product code from C212.DE7140). Co-occurrence check scoped to SG29. (medium confidence)
1226    fn evaluate_112(&self, ctx: &EvaluationContext) -> ConditionResult {
1227        ctx.any_group_has_co_occurrence(
1228            "LIN",
1229            1,
1230            &["Z54"],
1231            "PIA",
1232            1,
1233            0,
1234            &["9991000000078"],
1235            &["SG29"],
1236        )
1237    }
1238
1239    /// [113] Wenn LIN DE1229 mit Code Z42 (Zählzeitdefinition) vorhanden
1240    fn evaluate_113(&self, ctx: &EvaluationContext) -> ConditionResult {
1241        ctx.has_qualifier("LIN", 1, "Z42")
1242    }
1243
1244    /// [114] Wenn LIN DE1229 mit Code Z69 (Schaltzeitdefinition) vorhanden
1245    fn evaluate_114(&self, ctx: &EvaluationContext) -> ConditionResult {
1246        ctx.has_qualifier("LIN", 1, "Z69")
1247    }
1248
1249    /// [115] Wenn LIN DE1229 mit Code Z70 (Leistungskurvendefinition) vorhanden
1250    fn evaluate_115(&self, ctx: &EvaluationContext) -> ConditionResult {
1251        ctx.has_qualifier("LIN", 1, "Z70")
1252    }
1253
1254    /// [117] Wenn SG29 LIN++Z64 (Erforderliches Produkt Schaltzeitdefinitionen) vorhanden
1255    fn evaluate_117(&self, ctx: &EvaluationContext) -> ConditionResult {
1256        ctx.has_qualifier("LIN", 1, "Z64")
1257    }
1258
1259    /// [118] Wenn SG29 LIN++Z65 (Erforderliches Produkt Leistungskurvendefinitionen) vorhanden
1260    fn evaluate_118(&self, ctx: &EvaluationContext) -> ConditionResult {
1261        ctx.has_qualifier("LIN", 1, "Z65")
1262    }
1263
1264    /// [119] Wenn SG29 LIN++Z66 (Erforderliches Produkt Ad-hoc-Steuerkanal) vorhanden
1265    fn evaluate_119(&self, ctx: &EvaluationContext) -> ConditionResult {
1266        ctx.has_qualifier("LIN", 1, "Z66")
1267    }
1268
1269    /// [120] Wenn SG29 LIN++Z67 (Erforderliches Messprodukt für Werte nach Typ 2 aus Backend) vorhanden
1270    fn evaluate_120(&self, ctx: &EvaluationContext) -> ConditionResult {
1271        ctx.has_qualifier("LIN", 1, "Z67")
1272    }
1273
1274    /// [121] Wenn SG29 LIN++Z68 (Erforderliches Produkt Konfigurationserlaubnis für Werte nach Typ 2 aus SMGW) vorhanden
1275    fn evaluate_121(&self, ctx: &EvaluationContext) -> ConditionResult {
1276        ctx.has_qualifier("LIN", 1, "Z68")
1277    }
1278
1279    /// [122] Wenn SG1 RFF+Z41 (Referenznummer des Vorgangs der Anmeldung nach WiM) nicht vorhanden
1280    fn evaluate_122(&self, ctx: &EvaluationContext) -> ConditionResult {
1281        ctx.lacks_qualifier("RFF", 0, "Z41")
1282    }
1283
1284    /// [123] Wenn DTM+203 (Ausführungsdatum) nicht vorhanden
1285    fn evaluate_123(&self, ctx: &EvaluationContext) -> ConditionResult {
1286        ctx.lacks_qualifier("DTM", 0, "203")
1287    }
1288
1289    /// [124] Wenn SG1 RFF+Z41 (Referenznummer des Vorgangs der Anmeldung nach WiM) vorhanden
1290    fn evaluate_124(&self, ctx: &EvaluationContext) -> ConditionResult {
1291        ctx.has_qualifier("RFF", 0, "Z41")
1292    }
1293
1294    /// [125] Es sind nur die Konfigurations-Produkte erlaubt, die in der Codeliste der Konfigurationen im Kapitel 4.1 „Konfigurationsprodukte Schaltzeitdefinition“ enthalten sind.
1295    /// EXTERNAL: Requires context from outside the message.
1296    fn evaluate_125(&self, ctx: &EvaluationContext) -> ConditionResult {
1297        ctx.external
1298            .evaluate("konfigurationsprodukt_schaltzeitdefinition")
1299    }
1300
1301    /// [126] Es sind nur die Konfigurations-Produkte erlaubt, die in der Codeliste der Konfigurationen im Kapitel 4.2 „Konfigurationsprodukte Leistungskurvendefinition“ enthalten sind.
1302    /// EXTERNAL: Requires context from outside the message.
1303    // REVIEW: Code list membership validation: only products from 'Codeliste der Konfigurationen Kapitel 4.2 Konfigurationsprodukte Leistungskurvendefinition' are permitted in PIA DE7140 for LIN+Z65 (Erforderliches Produkt Leistungskurvendefinitionen). The allowed product codes are defined in an external AHB specification appendix, not derivable from the EDIFACT message itself. Delegated to ExternalConditionProvider. (medium confidence)
1304    fn evaluate_126(&self, ctx: &EvaluationContext) -> ConditionResult {
1305        ctx.external
1306            .evaluate("valid_leistungskurvendefinition_product")
1307    }
1308
1309    /// [127] Es sind nur die Konfigurations-Produkte erlaubt, die in der Codeliste der Konfigurationen im Kapitel 4.3 „Konfigurationsprodukte Ad-Hoc-Steuerkanal“ enthalten sind.
1310    /// EXTERNAL: Requires context from outside the message.
1311    // REVIEW: Code list membership validation: only products from 'Codeliste der Konfigurationen Kapitel 4.3 Konfigurationsprodukte Ad-Hoc-Steuerkanal' are permitted in PIA DE7140 for LIN+Z66 (Erforderliches Produkt Ad-hoc-Steuerkanal). The allowed product codes are defined in an external AHB specification appendix, not derivable from the EDIFACT message itself. Delegated to ExternalConditionProvider. (medium confidence)
1312    fn evaluate_127(&self, ctx: &EvaluationContext) -> ConditionResult {
1313        ctx.external.evaluate("valid_adhoc_steuerkanal_product")
1314    }
1315
1316    /// [128] Es sind nur die Messprodukte erlaubt, die in der Codeliste der Konfigurationen im Kapitel 4.5 „Messprodukte für Werte nach Typ 2 aus Backend für LF und NB“ enthalten sind.
1317    /// EXTERNAL: Requires context from outside the message.
1318    // REVIEW: Code list membership validation: only products from 'Codeliste der Konfigurationen Kapitel 4.5 Messprodukte für Werte nach Typ 2 aus Backend für LF und NB' are permitted in PIA DE7140 for LIN+Z67 (Erforderliches Messprodukt für Werte nach Typ 2 aus Backend). The allowed product codes are defined in an external AHB specification appendix, not derivable from the EDIFACT message itself. Delegated to ExternalConditionProvider. (medium confidence)
1319    fn evaluate_128(&self, ctx: &EvaluationContext) -> ConditionResult {
1320        ctx.external.evaluate("valid_messprodukt_typ2_backend")
1321    }
1322
1323    /// [130] Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Marktlokation angegeben ist
1324    fn evaluate_130(&self, ctx: &EvaluationContext) -> ConditionResult {
1325        // Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Marktlokation angegeben ist
1326        // LOC Meldepunkt: elements[0][0]=="172", elements[1][0]==DE3225 (Identifikator)
1327        let locs = ctx.find_segments_with_qualifier("LOC", 0, "172");
1328        match locs
1329            .first()
1330            .and_then(|s| s.elements.get(1))
1331            .and_then(|e| e.first())
1332        {
1333            Some(val) if !val.is_empty() => validate_malo_id(val),
1334            Some(_) => ConditionResult::False,
1335            None => ConditionResult::False, // segment absent → condition not applicable
1336        }
1337    }
1338
1339    /// [131] Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Messlokation angegeben ist
1340    /// EXTERNAL: Requires context from outside the message.
1341    fn evaluate_131(&self, ctx: &EvaluationContext) -> ConditionResult {
1342        ctx.external.evaluate("meldepunkt_is_messlokation_id")
1343    }
1344
1345    /// [132] Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Netzlokation angegeben ist
1346    /// EXTERNAL: Requires context from outside the message.
1347    fn evaluate_132(&self, ctx: &EvaluationContext) -> ConditionResult {
1348        ctx.external.evaluate("meldepunkt_is_netzlokation_id")
1349    }
1350
1351    /// [133] Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Steuerbaren Ressource angegeben ist
1352    /// EXTERNAL: Requires context from outside the message.
1353    fn evaluate_133(&self, ctx: &EvaluationContext) -> ConditionResult {
1354        ctx.external
1355            .evaluate("meldepunkt_is_steuerbare_ressource_id")
1356    }
1357
1358    /// [134] Wenn die Position in der ursprünglichen Antwort auf die Bestellung aus SG1 RFF+Z42 vorhanden war und reklamiert werden soll
1359    // REVIEW: RFF+Z42 in SG1 (elements[0][0]=="Z42") references the original order response position. Presence of this segment in the current message indicates the reclaim scenario. The 'reklamiert werden soll' clause is implied by the reference existing. (medium confidence)
1360    fn evaluate_134(&self, ctx: &EvaluationContext) -> ConditionResult {
1361        ctx.has_qualifier("RFF", 0, "Z42")
1362    }
1363
1364    /// [135] Wenn SG29 LIN++Z64 (Erforderliches Produkt Schaltzeitdefinitionen) nicht vorhanden
1365    fn evaluate_135(&self, ctx: &EvaluationContext) -> ConditionResult {
1366        ctx.lacks_qualifier("LIN", 1, "Z64")
1367    }
1368
1369    /// [136] Wenn SG29 LIN++Z65 (Erforderliches Produkt Leistungskurvendefinitionen) nicht vorhanden
1370    fn evaluate_136(&self, ctx: &EvaluationContext) -> ConditionResult {
1371        ctx.lacks_qualifier("LIN", 1, "Z65")
1372    }
1373
1374    /// [137] Wenn SG29 LIN++Z66 (Erforderliches Produkt Ad-hoc-Steuerkanal) nicht vorhanden
1375    fn evaluate_137(&self, ctx: &EvaluationContext) -> ConditionResult {
1376        ctx.lacks_qualifier("LIN", 1, "Z66")
1377    }
1378
1379    /// [138] Wenn SG29 LIN++Z67 (Erforderliches Messprodukt für Werte nach Typ 2 aus Backend) nicht vorhanden
1380    fn evaluate_138(&self, ctx: &EvaluationContext) -> ConditionResult {
1381        ctx.lacks_qualifier("LIN", 1, "Z67")
1382    }
1383
1384    /// [139] Wenn SG29 LIN++Z68 (Erforderliches Produkt Konfigurationserlaubnis für Werte nach Typ 2 aus SMGW) nicht vorhanden
1385    fn evaluate_139(&self, ctx: &EvaluationContext) -> ConditionResult {
1386        ctx.lacks_qualifier("LIN", 1, "Z68")
1387    }
1388
1389    /// [140] Messprodukt-Code aus dem Kapitel 2.4 "Standard-Messprodukte der Netzlokation" der Codeliste der Konfigurationen
1390    /// EXTERNAL: Requires context from outside the message.
1391    fn evaluate_140(&self, ctx: &EvaluationContext) -> ConditionResult {
1392        ctx.external
1393            .evaluate("is_standard_messprodukt_netzlokation_code")
1394    }
1395
1396    /// [147] wenn im DE3155 in demselben COM der Code EM vorhanden ist
1397    fn evaluate_147(&self, ctx: &EvaluationContext) -> ConditionResult {
1398        let com_segments = ctx.find_segments("COM");
1399        ConditionResult::from(com_segments.iter().any(|s| {
1400            s.elements
1401                .first()
1402                .and_then(|e| e.get(1))
1403                .is_some_and(|v| v == "EM")
1404        }))
1405    }
1406
1407    /// [148] wenn im DE3155 in demselben COM der Code TE / FX / AJ / AL vorhanden ist
1408    fn evaluate_148(&self, ctx: &EvaluationContext) -> ConditionResult {
1409        let com_segments = ctx.find_segments("COM");
1410        ConditionResult::from(com_segments.iter().any(|s| {
1411            s.elements
1412                .first()
1413                .and_then(|e| e.get(1))
1414                .is_some_and(|v| matches!(v.as_str(), "TE" | "FX" | "AJ" | "AL"))
1415        }))
1416    }
1417
1418    /// [153] Es sind nur die Produkt-Codes erlaubt, die in der Codeliste der Konfigurationen im Kapitel 7 "Produkte zur Bestellung einer Änderung an einer Lokation" die in der Spalte "Ebene" mit dem Wert "Mess...
1419    /// EXTERNAL: Requires context from outside the message.
1420    fn evaluate_153(&self, ctx: &EvaluationContext) -> ConditionResult {
1421        ctx.external.evaluate("product_code_level_messlokation")
1422    }
1423
1424    /// [154] Es sind nur die Produkt-Codes erlaubt, die in der Codeliste der Konfigurationen im Kapitel 7 "Produkte zur Bestellung einer Änderung an einer Lokation" die in der Spalte "Ebene" mit dem Wert "Netz...
1425    /// EXTERNAL: Requires context from outside the message.
1426    fn evaluate_154(&self, ctx: &EvaluationContext) -> ConditionResult {
1427        ctx.external.evaluate("product_code_level_netzlokation")
1428    }
1429
1430    /// [155] Es sind nur die Produkt-Codes erlaubt, die in der Codeliste der Konfigurationen im Kapitel 7 "Produkte zur Bestellung einer Änderung an einer Lokation" die in der Spalte "Ebene" mit dem Wert "Steu...
1431    /// EXTERNAL: Requires context from outside the message.
1432    fn evaluate_155(&self, ctx: &EvaluationContext) -> ConditionResult {
1433        ctx.external
1434            .evaluate("product_code_level_steuerbare_ressource")
1435    }
1436
1437    /// [156] Es sind weiterhin nur die Produkt-Codes erlaubt, die in der Codeliste der Konfigurationen im Kapitel 7 "Produkte zur Bestellung einer Änderung an einer Lokation" die in der Spalte "Produkt gegenü...
1438    /// EXTERNAL: Requires context from outside the message.
1439    fn evaluate_156(&self, ctx: &EvaluationContext) -> ConditionResult {
1440        ctx.external.evaluate("product_code_orderable_by_nb")
1441    }
1442
1443    /// [157] Es sind weiterhin nur die Produkt-Codes erlaubt, die in der Codeliste der Konfigurationen im Kapitel 7 "Produkte zur Bestellung einer Änderung an einer Lokation" die in der Spalte "Produkt gegenü...
1444    /// EXTERNAL: Requires context from outside the message.
1445    fn evaluate_157(&self, ctx: &EvaluationContext) -> ConditionResult {
1446        ctx.external.evaluate("product_code_orderable_by_lf")
1447    }
1448
1449    /// [158] Es sind nur die Produkt-Codes erlaubt, die in der Codeliste der Konfigurationen im Kapitel 6.2 "Produkte zur Bestellung einer Änderung von Abrechnungsdaten" genannt sind.
1450    /// EXTERNAL: Requires context from outside the message.
1451    fn evaluate_158(&self, ctx: &EvaluationContext) -> ConditionResult {
1452        ctx.external
1453            .evaluate("product_code_in_abrechnungsdaten_configuration_list")
1454    }
1455
1456    /// [159] Wenn in derselben SG29 LIN im PIA+5 (Erforderliches Produkt Abrechnungsdaten) DE7140 ein Produkt-Code genannt ist, der in der Codeliste der Konfigurationen im Kapitel 6.2 "Produkte zur Bestellung e...
1457    /// EXTERNAL: Requires context from outside the message.
1458    fn evaluate_159(&self, ctx: &EvaluationContext) -> ConditionResult {
1459        ctx.external
1460            .evaluate("abrechnungsdaten_product_has_property_code_column")
1461    }
1462
1463    /// [160] Es sind nur die Codes der Produkteigenschaft zu dem in derselben SG29 LIN im PIA+5 (Erforderliches Produkt Abrechnungsdaten) DE7140 erlaubt, die in der Codeliste der Konfigurationen im Kapitel 6.2 ...
1464    /// EXTERNAL: Requires context from outside the message.
1465    fn evaluate_160(&self, ctx: &EvaluationContext) -> ConditionResult {
1466        ctx.external
1467            .evaluate("abrechnungsdaten_property_code_matches_product_row")
1468    }
1469
1470    /// [161] Wenn in derselben SG29 LIN (Erforderliches Produkt Abrechnungsdaten) das SG30 CAV+ZH9 (Code der Produkteigenschaft) nicht vorhanden ist.
1471    fn evaluate_161(&self, ctx: &EvaluationContext) -> ConditionResult {
1472        ctx.any_group_has_qualifier_without("PIA", 0, "5", "CAV", 0, "ZH9", &["SG4", "SG29"])
1473    }
1474
1475    /// [162] Es ist nur der Wertebereich erlaubt, der zu dem in derselben SG29 LIN im PIA+5 (Erforderliches Produkt Abrechnungsdaten) DE7140 genannten Produkt, das in der Codeliste der Konfigurationen im Kapite...
1476    /// EXTERNAL: Requires context from outside the message.
1477    fn evaluate_162(&self, ctx: &EvaluationContext) -> ConditionResult {
1478        ctx.external
1479            .evaluate("abrechnungsdaten_value_range_matches_product_row")
1480    }
1481
1482    /// [163] Wenn innerhalb der Nachricht eine SG30 CCI+++ZA9 (Messprodukt für Übertragungsnetzbetreiber relevant) vorhanden ist.
1483    fn evaluate_163(&self, ctx: &EvaluationContext) -> ConditionResult {
1484        ctx.has_qualifier("CCI", 2, "ZA9")
1485    }
1486
1487    /// [164] Wenn die Konfiguration der in SG34 RFF+Z20 DE1154 (Referenz auf ID der Tranche) genannte Tranche innerhalb derselben SG29 LIN++Z16 (Erforderliches Produkt der Tranche) unverändert bestehen bleibt.
1488    /// EXTERNAL: Requires context from outside the message.
1489    fn evaluate_164(&self, ctx: &EvaluationContext) -> ConditionResult {
1490        ctx.external.evaluate("tranche_configuration_unchanged")
1491    }
1492
1493    /// [167] Wenn SG2 NAD+DP (Meldepunkt), SG3 RFF+Z20 (Referenz auf ID der Tranche) vorhanden
1494    fn evaluate_167(&self, ctx: &EvaluationContext) -> ConditionResult {
1495        match (
1496            ctx.has_qualifier("NAD", 0, "DP"),
1497            ctx.has_qualifier("RFF", 0, "Z20"),
1498        ) {
1499            (ConditionResult::True, ConditionResult::True) => ConditionResult::True,
1500            (ConditionResult::False, _) | (_, ConditionResult::False) => ConditionResult::False,
1501            _ => ConditionResult::Unknown,
1502        }
1503    }
1504
1505    /// [168] Wenn SG2 NAD+DP (Meldepunkt), SG3 RFF+Z20 (Referenz auf ID der Tranche) nicht vorhanden
1506    fn evaluate_168(&self, ctx: &EvaluationContext) -> ConditionResult {
1507        match ctx.has_qualifier("NAD", 0, "DP") {
1508            ConditionResult::True => ctx.lacks_qualifier("RFF", 0, "Z20"),
1509            other => other,
1510        }
1511    }
1512
1513    /// [169] Wenn in SG29 LIN++Z19 (Erforderliches Produkt der Messlokation) in SG30 CCI (Zugeordnete Zählzeitdefinition im DE7059 der Code Z39 (Code der Zählzeitdefinition) vorhanden ist
1514    fn evaluate_169(&self, ctx: &EvaluationContext) -> ConditionResult {
1515        ctx.any_group_has_co_occurrence("LIN", 1, &["Z19"], "CCI", 0, 0, &["Z39"], &["SG29"])
1516    }
1517
1518    /// [170] Wenn in derselben SG29 LIN die SG30 CCI+Z37++ZD1 (Basis zur Bildung der Tranchengröße) (Prozentual) vorhanden
1519    fn evaluate_170(&self, ctx: &EvaluationContext) -> ConditionResult {
1520        ctx.any_group_has_qualified_value("CCI", 0, "Z37", 2, 0, &["ZD1"], &["SG29"])
1521    }
1522
1523    /// [171] Wenn in derselben SG29 LIN (Erforderliches Produkt der Tranche) das IMD+++Z64 (Leistungsbeschreibung Konfiguration) (Neukonfiguration) vorhanden ist
1524    fn evaluate_171(&self, ctx: &EvaluationContext) -> ConditionResult {
1525        ctx.any_group_has_qualifier("IMD", 2, "Z64", &["SG29"])
1526    }
1527
1528    /// [172] Wenn es sich bei der in SG2 LOC+172 DE3225 genannten Lokation um die Integration in eine Kundenanlage oder Herauslösung aus einer Kundenanlage nach §20 Abs.1d EnWG handelt. Details siehe UTILMD A...
1529    // REVIEW: LOC+172 in SG2 is the Meldepunkt qualifier, which in the ORDERS MIG is exclusively used for Kundenanlage integration/dissolution scenarios per §20 Abs.1d EnWG. Presence of LOC+172 in SG2 is the EDIFACT-level indicator for this context; the AHB cross-reference to UTILMD AHB Strom describes the same structural signal. (medium confidence)
1530    fn evaluate_172(&self, ctx: &EvaluationContext) -> ConditionResult {
1531        ctx.has_qualifier("LOC", 0, "172")
1532    }
1533
1534    /// [173] Wenn IMD++Z66 (Beendigung Konfiguration aufgrund Überführung der Marktlokation zu ruhender Marktlokation) vorhanden
1535    fn evaluate_173(&self, ctx: &EvaluationContext) -> ConditionResult {
1536        ctx.has_qualifier("IMD", 1, "Z66")
1537    }
1538
1539    /// [174] Wenn IMD++Z67 (Aktivierung Konfiguration in der derzeit ruhenden Marktlokation) vorhanden
1540    fn evaluate_174(&self, ctx: &EvaluationContext) -> ConditionResult {
1541        ctx.has_qualifier("IMD", 1, "Z67")
1542    }
1543
1544    /// [175] Wenn SG2 NAD+DP (Meldepunkt), SG3 RFF+Z59 (Referenz auf die ID der Marktlokation der Kundenanlage) vorhanden
1545    fn evaluate_175(&self, ctx: &EvaluationContext) -> ConditionResult {
1546        match (
1547            ctx.has_qualifier("NAD", 0, "DP"),
1548            ctx.has_qualifier("RFF", 0, "Z59"),
1549        ) {
1550            (ConditionResult::True, ConditionResult::True) => ConditionResult::True,
1551            (ConditionResult::False, _) | (_, ConditionResult::False) => ConditionResult::False,
1552            _ => ConditionResult::Unknown,
1553        }
1554    }
1555
1556    /// [176] Wenn SG2 NAD+DP (Meldepunkt), SG3 RFF+Z59 (Referenz auf die ID der Marktlokation der Kundenanlage) nicht vorhanden
1557    fn evaluate_176(&self, ctx: &EvaluationContext) -> ConditionResult {
1558        match ctx.has_qualifier("NAD", 0, "DP") {
1559            ConditionResult::True => ctx.lacks_qualifier("RFF", 0, "Z59"),
1560            other => other,
1561        }
1562    }
1563
1564    /// [177] Wenn IMD++Z66 (Beendigung Konfiguration aufgrund Überführung der Marktlokation zu ruhender Marktlokation) nicht vorhanden
1565    fn evaluate_177(&self, ctx: &EvaluationContext) -> ConditionResult {
1566        ctx.lacks_qualifier("IMD", 1, "Z66")
1567    }
1568
1569    /// [181] Wenn BGM+Z93 (Bestellung eines Angebots Änderung der Technik der Lokation) vorhanden
1570    fn evaluate_181(&self, ctx: &EvaluationContext) -> ConditionResult {
1571        ctx.has_qualifier("BGM", 0, "Z93")
1572    }
1573
1574    /// [182] Wenn BGM+Z12 (Änderung der Technik der Lokation) vorhanden.
1575    fn evaluate_182(&self, ctx: &EvaluationContext) -> ConditionResult {
1576        ctx.has_qualifier("BGM", 0, "Z12")
1577    }
1578
1579    /// [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...
1580    fn evaluate_490(&self, ctx: &EvaluationContext) -> ConditionResult {
1581        let dtm_segs = ctx.find_segments("DTM");
1582        match dtm_segs
1583            .first()
1584            .and_then(|s| s.elements.first())
1585            .and_then(|e| e.get(1))
1586        {
1587            Some(val) => is_mesz_utc(val),
1588            None => ConditionResult::False, // segment absent → condition not applicable
1589        }
1590    }
1591
1592    /// [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)...
1593    fn evaluate_491(&self, ctx: &EvaluationContext) -> ConditionResult {
1594        let dtm_segs = ctx.find_segments("DTM");
1595        match dtm_segs
1596            .first()
1597            .and_then(|s| s.elements.first())
1598            .and_then(|e| e.get(1))
1599        {
1600            Some(val) => is_mez_utc(val),
1601            None => ConditionResult::False, // segment absent → condition not applicable
1602        }
1603    }
1604
1605    /// [492] wenn MP-ID in NAD+MR aus Sparte Strom
1606    /// EXTERNAL: Requires context from outside the message.
1607    // REVIEW: Whether the MP-ID in NAD+MR belongs to the Strom (electricity) sector cannot be determined from the EDIFACT message alone — it requires a market participant registry lookup. (medium confidence)
1608    fn evaluate_492(&self, ctx: &EvaluationContext) -> ConditionResult {
1609        ctx.external.evaluate("recipient_is_strom")
1610    }
1611
1612    /// [493] wenn MP-ID in NAD+MR aus Sparte Gas
1613    /// EXTERNAL: Requires context from outside the message.
1614    // REVIEW: Whether the MP-ID in NAD+MR belongs to the Gas sector cannot be determined from the EDIFACT message alone — it requires a market participant registry lookup. (medium confidence)
1615    fn evaluate_493(&self, ctx: &EvaluationContext) -> ConditionResult {
1616        ctx.external.evaluate("recipient_is_gas")
1617    }
1618
1619    /// [494] Das hier genannte Datum muss der Zeitpunkt sein, zu dem das Dokument erstellt wurde, oder ein Zeitpunkt, der davor liegt.
1620    // REVIEW: States that the date in this DE must be the document creation time or earlier, i.e. <= DTM+137 Nachrichtendatum. Applied to DTM+203 (Ausführungsdatum) as the most logical target in ORDERS. Lexicographic string comparison is valid for CCYYMMDDHHMM (format 303) values since they are zero-padded fixed-width. (medium confidence)
1621    fn evaluate_494(&self, ctx: &EvaluationContext) -> ConditionResult {
1622        // The date here must be the document creation time (DTM+137 Nachrichtendatum) or earlier.
1623        // DTM+137: elements[0][0]=qualifier(137), elements[0][1]=DE2380 (actual value), elements[0][2]=format(303)
1624        // Applied to Ausführungsdatum (DTM+203) as the most likely subject in ORDERS.
1625        let dtm137_segs = ctx.find_segments_with_qualifier("DTM", 0, "137");
1626        let dtm203_segs = ctx.find_segments_with_qualifier("DTM", 0, "203");
1627        let ref_val = dtm137_segs
1628            .first()
1629            .and_then(|s| s.elements.first())
1630            .and_then(|e| e.get(1));
1631        let cmp_val = dtm203_segs
1632            .first()
1633            .and_then(|s| s.elements.first())
1634            .and_then(|e| e.get(1));
1635        match (cmp_val, ref_val) {
1636            (Some(cv), Some(rv)) => ConditionResult::from(cv.as_str() <= rv.as_str()),
1637            _ => ConditionResult::Unknown,
1638        }
1639    }
1640
1641    /// [495] Der Zeitpunkt muss ≤ dem Wert im DE2380 des DTM+137 sein
1642    // REVIEW: Explicitly requires the subject timestamp to be <= DE2380 of DTM+137 (Nachrichtendatum). Notation resolved: DTM+137 elements[0][1] is DE2380 per the MIG segment structure reference. Applied to DTM+203 (Ausführungsdatum) as the primary date field requiring this constraint in ORDERS. String comparison is valid for fixed-width CCYYMMDDHHMM format 303. (medium confidence)
1643    fn evaluate_495(&self, ctx: &EvaluationContext) -> ConditionResult {
1644        // The point in time must be <= DE2380 of DTM+137 (Nachrichtendatum).
1645        // DTM element layout per MIG: elements[0][0]=qualifier, elements[0][1]=DE2380 value, elements[0][2]=format code.
1646        // Applied to Ausführungsdatum (DTM+203) as the most relevant cross-date check in ORDERS.
1647        let dtm137_segs = ctx.find_segments_with_qualifier("DTM", 0, "137");
1648        let dtm203_segs = ctx.find_segments_with_qualifier("DTM", 0, "203");
1649        let ref_val = dtm137_segs
1650            .first()
1651            .and_then(|s| s.elements.first())
1652            .and_then(|e| e.get(1));
1653        let cmp_val = dtm203_segs
1654            .first()
1655            .and_then(|s| s.elements.first())
1656            .and_then(|e| e.get(1));
1657        match (cmp_val, ref_val) {
1658            (Some(cv), Some(rv)) => ConditionResult::from(cv.as_str() <= rv.as_str()),
1659            _ => ConditionResult::Unknown,
1660        }
1661    }
1662
1663    /// [500] Hinweis: Zählpunkt der BAS
1664    fn evaluate_500(&self, _ctx: &EvaluationContext) -> ConditionResult {
1665        ConditionResult::Unknown
1666    }
1667
1668    /// [501] Hinweis: Zählpunkt der DZR
1669    fn evaluate_501(&self, _ctx: &EvaluationContext) -> ConditionResult {
1670        ConditionResult::Unknown
1671    }
1672
1673    /// [503] Hinweis: Angabe eines technischen Ansprechpartners für die Geräteübernahme
1674    fn evaluate_503(&self, _ctx: &EvaluationContext) -> ConditionResult {
1675        ConditionResult::Unknown
1676    }
1677
1678    /// [506] Hinweis: Datum, bis zu dem der MSBA zur Fortführung verpflichtet wird
1679    fn evaluate_506(&self, _ctx: &EvaluationContext) -> ConditionResult {
1680        ConditionResult::Unknown
1681    }
1682
1683    /// [507] Hinweis: Es müssen alle nach Durchführung der Messlokationsänderung eingesetzten/genutzten OBIS- Kennzahlen übermittelt werden (wird eine "Erweiterung" des Messumfangs beauftragt, sind auch die...
1684    fn evaluate_507(&self, _ctx: &EvaluationContext) -> ConditionResult {
1685        ConditionResult::Unknown
1686    }
1687
1688    /// [514] Hinweis: Das Abonnement kann frühestens ab dem aktuellen Liefermonat beim Netzbetreiber gestartet werden.
1689    fn evaluate_514(&self, _ctx: &EvaluationContext) -> ConditionResult {
1690        ConditionResult::Unknown
1691    }
1692
1693    /// [515] Hinweis: Das angegebene Betrachtungszeitintervall bestimmt beim Start Abo bzw. Ende Abo ab bzw. bis wann (einschließlich) das Abo laufen soll.
1694    fn evaluate_515(&self, _ctx: &EvaluationContext) -> ConditionResult {
1695        ConditionResult::Unknown
1696    }
1697
1698    /// [517] Hinweis: Zählpunkt der LF-AASZR
1699    fn evaluate_517(&self, _ctx: &EvaluationContext) -> ConditionResult {
1700        ConditionResult::Unknown
1701    }
1702
1703    /// [518] Hinweis: Das angegebene Ausführungsdatum bestimmt beim Start Abo bzw. Ende Abo ab bzw. bis wann (einschließlich) das Abo laufen soll.
1704    fn evaluate_518(&self, _ctx: &EvaluationContext) -> ConditionResult {
1705        ConditionResult::Unknown
1706    }
1707
1708    /// [519] Hinweis: Bei Gas bezieht sich die Anforderung immer sowohl auf die vorläufigen Profilwerte als auch auf die endgültigen Profilwerte, falls diese bereits vorliegen.
1709    fn evaluate_519(&self, _ctx: &EvaluationContext) -> ConditionResult {
1710        ConditionResult::Unknown
1711    }
1712
1713    /// [521] Hinweis: Verwendung der ID der Marktlokation
1714    fn evaluate_521(&self, _ctx: &EvaluationContext) -> ConditionResult {
1715        // Hinweis: Verwendung der ID der Marktlokation — informational note, always applies
1716        ConditionResult::True
1717    }
1718
1719    /// [522] Hinweis: Verwendung der ID der Messlokation
1720    fn evaluate_522(&self, _ctx: &EvaluationContext) -> ConditionResult {
1721        // Hinweis: Verwendung der ID der Messlokation — informational note, always applies
1722        ConditionResult::True
1723    }
1724
1725    /// [523] Hinweis: Verwendung der ID der Tranche
1726    fn evaluate_523(&self, _ctx: &EvaluationContext) -> ConditionResult {
1727        // Hinweis: Verwendung der ID der Tranche — informational note, always applies
1728        ConditionResult::True
1729    }
1730
1731    /// [525] Hinweis: Wert aus BGM DE1004 der MSCONS
1732    fn evaluate_525(&self, _ctx: &EvaluationContext) -> ConditionResult {
1733        // Hinweis: Wert aus BGM DE1004 der MSCONS — informational note, always applies
1734        ConditionResult::True
1735    }
1736
1737    /// [527] Hinweis: Zählpunkt der BG-SZR (Kategorie B)
1738    fn evaluate_527(&self, _ctx: &EvaluationContext) -> ConditionResult {
1739        // Hinweis: Zählpunkt der BG-SZR (Kategorie B) — informational note, always applies
1740        ConditionResult::True
1741    }
1742
1743    /// [530] Hinweis: Wert aus BGM+310 DE1004 der QUOTES mit der das Angebot erfolgt ist.
1744    fn evaluate_530(&self, _ctx: &EvaluationContext) -> ConditionResult {
1745        // Hinweis: Wert aus BGM+310 DE1004 der QUOTES mit der das Angebot erfolgt ist — informational note, always applies
1746        ConditionResult::True
1747    }
1748
1749    /// [531] Hinweis: Wert aus LIN DE1082 der QUOTES, mit der das Angebot erfolgt ist
1750    fn evaluate_531(&self, _ctx: &EvaluationContext) -> ConditionResult {
1751        // Hinweis: Wert aus LIN DE1082 der QUOTES, mit der das Angebot erfolgt ist — informational note, always applies
1752        ConditionResult::True
1753    }
1754
1755    /// [532] Hinweis: Wert aus BGM+Z29 DE1004 der QUOTES, mit der das Angebot zur Abrechnung des Messstellenbetriebs erfolgt ist.
1756    fn evaluate_532(&self, _ctx: &EvaluationContext) -> ConditionResult {
1757        // Hinweis: Wert aus BGM+Z29 DE1004 der QUOTES, mit der das Angebot zur Abrechnung des Messstellenbetriebs erfolgt ist — informational note, always applies
1758        ConditionResult::True
1759    }
1760
1761    /// [533] Hinweis: Gerichtsvollzieher hat Termin vorgegeben
1762    fn evaluate_533(&self, _ctx: &EvaluationContext) -> ConditionResult {
1763        // Hinweis: Gerichtsvollzieher hat Termin vorgegeben — informational note, always applies
1764        ConditionResult::True
1765    }
1766
1767    /// [535] Hinweis: Verwendung der ID der Messlokation der Sparte Strom
1768    fn evaluate_535(&self, _ctx: &EvaluationContext) -> ConditionResult {
1769        // Hinweis: Verwendung der ID der Messlokation der Sparte Strom — informational note, always applies
1770        ConditionResult::True
1771    }
1772
1773    /// [536] Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z59
1774    fn evaluate_536(&self, _ctx: &EvaluationContext) -> ConditionResult {
1775        // Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z59 — informational note, always applies
1776        ConditionResult::True
1777    }
1778
1779    /// [539] Hinweis: Es sind nur Codes von Zählzeiten aus Liste des NB anzugeben
1780    fn evaluate_539(&self, _ctx: &EvaluationContext) -> ConditionResult {
1781        // Hinweis: Es sind nur Codes von Zählzeiten aus Liste des NB anzugeben — informational note, always applies
1782        ConditionResult::True
1783    }
1784
1785    /// [540] Hinweis: Es sind nur Codes von Zählzeiten aus Liste des LF anzugeben
1786    fn evaluate_540(&self, _ctx: &EvaluationContext) -> ConditionResult {
1787        // Hinweis: Es sind nur Codes von Zählzeiten aus Liste des LF anzugeben — informational note, always applies
1788        ConditionResult::True
1789    }
1790
1791    /// [542] Hinweis: Wert aus BGM+Z57 DE1004 der QUOTES mit der das Angebot erfolgt ist.
1792    fn evaluate_542(&self, _ctx: &EvaluationContext) -> ConditionResult {
1793        // Hinweis: Wert aus BGM+Z57 DE1004 der QUOTES mit der das Angebot erfolgt ist — informational note, always applies
1794        ConditionResult::True
1795    }
1796
1797    /// [543] Hinweis: Wert aus BGM+Z57 DE1004 der ORDERS mit der die Bestellung der Werte erfolgt ist.
1798    fn evaluate_543(&self, _ctx: &EvaluationContext) -> ConditionResult {
1799        // Hinweis: Wert aus BGM+Z57 DE1004 der ORDERS mit der die Bestellung der Werte erfolgt ist — informational note, always applies
1800        ConditionResult::True
1801    }
1802
1803    /// [545] Hinweis: Es werden nur die Messprodukte der Messlokationen angegeben, die für die in der SG2 genannte Marktlokation bzw. deren Tranchen erforderlich sind. Messprodukte an der Messlokation für wei...
1804    fn evaluate_545(&self, _ctx: &EvaluationContext) -> ConditionResult {
1805        // Hinweis: Es werden nur die Messprodukte der Messlokationen angegeben... — informational note, always applies
1806        ConditionResult::True
1807    }
1808
1809    /// [547] Hinweis: Dokumentennummer aus BGM+Z60 DE1004 der UTILTS
1810    fn evaluate_547(&self, _ctx: &EvaluationContext) -> ConditionResult {
1811        // Hinweis: Dokumentennummer aus BGM+Z60 DE1004 der UTILTS — informational note, always applies
1812        ConditionResult::True
1813    }
1814
1815    /// [548] Hinweis: Wenn die Änderung der Gerätekonfiguration mit einer Zählzeit übermittelt wird, ist hier die MP-ID des Eigentümers der Liste der Zählzeit einzutragen. Wenn anstatt der bisherigen Zäh...
1816    fn evaluate_548(&self, _ctx: &EvaluationContext) -> ConditionResult {
1817        // Hinweis: MP-ID des Eigentümers der Zählzeitliste — informational note, always applies
1818        ConditionResult::True
1819    }
1820
1821    /// [549] Hinweis: Findet bei der Reklamation von Zählerständen immer Anwendung. Einzige Ausnahme ist, wenn es sich um die Reklamation eines fehlenden Zählerstandes aufgrund einer Turnusablesung handelt, ...
1822    fn evaluate_549(&self, _ctx: &EvaluationContext) -> ConditionResult {
1823        // Hinweis: Reklamation von Zählerständen — Zeitpunktangabe vs. Zeitintervall — informational note, always applies
1824        ConditionResult::True
1825    }
1826
1827    /// [550] Hinweis: Findet nur dann Anwendung, wenn es sich um die Reklamation eines fehlenden Zählerstandes aufgrund einer Turnusablesung handelt, bei welcher der MSB am Objekt der Marktlokation die Informa...
1828    fn evaluate_550(&self, _ctx: &EvaluationContext) -> ConditionResult {
1829        // Hinweis: Reklamation fehlender Zählerstand bei Turnusablesung — informational note, always applies
1830        ConditionResult::True
1831    }
1832
1833    /// [551] Hinweis: Die SG29 ist so oft zu wiederholen, dass alle Messprodukte und Zählzeiten genannt werden, die ab dem in DTM+203 genannten Zeitpunkt auf der Messlokation durch den MSB konfiguriert werden ...
1834    fn evaluate_551(&self, _ctx: &EvaluationContext) -> ConditionResult {
1835        // Hinweis: SG29 Wiederholung für alle Messprodukte und Zählzeiten — informational note, always applies
1836        ConditionResult::True
1837    }
1838
1839    /// [552] Hinweis: Verwendung der ID der Netzlokation
1840    fn evaluate_552(&self, _ctx: &EvaluationContext) -> ConditionResult {
1841        // Hinweis: Verwendung der ID der Netzlokation — informational note, always applies
1842        ConditionResult::True
1843    }
1844
1845    /// [553] Hinweis: Verwendung der ID der Steuerbaren Ressource
1846    fn evaluate_553(&self, _ctx: &EvaluationContext) -> ConditionResult {
1847        // Hinweis: Verwendung der ID der Steuerbaren Ressource — informational note, always applies
1848        ConditionResult::True
1849    }
1850
1851    /// [554] Hinweis: Wert aus BGM+Z74 DE1004 der QUOTES mit der das Angebot erfolgt ist.
1852    fn evaluate_554(&self, _ctx: &EvaluationContext) -> ConditionResult {
1853        // Hinweis: Wert aus BGM+Z74 DE1004 der QUOTES — informational note about value origin, always applies
1854        ConditionResult::True
1855    }
1856
1857    /// [555] Hinweis: Vorgangsnummer aus SG4 IDE+24 DE7402 der UTILMD mit BGM+E01 mit der die Anmeldung des MSB-Wechsels erfolgt ist.
1858    fn evaluate_555(&self, _ctx: &EvaluationContext) -> ConditionResult {
1859        // Hinweis: Vorgangsnummer aus SG4 IDE+24 DE7402 der UTILMD — informational note about value origin, always applies
1860        ConditionResult::True
1861    }
1862
1863    /// [557] Hinweis: Es werden nur die Messprodukte der Messlokationen angegeben, die für die in der SG2 genannte Netzlokation erforderlich sind. Messprodukte an der Messlokation für weitere Netzlokationen o...
1864    fn evaluate_557(&self, _ctx: &EvaluationContext) -> ConditionResult {
1865        // Hinweis: Only Messprodukte for Messlokationen required for the named Netzlokation are specified — informational note, always applies
1866        ConditionResult::True
1867    }
1868
1869    /// [558] Hinweis: Dokumentennummer aus BGM+Z78 DE1004 der UTILTS
1870    fn evaluate_558(&self, _ctx: &EvaluationContext) -> ConditionResult {
1871        // Hinweis: Dokumentennummer aus BGM+Z78 DE1004 der UTILTS — informational note, always applies
1872        ConditionResult::True
1873    }
1874
1875    /// [559] Hinweis: Dokumentennummer aus BGM+Z79 DE1004 der UTILTS
1876    fn evaluate_559(&self, _ctx: &EvaluationContext) -> ConditionResult {
1877        // Hinweis: Dokumentennummer aus BGM+Z79 DE1004 der UTILTS — informational note, always applies
1878        ConditionResult::True
1879    }
1880
1881    /// [560] Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z80
1882    fn evaluate_560(&self, _ctx: &EvaluationContext) -> ConditionResult {
1883        // Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z80 — informational note, always applies
1884        ConditionResult::True
1885    }
1886
1887    /// [561] Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z81
1888    fn evaluate_561(&self, _ctx: &EvaluationContext) -> ConditionResult {
1889        // Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z81 — informational note, always applies
1890        ConditionResult::True
1891    }
1892
1893    /// [562] Hinweis: Wert aus BGM+Z73 DE1004 der IFTSTA mit der die Antwort auf die Bestellung der Konfiguration übermittelt wurde
1894    fn evaluate_562(&self, _ctx: &EvaluationContext) -> ConditionResult {
1895        // Hinweis: Wert aus BGM+Z73 DE1004 der IFTSTA — informational note, always applies
1896        ConditionResult::True
1897    }
1898
1899    /// [563] Hinweis: Vorgangsnummer aus CNI DE1490 der IFTSTA mit BGM+Z73 mit der die Antwort auf die Bestellung der Konfiguration übermittelt wurde
1900    fn evaluate_563(&self, _ctx: &EvaluationContext) -> ConditionResult {
1901        // Hinweis: Vorgangsnummer aus CNI DE1490 der IFTSTA mit BGM+Z73 mit der die Antwort auf die Bestellung der Konfiguration übermittelt wurde — informational note, always applies
1902        ConditionResult::True
1903    }
1904
1905    /// [564] Hinweis: Für den Empfang der Werte nach Typ 2 aus dem SMGW.
1906    fn evaluate_564(&self, _ctx: &EvaluationContext) -> ConditionResult {
1907        // Hinweis: Für den Empfang der Werte nach Typ 2 aus dem SMGW — informational note, always applies
1908        ConditionResult::True
1909    }
1910
1911    /// [566] Hinweis: Verwendung der ID der Technischen Ressource
1912    fn evaluate_566(&self, _ctx: &EvaluationContext) -> ConditionResult {
1913        // Hinweis: Verwendung der ID der Technischen Ressource — informational note, always applies
1914        ConditionResult::True
1915    }
1916
1917    /// [567] Hinweis: Es darf nur eine Information im DE3148 übermittelt werden
1918    fn evaluate_567(&self, _ctx: &EvaluationContext) -> ConditionResult {
1919        // Hinweis: Es darf nur eine Information im DE3148 übermittelt werden — informational note, always applies
1920        ConditionResult::True
1921    }
1922
1923    /// [568] Hinweis: Wenn die Einrichtung der Konfiguration mit einer Zählzeit übermittelt wird, ist hier die MP-ID des NB als Eigentümer der Liste der Zählzeit einzutragen.
1924    fn evaluate_568(&self, _ctx: &EvaluationContext) -> ConditionResult {
1925        // Hinweis: Wenn die Einrichtung der Konfiguration mit einer Zählzeit übermittelt wird, ist hier die MP-ID des NB als Eigentümer der Liste der Zählzeit einzutragen — informational note, always applies
1926        ConditionResult::True
1927    }
1928
1929    /// [569] Hinweis: MaBiS-Zählpunkt der LF-SZR
1930    fn evaluate_569(&self, _ctx: &EvaluationContext) -> ConditionResult {
1931        // Hinweis: MaBiS-Zählpunkt der LF-SZR — informational note, always applies
1932        ConditionResult::True
1933    }
1934
1935    /// [570] Hinweis: zur Angabe von Kontaktdaten des Kunden des Lieferanten um die Änderung an der Technik zu vereinfachen.
1936    fn evaluate_570(&self, _ctx: &EvaluationContext) -> ConditionResult {
1937        // Hinweis: zur Angabe von Kontaktdaten des Kunden des Lieferanten um die Änderung an der Technik zu vereinfachen — informational note, always applies
1938        ConditionResult::True
1939    }
1940
1941    /// [571] Hinweis: MSB der Marktlokation, an den die Werte der weiteren Energieflussrichtung der Messlokation zu übermitteln sind.
1942    fn evaluate_571(&self, _ctx: &EvaluationContext) -> ConditionResult {
1943        // Hinweis: MSB der Marktlokation, an den die Werte der weiteren Energieflussrichtung der Messlokation zu übermitteln sind — informational note, always applies
1944        ConditionResult::True
1945    }
1946
1947    /// [572] Hinweis: MSB der Marktlokation der Kundenanlage, in der die betroffene Lokation integriert wird.
1948    fn evaluate_572(&self, _ctx: &EvaluationContext) -> ConditionResult {
1949        // Hinweis: MSB der Marktlokation der Kundenanlage, in der die betroffene Lokation integriert wird — informational note, always applies
1950        ConditionResult::True
1951    }
1952
1953    /// [573] Hinweis: Es ist eine URI IPv4 für die Bereitstellung der Werte anzugeben.
1954    fn evaluate_573(&self, _ctx: &EvaluationContext) -> ConditionResult {
1955        // Hinweis: Es ist eine URI IPv4 für die Bereitstellung der Werte anzugeben — informational note, always applies
1956        ConditionResult::True
1957    }
1958
1959    /// [574] Hinweis: Es ist eine URI IPv6 für die Bereitstellung der Werte anzugeben.
1960    fn evaluate_574(&self, _ctx: &EvaluationContext) -> ConditionResult {
1961        // Hinweis: Es ist eine URI IPv6 für die Bereitstellung der Werte anzugeben.
1962        ConditionResult::True
1963    }
1964
1965    /// [575] Hinweis: Wenn der gewünschte Änderungszeitpunkt ein fixer Zeitpunkt ist.
1966    fn evaluate_575(&self, _ctx: &EvaluationContext) -> ConditionResult {
1967        // Hinweis: Wenn der gewünschte Änderungszeitpunkt ein fixer Zeitpunkt ist.
1968        ConditionResult::True
1969    }
1970
1971    /// [576] Hinweis: Wenn der gewünschte Änderungszeitpunkt ein nächst möglicher Termin zum oder nach dem angegebenen Zeitpunkt ist.
1972    fn evaluate_576(&self, _ctx: &EvaluationContext) -> ConditionResult {
1973        // Hinweis: Wenn der gewünschte Änderungszeitpunkt ein nächst möglicher Termin zum oder nach dem angegebenen Zeitpunkt ist.
1974        ConditionResult::True
1975    }
1976
1977    /// [577] Hinweis: Wert aus BGM+Z93 (Bestellung eines Angebots Änderung der Technik der Lokation) DE1004 der QUOTES mit der das Angebot erfolgt ist.
1978    fn evaluate_577(&self, _ctx: &EvaluationContext) -> ConditionResult {
1979        // Hinweis: Wert aus BGM+Z93 (Bestellung eines Angebots Änderung der Technik der Lokation) DE1004 der QUOTES mit der das Angebot erfolgt ist — informational note, always applies
1980        ConditionResult::True
1981    }
1982
1983    /// [578] Hinweis: Wert aus BGM DE1004 der PRICAT mit der das Preisblatt B des MSB, auf die aus Sicht des NB das Angebot basiert, übermittelt wurde.
1984    fn evaluate_578(&self, _ctx: &EvaluationContext) -> ConditionResult {
1985        // Hinweis: Wert aus BGM DE1004 der PRICAT mit der das Preisblatt B des MSB übermittelt wurde — informational note, always applies
1986        ConditionResult::True
1987    }
1988
1989    /// [579] Hinweis: Angabe des Beginnzeitpunkts des gewünschten Umsetzungstermins aus Sicht des Bestellers.
1990    fn evaluate_579(&self, _ctx: &EvaluationContext) -> ConditionResult {
1991        // Hinweis: Angabe des Beginnzeitpunkts des gewünschten Umsetzungstermins aus Sicht des Bestellers.
1992        // Informational note, always applies.
1993        ConditionResult::True
1994    }
1995
1996    /// [580] Hinweis: Angabe des Endezeitpunkts des gewünschten Umsetzungstermins aus Sicht des Bestellers.
1997    fn evaluate_580(&self, _ctx: &EvaluationContext) -> ConditionResult {
1998        // Hinweis: Angabe des Endezeitpunkts des gewünschten Umsetzungstermins aus Sicht des Bestellers.
1999        // Informational note, always applies.
2000        ConditionResult::True
2001    }
2002
2003    /// [591] Hinweis: Wenn es sich um die Bestellung eines vorherigen Angebots im Rahmen der BDEW Anwendungshilfe "Prozesse zur Änderung der Technik an Lokationen" handelt.
2004    fn evaluate_591(&self, _ctx: &EvaluationContext) -> ConditionResult {
2005        // Hinweis: Wenn es sich um die Bestellung eines vorherigen Angebots im Rahmen der BDEW Anwendungshilfe handelt.
2006        // Informational note, always applies.
2007        ConditionResult::True
2008    }
2009
2010    /// [592] Hinweis: wenn es sich um die Beauftragung einer Änderung gemäß WiM Teil1 UC "Messlokationsänderung" handelt.
2011    fn evaluate_592(&self, _ctx: &EvaluationContext) -> ConditionResult {
2012        // Hinweis: wenn es sich um die Beauftragung einer Änderung gemäß WiM Teil1 UC "Messlokationsänderung" handelt.
2013        // Informational note, always applies.
2014        ConditionResult::True
2015    }
2016
2017    /// [903] Format: Möglicher Wert: 1
2018    fn evaluate_903(&self, _ctx: &EvaluationContext) -> ConditionResult {
2019        ConditionResult::True
2020    }
2021
2022    /// [906] Format: max. 3 Nachkommastellen
2023    fn evaluate_906(&self, ctx: &EvaluationContext) -> ConditionResult {
2024        // Format: max. 3 Nachkommastellen
2025        let segs = ctx.find_segments("QTY");
2026        match segs
2027            .first()
2028            .and_then(|s| s.elements.first())
2029            .and_then(|e| e.get(1))
2030        {
2031            Some(val) => validate_max_decimal_places(val, 3),
2032            None => ConditionResult::False, // segment absent → condition not applicable
2033        }
2034    }
2035
2036    /// [911] Format: Mögliche Werte: 1 bis n, je Nachricht oder Segmentgruppe bei 1 beginnend und fortlaufend aufsteigend
2037    fn evaluate_911(&self, _ctx: &EvaluationContext) -> ConditionResult {
2038        // Hinweis: Mögliche Werte: 1 bis n, je Nachricht oder Segmentgruppe bei 1 beginnend und fortlaufend aufsteigend
2039        // This is a cardinality/sequencing annotation — informational, always applies
2040        ConditionResult::True
2041    }
2042
2043    /// [914] Format: Möglicher Wert: &gt;0
2044    fn evaluate_914(&self, ctx: &EvaluationContext) -> ConditionResult {
2045        // Format: Möglicher Wert: >0 — QTY value must be greater than zero
2046        let segs = ctx.find_segments("QTY");
2047        match segs
2048            .first()
2049            .and_then(|s| s.elements.first())
2050            .and_then(|e| e.get(1))
2051        {
2052            Some(val) => validate_numeric(val, ">", 0.0),
2053            None => ConditionResult::False, // segment absent → condition not applicable
2054        }
2055    }
2056
2057    /// [922] Format: TR-ID
2058    // REVIEW: TR-ID (Transaktionsreferenz-ID) format. In ORDERS the transaction reference ID appears in BGM C106. The exact segment context depends on the AHB field definition — implemented as max-length-35 check on BGM, consistent with EDIFACT AN..35 data element constraints. Medium confidence because the target segment may differ by AHB row. (medium confidence)
2059    fn evaluate_922(&self, ctx: &EvaluationContext) -> ConditionResult {
2060        // Format: TR-ID — Transaktionsreferenz-ID, max 35 alphanumeric characters
2061        // In ORDERS, TR-ID typically appears in BGM element 1 (C106 document identifier)
2062        let segs = ctx.find_segments("BGM");
2063        match segs
2064            .first()
2065            .and_then(|s| s.elements.get(1))
2066            .and_then(|e| e.first())
2067        {
2068            Some(val) if !val.is_empty() => validate_max_length(val, 35),
2069            Some(_) => ConditionResult::False,
2070            None => ConditionResult::False, // segment absent → condition not applicable
2071        }
2072    }
2073
2074    /// [930] Format: max. 2 Nachkommastellen
2075    fn evaluate_930(&self, ctx: &EvaluationContext) -> ConditionResult {
2076        // Format: max. 2 Nachkommastellen — QTY value must have at most 2 decimal places
2077        let segs = ctx.find_segments("QTY");
2078        match segs
2079            .first()
2080            .and_then(|s| s.elements.first())
2081            .and_then(|e| e.get(1))
2082        {
2083            Some(val) => validate_max_decimal_places(val, 2),
2084            None => ConditionResult::False, // segment absent → condition not applicable
2085        }
2086    }
2087
2088    /// [931] Format: ZZZ = +00
2089    fn evaluate_931(&self, ctx: &EvaluationContext) -> ConditionResult {
2090        // Format: ZZZ = +00 — DTM timezone offset must be UTC (+00)
2091        let segs = ctx.find_segments("DTM");
2092        match segs
2093            .first()
2094            .and_then(|s| s.elements.first())
2095            .and_then(|e| e.get(1))
2096        {
2097            Some(val) => validate_timezone_utc(val),
2098            None => ConditionResult::False, // segment absent → condition not applicable
2099        }
2100    }
2101
2102    /// [932] Format: HHMM = 2200
2103    // REVIEW: HHMM = 2200 time constraint on DTM. In ORDERS FV2604, delivery period end (qualifier 163) must terminate at 22:00 UTC, matching the standard German grid day-end convention. Medium confidence because the target DTM qualifier may differ for the specific AHB row — 163 is the most likely candidate for an end-of-period constraint. (medium confidence)
2104    fn evaluate_932(&self, ctx: &EvaluationContext) -> ConditionResult {
2105        // Format: HHMM = 2200 — DTM+163 (delivery period end) time must be 2200
2106        let dtm_segs = ctx.find_segments_with_qualifier("DTM", 0, "163");
2107        match dtm_segs
2108            .first()
2109            .and_then(|s| s.elements.first())
2110            .and_then(|e| e.get(1))
2111        {
2112            Some(val) => validate_hhmm_equals(val, "2200"),
2113            None => ConditionResult::False, // segment absent → condition not applicable
2114        }
2115    }
2116
2117    /// [933] Format: HHMM = 2300
2118    fn evaluate_933(&self, ctx: &EvaluationContext) -> ConditionResult {
2119        let dtm_segs = ctx.find_segments("DTM");
2120        match dtm_segs
2121            .first()
2122            .and_then(|s| s.elements.first())
2123            .and_then(|e| e.get(1))
2124        {
2125            Some(val) => validate_hhmm_equals(val, "2300"),
2126            None => ConditionResult::False, // segment absent → condition not applicable
2127        }
2128    }
2129
2130    /// [934] Format: HHMM = 0400
2131    fn evaluate_934(&self, ctx: &EvaluationContext) -> ConditionResult {
2132        let dtm_segs = ctx.find_segments("DTM");
2133        match dtm_segs
2134            .first()
2135            .and_then(|s| s.elements.first())
2136            .and_then(|e| e.get(1))
2137        {
2138            Some(val) => validate_hhmm_equals(val, "0400"),
2139            None => ConditionResult::False, // segment absent → condition not applicable
2140        }
2141    }
2142
2143    /// [935] Format: HHMM = 0500
2144    fn evaluate_935(&self, ctx: &EvaluationContext) -> ConditionResult {
2145        let dtm_segs = ctx.find_segments("DTM");
2146        match dtm_segs
2147            .first()
2148            .and_then(|s| s.elements.first())
2149            .and_then(|e| e.get(1))
2150        {
2151            Some(val) => validate_hhmm_equals(val, "0500"),
2152            None => ConditionResult::False, // segment absent → condition not applicable
2153        }
2154    }
2155
2156    /// [939] Format: Die Zeichenkette muss die Zeichen @ und . enthalten
2157    fn evaluate_939(&self, ctx: &EvaluationContext) -> ConditionResult {
2158        let segs = ctx.find_segments("COM");
2159        match segs
2160            .first()
2161            .and_then(|s| s.elements.first())
2162            .and_then(|e| e.first())
2163        {
2164            Some(val) => validate_email(val),
2165            None => ConditionResult::False, // segment absent → condition not applicable
2166        }
2167    }
2168
2169    /// [940] Format: Die Zeichenkette muss mit dem Zeichen + beginnen und danach dürfen nur noch Ziffern folgen
2170    fn evaluate_940(&self, ctx: &EvaluationContext) -> ConditionResult {
2171        let segs = ctx.find_segments("COM");
2172        match segs
2173            .first()
2174            .and_then(|s| s.elements.first())
2175            .and_then(|e| e.first())
2176        {
2177            Some(val) => validate_phone(val),
2178            None => ConditionResult::False, // segment absent → condition not applicable
2179        }
2180    }
2181
2182    /// [950] Format: Marktlokations-ID
2183    fn evaluate_950(&self, ctx: &EvaluationContext) -> ConditionResult {
2184        let segs = ctx.find_segments_with_qualifier("LOC", 0, "Z16");
2185        match segs
2186            .first()
2187            .and_then(|s| s.elements.get(1))
2188            .and_then(|e| e.first())
2189        {
2190            Some(val) => validate_malo_id(val),
2191            None => ConditionResult::False, // segment absent → condition not applicable
2192        }
2193    }
2194
2195    /// [951] Format: Zählpunktbezeichnung
2196    fn evaluate_951(&self, ctx: &EvaluationContext) -> ConditionResult {
2197        let segs = ctx.find_segments_with_qualifier("LOC", 0, "Z17");
2198        match segs
2199            .first()
2200            .and_then(|s| s.elements.get(1))
2201            .and_then(|e| e.first())
2202        {
2203            Some(val) => validate_zahlpunkt(val),
2204            None => ConditionResult::False, // segment absent → condition not applicable
2205        }
2206    }
2207
2208    /// [955] Format: Möglicher Wert: &lt;100
2209    // REVIEW: Format: Möglicher Wert: <100 — numeric value must be less than 100. Most likely applies to a QTY quantity value (C186.D6060, elements[0][1]). validate_numeric with "<" and threshold 100.0 covers this. Medium confidence because the exact segment context (QTY vs PRI vs PCT) is not specified — QTY is the most common numeric value carrier in ORDERS. (medium confidence)
2210    fn evaluate_955(&self, ctx: &EvaluationContext) -> ConditionResult {
2211        let segs = ctx.find_segments("QTY");
2212        match segs
2213            .first()
2214            .and_then(|s| s.elements.first())
2215            .and_then(|e| e.get(1))
2216        {
2217            Some(val) => validate_numeric(val, "<", 100.0),
2218            None => ConditionResult::False, // segment absent → condition not applicable
2219        }
2220    }
2221
2222    /// [960] Format: Netzlokations-ID
2223    fn evaluate_960(&self, ctx: &EvaluationContext) -> ConditionResult {
2224        let segs = ctx.find_segments_with_qualifier("LOC", 0, "Z18");
2225        match segs
2226            .first()
2227            .and_then(|s| s.elements.get(1))
2228            .and_then(|e| e.first())
2229        {
2230            Some(val) => validate_malo_id(val),
2231            None => ConditionResult::False, // segment absent → condition not applicable
2232        }
2233    }
2234
2235    /// [961] Format: SR-ID
2236    fn evaluate_961(&self, ctx: &EvaluationContext) -> ConditionResult {
2237        let segs = ctx.find_segments_with_qualifier("LOC", 0, "Z19");
2238        match segs
2239            .first()
2240            .and_then(|s| s.elements.get(1))
2241            .and_then(|e| e.first())
2242        {
2243            Some(val) => validate_malo_id(val),
2244            None => ConditionResult::False, // segment absent → condition not applicable
2245        }
2246    }
2247
2248    /// [962] Format: max. 6 Vorkommastellen
2249    // REVIEW: Format: max 6 integer digits (Vorkommastellen). Applied to QTY element[0][1] as the most common numeric data field in ORDERS requiring integer-part validation. Uses validate_max_integer_digits helper. Confidence medium because the target segment is inferred from context rather than explicitly stated. (medium confidence)
2250    fn evaluate_962(&self, ctx: &EvaluationContext) -> ConditionResult {
2251        // Format: max. 6 Vorkommastellen — applied to QTY value (most likely numeric field in ORDERS)
2252        let segs = ctx.find_segments("QTY");
2253        match segs
2254            .first()
2255            .and_then(|s| s.elements.first())
2256            .and_then(|e| e.get(1))
2257        {
2258            Some(val) => validate_max_integer_digits(val, 6),
2259            None => ConditionResult::False, // segment absent → condition not applicable
2260        }
2261    }
2262
2263    /// [2001] Die SG29 ist so oft zu wiederholen, wie ab dem DTM+203 (Ausführungsdatum) Tranchen zu der in der SG2 genannten Marktlokation vorhanden sind.
2264    fn evaluate_2001(&self, _ctx: &EvaluationContext) -> ConditionResult {
2265        // Hinweis: SG29 ist so oft zu wiederholen, wie ab dem DTM+203 (Ausführungsdatum) Tranchen zu der in der SG2 genannten Marktlokation vorhanden sind — informational cardinality annotation, always applies
2266        ConditionResult::True
2267    }
2268
2269    /// [2002] Ist mindestens zwei Mal anzugeben
2270    // REVIEW: Must be specified at least twice. Counts DTM+203 (Ausführungsdatum, qualifier at elements[0][0]) occurrences as a proxy for SG29 group instance count since each SG29 contains exactly one DTM+203. Condition is True when count >= 2. (medium confidence)
2271    fn evaluate_2002(&self, ctx: &EvaluationContext) -> ConditionResult {
2272        // "Ist mindestens zwei Mal anzugeben" — SG29 must appear at least twice.
2273        // DTM+203 (Ausführungsdatum) occurs exactly once per SG29 instance,
2274        // so counting DTM+203 segments gives the SG29 repetition count.
2275        let count = ctx.find_segments_with_qualifier("DTM", 0, "203").len();
2276        ConditionResult::from(count >= 2)
2277    }
2278
2279    /// [2003] Die SG29 ist so oft zu wiederholen, wie ab dem DTM+203 (Ausführungsdatum) Messlokationen zu der in der SG2 genannten Marktlokation vorhanden sind und für jede dieser Messlokationen müssen alle M...
2280    fn evaluate_2003(&self, _ctx: &EvaluationContext) -> ConditionResult {
2281        // Hinweis: SG29 repetition cardinality rule — informational annotation documenting that
2282        // SG29 must repeat once per Messlokation associated with the Marktlokation from DTM+203,
2283        // and all Messprodukte for each Messlokation (including Tranchen) must be listed.
2284        // This is a structural cardinality guidance note, always applies.
2285        ConditionResult::True
2286    }
2287
2288    /// [2004] Die SG29 ist so oft zu wiederholen, dass alle Geräte der betroffenen Geräteart die im Rahmen des Gerätewechsels aufgrund MSB-Wechsel getauscht werden sollen genannt sind.
2289    fn evaluate_2004(&self, _ctx: &EvaluationContext) -> ConditionResult {
2290        // Hinweis: Die SG29 ist so oft zu wiederholen, dass alle Geräte der betroffenen Geräteart
2291        // die im Rahmen des Gerätewechsels aufgrund MSB-Wechsel getauscht werden sollen, genannt sind.
2292        // Informational cardinality note — always applies.
2293        ConditionResult::True
2294    }
2295
2296    /// [2005] Pro SG29 LIN ist die SG34 RFF+Z09 (Gerätenummer) genau einmal anzugeben
2297    // REVIEW: Per SG29 LIN, RFF+Z09 (Gerätenummer) must appear exactly once. We check that there is exactly one RFF segment with qualifier Z09 in the message context. This is a cardinality constraint evaluated at message level via segment counting. (medium confidence)
2298    fn evaluate_2005(&self, ctx: &EvaluationContext) -> ConditionResult {
2299        {
2300            let rffs = ctx.find_segments_with_qualifier("RFF", 0, "Z09");
2301            ConditionResult::from(rffs.len() == 1)
2302        }
2303    }
2304
2305    /// [2006] Pro SG29 LIN ist die SG34 RFF+Z09 (Gerätenummer) bis zu dreimal anzugeben
2306    // REVIEW: Per SG29 LIN, RFF+Z09 (Gerätenummer) may appear up to three times. We verify that at most 3 RFF segments with qualifier Z09 exist in the message context. (medium confidence)
2307    fn evaluate_2006(&self, ctx: &EvaluationContext) -> ConditionResult {
2308        {
2309            let rffs = ctx.find_segments_with_qualifier("RFF", 0, "Z09");
2310            ConditionResult::from(rffs.len() <= 3)
2311        }
2312    }
2313
2314    /// [2007] Die SG29 ist so oft zu wiederholen, wie ab dem DTM+203 (Ausführungsdatum) Messlokationen zu der in der SG2 genannten Netzlokation vorhanden sind und für jede dieser Messlokationen müssen alle Me...
2315    fn evaluate_2007(&self, _ctx: &EvaluationContext) -> ConditionResult {
2316        // Hinweis: Die SG29 ist so oft zu wiederholen, wie ab dem DTM+203 (Ausführungsdatum)
2317        // Messlokationen zu der in der SG2 genannten Netzlokation vorhanden sind und für jede
2318        // dieser Messlokationen müssen alle Messprodukte genannt sein, die ab dem DTM+203
2319        // (Ausführungsdatum) in der SG2 genannten Netzlokation vorhanden sind.
2320        // Informational cardinality note — always applies.
2321        ConditionResult::True
2322    }
2323
2324    /// [2044] Pro SG29 LIN ist die SG29 PIA genau einmal anzugeben
2325    // REVIEW: Per SG29 LIN, the SG29 PIA segment must appear exactly once. We count PIA segments in the message and check for exactly one occurrence. This is a structural cardinality check on the PIA segment. (medium confidence)
2326    fn evaluate_2044(&self, ctx: &EvaluationContext) -> ConditionResult {
2327        {
2328            let pias = ctx.find_segments("PIA");
2329            ConditionResult::from(pias.len() == 1)
2330        }
2331    }
2332
2333    /// [2050] Pro Nachricht ist die SG29 genau einmal anzugeben
2334    // REVIEW: Per message, SG29 (identified by its entry segment LIN) must appear exactly once. We count all LIN segments in the message and check for exactly one occurrence. (medium confidence)
2335    fn evaluate_2050(&self, ctx: &EvaluationContext) -> ConditionResult {
2336        {
2337            let lins = ctx.find_segments("LIN");
2338            ConditionResult::from(lins.len() == 1)
2339        }
2340    }
2341
2342    /// [2060] Pro Nachricht ist die SG29 LIN+Z64 (Erforderliches Produkt Schaltzeitdefinitionen) maximal einmal anzugeben
2343    fn evaluate_2060(&self, ctx: &EvaluationContext) -> ConditionResult {
2344        {
2345            let lins = ctx.find_segments("LIN");
2346            let count = lins
2347                .iter()
2348                .filter(|s| {
2349                    s.elements
2350                        .get(1)
2351                        .and_then(|e| e.first())
2352                        .is_some_and(|v| v == "Z64")
2353                })
2354                .count();
2355            ConditionResult::from(count <= 1)
2356        }
2357    }
2358
2359    /// [2061] Pro Nachricht ist die SG29 LIN++Z65 (Erforderliches Produkt Leistungskurvendefinitionen) maximal einmal anzugeben
2360    fn evaluate_2061(&self, ctx: &EvaluationContext) -> ConditionResult {
2361        {
2362            let lins = ctx.find_segments("LIN");
2363            let count = lins
2364                .iter()
2365                .filter(|s| {
2366                    s.elements
2367                        .get(1)
2368                        .and_then(|e| e.first())
2369                        .is_some_and(|v| v == "Z65")
2370                })
2371                .count();
2372            ConditionResult::from(count <= 1)
2373        }
2374    }
2375
2376    /// [2062] Pro Nachricht ist die SG29 LIN++Z66 (Erforderliches Produkt Ad-hoc-Steuerkanal) maximal einmal anzugeben
2377    // REVIEW: Count LIN segments where elements[1][0]=="Z66" (LIN++Z66, ad-hoc Steuerkanal). Condition is True when at most one such SG29 line item is present per message. (medium confidence)
2378    fn evaluate_2062(&self, ctx: &EvaluationContext) -> ConditionResult {
2379        let count = ctx
2380            .find_segments("LIN")
2381            .iter()
2382            .filter(|s| {
2383                s.elements
2384                    .get(1)
2385                    .and_then(|e| e.first())
2386                    .is_some_and(|v| v == "Z66")
2387            })
2388            .count();
2389        ConditionResult::from(count <= 1)
2390    }
2391
2392    /// [2063] Pro Nachricht ist die SG29 LIN++Z67 (Erforderliches Messprodukt für Werte nach Typ 2 aus Backend) maximal einmal anzugeben
2393    // REVIEW: Count LIN segments where elements[1][0]=="Z67" (LIN++Z67, Messprodukt Typ 2 Backend). Condition is True when at most one such SG29 line item is present per message. (medium confidence)
2394    fn evaluate_2063(&self, ctx: &EvaluationContext) -> ConditionResult {
2395        let count = ctx
2396            .find_segments("LIN")
2397            .iter()
2398            .filter(|s| {
2399                s.elements
2400                    .get(1)
2401                    .and_then(|e| e.first())
2402                    .is_some_and(|v| v == "Z67")
2403            })
2404            .count();
2405        ConditionResult::from(count <= 1)
2406    }
2407
2408    /// [2064] Pro Nachricht ist die SG29 LIN++Z68 (Erforderliches Produkt Konfigurationserlaubnis für Werte nach Typ 2 aus SMGW) maximal einmal anzugeben
2409    // REVIEW: Count LIN segments where elements[1][0]=="Z68" (LIN++Z68, Konfigurationserlaubnis Typ 2 SMGW). Condition is True when at most one such SG29 line item is present per message. (medium confidence)
2410    fn evaluate_2064(&self, ctx: &EvaluationContext) -> ConditionResult {
2411        let count = ctx
2412            .find_segments("LIN")
2413            .iter()
2414            .filter(|s| {
2415                s.elements
2416                    .get(1)
2417                    .and_then(|e| e.first())
2418                    .is_some_and(|v| v == "Z68")
2419            })
2420            .count();
2421        ConditionResult::from(count <= 1)
2422    }
2423
2424    /// [2065] Diese SG30 ist so oft zu wiederholen, wie zu den unterschiedlichen Messprodukt-Position-Codes zu dem innerhalb derselben SG29 LIN im PIA+5 DE7140 (Erforderliches Produkt Konfigurationserlaubnis fü...
2425    fn evaluate_2065(&self, _ctx: &EvaluationContext) -> ConditionResult {
2426        // Hinweis: SG30 ist so oft zu wiederholen, wie unterschiedliche Messprodukt-Position-Codes für das in SG29 PIA+5 DE7140 angegebene Produkt vorhanden sind, die in der Codeliste Kapitel 4.4 mit 'Bei Schwellwertunter- / -überschreitung' gekennzeichnet sind — informational cardinality annotation referencing external code list, always applies
2427        ConditionResult::True
2428    }
2429
2430    /// [2066] Die SG3 RFF+Z37 Referenz auf ID der Technischen Ressource ist so oft zu wiederholen, bis alle IDs der Technischen Ressourcen angegeben sind, die der Steuerbaren Ressource in LOC+172 DE3225 (Meldepu...
2431    fn evaluate_2066(&self, _ctx: &EvaluationContext) -> ConditionResult {
2432        // Hinweis: Die SG3 RFF+Z37 ist so oft zu wiederholen, bis alle IDs der Technischen
2433        // Ressourcen angegeben sind, die der Steuerbaren Ressource in LOC+172 DE3225 (Meldepunkt)
2434        // mit diesem Vorgang zugeordnet werden sollen.
2435        // Informational cardinality note — always applies.
2436        ConditionResult::True
2437    }
2438
2439    /// [2088] Die SG29 ist so oft zu wiederholen, dass alle Messprodukte ab dem DTM+203 (Ausführungsdatum) zu der in der SG2 genannten Netzlokation genannt sind.
2440    fn evaluate_2088(&self, _ctx: &EvaluationContext) -> ConditionResult {
2441        // Hinweis: Die SG29 ist so oft zu wiederholen, dass alle Messprodukte ab dem DTM+203
2442        // (Ausführungsdatum) zu der in der SG2 genannten Netzlokation genannt sind.
2443        // Informational cardinality note — always applies.
2444        ConditionResult::True
2445    }
2446
2447    /// [2089] Die SG29 ist so oft zu wiederholen, dass alle Messprodukte ab dem DTM+203 (Ausführungsdatum) zu der in der SG2 genannten Marktlokation genannt sind.
2448    fn evaluate_2089(&self, _ctx: &EvaluationContext) -> ConditionResult {
2449        // Hinweis: Die SG29 ist so oft zu wiederholen, dass alle Messprodukte ab dem DTM+203
2450        // (Ausführungsdatum) zu der in der SG2 genannten Marktlokation genannt sind.
2451        // Informational cardinality note about SG29 repetition count — always applies.
2452        ConditionResult::True
2453    }
2454
2455    /// [2090] Für 33-stellige ID im SG2 LOC+172 (Meldepunkt) DE3225 mindestens einmal anzugeben
2456    fn evaluate_2090(&self, ctx: &EvaluationContext) -> ConditionResult {
2457        let locs = ctx.find_segments_with_qualifier("LOC", 0, "172");
2458        ConditionResult::from(locs.iter().any(|s| {
2459            s.elements
2460                .get(1)
2461                .and_then(|e| e.first())
2462                .is_some_and(|v| v.len() == 33)
2463        }))
2464    }
2465
2466    /// [2092] Pro Nachricht ist die SG29 maximal einmal anzugeben
2467    // REVIEW: SG29 is initiated by the LIN segment. Count all LIN segments in the message and verify there is at most one, making the condition True when the cardinality constraint is satisfied. (medium confidence)
2468    fn evaluate_2092(&self, ctx: &EvaluationContext) -> ConditionResult {
2469        ConditionResult::from(ctx.find_segments("LIN").len() <= 1)
2470    }
2471
2472    /// [2094] Pro Nachricht ist die SG29 LIN (Positionsdaten) so oft anzugeben, wie Positionen aus dem Angebot, welches in SG1 RFF+AAG (Referenz Nachrichtennummer), DE1154 angegeben ist, bestellt werden sollen.
2473    fn evaluate_2094(&self, _ctx: &EvaluationContext) -> ConditionResult {
2474        // Hinweis: Pro Nachricht ist die SG29 LIN (Positionsdaten) so oft anzugeben, wie
2475        // Positionen aus dem Angebot (referenziert in SG1 RFF+AAG DE1154) bestellt werden sollen.
2476        // Informational cardinality note — the required repetition count depends on an external
2477        // offer document that cannot be inspected from within this EDIFACT message.
2478        ConditionResult::True
2479    }
2480
2481    /// [2095] Diese SG29 ist so oft zu wiederholen, dass alle Produkte zur Lokation die ab dem DTM+203 (Ausführungsdatum) gewünscht sind und deren Kombination gemäß Codeliste der Konfigurationen Kapitel 7 "P...
2482    fn evaluate_2095(&self, _ctx: &EvaluationContext) -> ConditionResult {
2483        // Hinweis: Diese SG29 ist so oft zu wiederholen, dass alle Produkte zur Lokation
2484        // ab dem DTM+203 (Ausführungsdatum) genannt sind, deren Kombination gemäß
2485        // Codeliste der Konfigurationen Kapitel 7 möglich sind.
2486        // Informational cardinality note — valid combinations are defined by an external
2487        // code list (Kapitel 7) and cannot be validated from EDIFACT content alone.
2488        ConditionResult::True
2489    }
2490
2491    /// [2096] Die SG3 Referenz auf die ID der Tranche ist so oft zu wiederholen, wie ab dem DTM+203 (Ausführungsdatum) Tranchen zu der in der SG2 genannten Marktlokation vorhanden sind.
2492    fn evaluate_2096(&self, _ctx: &EvaluationContext) -> ConditionResult {
2493        // Hinweis: Die SG3 Referenz auf die ID der Tranche ist so oft zu wiederholen, wie
2494        // ab dem DTM+203 (Ausführungsdatum) Tranchen zu der in der SG2 genannten
2495        // Marktlokation vorhanden sind.
2496        // Informational cardinality note — the number of Tranchen for a Marktlokation is
2497        // business context that cannot be determined from the EDIFACT message alone.
2498        ConditionResult::True
2499    }
2500
2501    /// [2097] Die SG29 ist so oft zu wiederholen, dass für alle in SG3 Referenz auf ID der Tranche genannten Tranchen mindestens eine SG29 vorhanden ist.
2502    fn evaluate_2097(&self, _ctx: &EvaluationContext) -> ConditionResult {
2503        // Hinweis: Die SG29 ist so oft zu wiederholen, dass für alle in SG3 RFF+Z20
2504        // (Referenz auf ID der Tranche) genannten Tranchen mindestens eine SG29 vorhanden ist.
2505        // Informational completeness note — each Tranche referenced in SG3 must have
2506        // at least one corresponding SG29. Documents structural pairing requirements.
2507        ConditionResult::True
2508    }
2509
2510    /// [2098] Die SG2 Lieferant an der Lokation ist so oft zu wiederholen, dass für alle in SG3 Referenz auf ID der Tranche genannten Tranchen genau eine SG2 Lieferant der Lokation vorhanden ist.
2511    // REVIEW: Cardinality rule: SG2 repetition count must equal the number of SG3 tranche references. Implemented by comparing count_in_group for both groups within SG29. Medium confidence because exact group paths and SG3 RFF qualifier for 'Tranche ID' are not confirmed without the full MIG segment structure reference — the paths &["SG29", "SG2"] and &["SG29", "SG3"] are based on standard ORDERS tx_group conventions from project memory. (medium confidence)
2512    fn evaluate_2098(&self, ctx: &EvaluationContext) -> ConditionResult {
2513        // SG2 Lieferant an der Lokation must repeat once per SG3 tranche reference.
2514        // Count SG2 group instances (NAD as entry segment) and SG3 RFF tranche references.
2515        // Both counts must be equal and non-zero for the condition to be satisfied.
2516        let sg2_count = ctx.count_in_group("NAD", &["SG29", "SG2"]);
2517        let sg3_count = ctx.count_in_group("RFF", &["SG29", "SG3"]);
2518        if sg2_count == 0 || sg3_count == 0 {
2519            return ConditionResult::Unknown;
2520        }
2521        ConditionResult::from(sg2_count == sg3_count)
2522    }
2523
2524    /// [2099] Die SG2 Lieferant an der Lokation ist genau einmal anzugeben.
2525    // REVIEW: Simple cardinality check: SG2 must appear exactly once (genau einmal). Implemented using count_in_group on NAD (the entry segment of SG2) within SG29. Returns Unknown when no SG2 is found at all (not yet present), False when count > 1, True when exactly 1. Medium confidence due to unconfirmed group path without the full EDIFACT Segment Structure Reference for this PID. (medium confidence)
2526    fn evaluate_2099(&self, ctx: &EvaluationContext) -> ConditionResult {
2527        // SG2 Lieferant an der Lokation must appear exactly once.
2528        // Count NAD segments (entry segment of SG2) within the SG29 SG2 group path.
2529        let count = ctx.count_in_group("NAD", &["SG29", "SG2"]);
2530        if count == 0 {
2531            return ConditionResult::Unknown;
2532        }
2533        ConditionResult::from(count == 1)
2534    }
2535}