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