Skip to main content

automapper_validation/generated/fv2510/
orders_conditions_fv2510.rs

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