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        // HAND-EDITED: "in derselben SG29 mit Z54 in LIN … PIA+5+9991000000078:Z11" — the enclosing SG29 only, when the scope
1139        // reaches one; the message as before otherwise.
1140        if let Some(scope) = ctx.enclosing_scope("SG29") {
1141            return ConditionResult::from(
1142                ctx.find_segments_at(scope, "LIN")
1143                    .iter()
1144                    .any(|s| s.get_element(1) == "Z54")
1145                    && ctx.find_segments_at(scope, "PIA").iter().any(|s| {
1146                        s.get_element(0) == "5"
1147                            && s.get_component(1, 0) == "9991000000078"
1148                            && s.get_component(1, 1) == "Z11"
1149                    }),
1150            );
1151        }
1152        ctx.any_group_has_co_occurrence(
1153            "LIN",
1154            1,
1155            &["Z54"],
1156            "PIA",
1157            1,
1158            0,
1159            &["9991000000078"],
1160            &["SG29"],
1161        )
1162    }
1163
1164    /// [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...
1165    /// EXTERNAL: Requires context from outside the message.
1166    // 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)
1167    fn evaluate_82(&self, ctx: &EvaluationContext) -> ConditionResult {
1168        ctx.external
1169            .evaluate("other_sg29_z54_with_zaehlzeit_product")
1170    }
1171
1172    /// [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...
1173    // 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)
1174    fn evaluate_83(&self, ctx: &EvaluationContext) -> ConditionResult {
1175        match ctx
1176            .external
1177            .evaluate("other_sg29_z54_with_zaehlzeit_product")
1178        {
1179            ConditionResult::True => ConditionResult::False,
1180            ConditionResult::False => ConditionResult::True,
1181            ConditionResult::Unknown => ConditionResult::Unknown,
1182        }
1183    }
1184
1185    /// [84] IMD++Z14+Z07 vorhanden
1186    // 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)
1187    fn evaluate_84(&self, ctx: &EvaluationContext) -> ConditionResult {
1188        {
1189            let segments = ctx.find_segments("IMD");
1190            ConditionResult::from(segments.iter().any(|s| {
1191                s.elements
1192                    .get(1)
1193                    .and_then(|e| e.first())
1194                    .is_some_and(|v| v == "Z14")
1195                    && s.elements
1196                        .get(2)
1197                        .and_then(|e| e.first())
1198                        .is_some_and(|v| v == "Z07")
1199            }))
1200        }
1201    }
1202
1203    /// [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
1204    // 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)
1205    fn evaluate_85(&self, ctx: &EvaluationContext) -> ConditionResult {
1206        // HAND-EDITED: "in derselben SG29 mit Z54 in LIN … PIA+5+9991000000086:Z11" — the enclosing SG29 only, when the scope
1207        // reaches one; the message as before otherwise.
1208        if let Some(scope) = ctx.enclosing_scope("SG29") {
1209            return ConditionResult::from(
1210                ctx.find_segments_at(scope, "LIN")
1211                    .iter()
1212                    .any(|s| s.get_element(1) == "Z54")
1213                    && ctx.find_segments_at(scope, "PIA").iter().any(|s| {
1214                        s.get_element(0) == "5"
1215                            && s.get_component(1, 0) == "9991000000086"
1216                            && s.get_component(1, 1) == "Z11"
1217                    }),
1218            );
1219        }
1220        ctx.any_group_has_co_occurrence(
1221            "LIN",
1222            1,
1223            &["Z54"],
1224            "PIA",
1225            1,
1226            0,
1227            &["9991000000086"],
1228            &["SG29"],
1229        )
1230    }
1231
1232    /// [87] Wenn FTX+Z09/Z10 vorhanden
1233    fn evaluate_87(&self, ctx: &EvaluationContext) -> ConditionResult {
1234        {
1235            let segs = ctx.find_segments("FTX");
1236            ConditionResult::from(segs.iter().any(|s| {
1237                s.elements
1238                    .first()
1239                    .and_then(|e| e.first())
1240                    .is_some_and(|v| v == "Z09" || v == "Z10")
1241            }))
1242        }
1243    }
1244
1245    /// [93] Wenn in derselben Nachricht eine SG29 mit Z16 in LIN DE1229 (Erforderliches Produkt der Tranche) nicht vorhanden
1246    fn evaluate_93(&self, ctx: &EvaluationContext) -> ConditionResult {
1247        ctx.lacks_qualifier("LIN", 1, "Z16")
1248    }
1249
1250    /// [94] Wenn in derselben Nachricht eine SG29 mit Z54 in LIN DE1229 (Erforderliches Produkt der Marktlokation) nicht vorhanden
1251    fn evaluate_94(&self, ctx: &EvaluationContext) -> ConditionResult {
1252        ctx.lacks_qualifier("LIN", 1, "Z54")
1253    }
1254
1255    /// [95] Messprodukt-Code aus dem Kapitel 2.1 "Standard-Messprodukte der Marktlokation" der Codeliste der Konfigurationen
1256    /// EXTERNAL: Requires context from outside the message.
1257    fn evaluate_95(&self, ctx: &EvaluationContext) -> ConditionResult {
1258        ctx.external.evaluate("messprodukt_standard_marktlokation")
1259    }
1260
1261    /// [96] Messprodukt-Code aus dem Kapitel 2.2 "Standard-Messprodukte der Tranche" der Codeliste der Konfigurationen
1262    /// EXTERNAL: Requires context from outside the message.
1263    fn evaluate_96(&self, ctx: &EvaluationContext) -> ConditionResult {
1264        ctx.external.evaluate("messprodukt_standard_tranche")
1265    }
1266
1267    /// [97] Wenn FTX+Z10 vorhanden
1268    fn evaluate_97(&self, ctx: &EvaluationContext) -> ConditionResult {
1269        ctx.has_qualifier("FTX", 0, "Z10")
1270    }
1271
1272    /// [99] Wenn FTX+Z08/Z10 vorhanden
1273    fn evaluate_99(&self, ctx: &EvaluationContext) -> ConditionResult {
1274        ctx.any_group_has_any_qualifier("FTX", 0, &["Z08", "Z10"], &["SG29"])
1275    }
1276
1277    /// [100] Messprodukt-Code aus dem Kapitel 2.3 "Standard-Messprodukte der Messlokation" der Codeliste der Konfigurationen
1278    /// EXTERNAL: Requires context from outside the message.
1279    fn evaluate_100(&self, ctx: &EvaluationContext) -> ConditionResult {
1280        ctx.external.evaluate("messprodukt_standard_messlokation")
1281    }
1282
1283    /// [101] Wenn MP-ID in SG2 NAD+MR mit Rolle MSB in der Sparte Gas nicht vorhanden
1284    /// EXTERNAL: Requires context from outside the message.
1285    // 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)
1286    fn evaluate_101(&self, ctx: &EvaluationContext) -> ConditionResult {
1287        ctx.external.evaluate("recipient_is_msb_gas")
1288    }
1289
1290    /// [102] Wenn in derselben SG29 LIN das CCI+++Z25 (Geräteart Wandler) vorhanden
1291    fn evaluate_102(&self, ctx: &EvaluationContext) -> ConditionResult {
1292        // HAND-EDITED: "in dieser/derselben SG29" — scoped to the enclosing group.
1293        ctx.this_group_has_qualifier("CCI", 2, "Z25", &["SG29"])
1294    }
1295
1296    /// [103] Wenn in derselben SG29 LIN das CCI+++Z25 (Geräteart Wandler) nicht vorhanden
1297    fn evaluate_103(&self, ctx: &EvaluationContext) -> ConditionResult {
1298        // HAND-EDITED: "in dieser/derselben SG29" — scoped to the enclosing group.
1299        match ctx.this_group_has_qualifier("CCI", 2, "Z25", &["SG29"]) {
1300            ConditionResult::True => ConditionResult::False,
1301            ConditionResult::False => ConditionResult::True,
1302            ConditionResult::Unknown => ConditionResult::Unknown,
1303        }
1304    }
1305
1306    /// [104] Wenn MP-ID in SG2 NAD+VY mit Rolle LF vorhanden
1307    /// EXTERNAL: Requires context from outside the message.
1308    // 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)
1309    fn evaluate_104(&self, ctx: &EvaluationContext) -> ConditionResult {
1310        ctx.external.evaluate("nad_vy_is_lf")
1311    }
1312
1313    /// [105] Wenn die bisherige Konfiguration mit Zählzeiten des LF vom LF beendet werden soll
1314    /// EXTERNAL: Requires context from outside the message.
1315    fn evaluate_105(&self, ctx: &EvaluationContext) -> ConditionResult {
1316        ctx.external
1317            .evaluate("bisherige_konfiguration_zaehltzeiten_lf_beenden")
1318    }
1319
1320    /// [106] wenn IMD++Z60 (Abbestellung Messprodukt mit Zählzeitdefinition des LF) nicht vorhanden
1321    fn evaluate_106(&self, ctx: &EvaluationContext) -> ConditionResult {
1322        ctx.lacks_qualifier("IMD", 1, "Z60")
1323    }
1324
1325    /// [107] Wenn IMD++Z57 (Abbestellung Zählzeitdefinition) nicht vorhanden
1326    fn evaluate_107(&self, ctx: &EvaluationContext) -> ConditionResult {
1327        ctx.lacks_qualifier("IMD", 1, "Z57")
1328    }
1329
1330    /// [108] Wenn RFF+AGK (Konfigurations-ID) nicht vorhanden
1331    fn evaluate_108(&self, ctx: &EvaluationContext) -> ConditionResult {
1332        ctx.lacks_qualifier("RFF", 0, "AGK")
1333    }
1334
1335    /// [109] Wenn LOC+172 (Meldepunkt) nicht vorhanden
1336    fn evaluate_109(&self, ctx: &EvaluationContext) -> ConditionResult {
1337        ctx.lacks_qualifier("LOC", 0, "172")
1338    }
1339
1340    /// [110] wenn DTM+163 (Beginn Zeitraum für Wertanfrage) vorhanden
1341    fn evaluate_110(&self, ctx: &EvaluationContext) -> ConditionResult {
1342        ctx.has_qualifier("DTM", 0, "163")
1343    }
1344
1345    /// [112] Wenn in derselben SG29 LIN++Z54 (Erforderliches Produkt der Marktlokation), das PIA+5+9991000000078: Z11 (Wirkarbeit Lastgang 1/4 stündlich) vorhanden ist
1346    // 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)
1347    fn evaluate_112(&self, ctx: &EvaluationContext) -> ConditionResult {
1348        // HAND-EDITED: "in derselben SG29 LIN++Z54 … PIA+5+9991000000078:Z11" — the enclosing SG29 only, when the scope
1349        // reaches one; the message as before otherwise.
1350        if let Some(scope) = ctx.enclosing_scope("SG29") {
1351            return ConditionResult::from(
1352                ctx.find_segments_at(scope, "LIN")
1353                    .iter()
1354                    .any(|s| s.get_element(1) == "Z54")
1355                    && ctx.find_segments_at(scope, "PIA").iter().any(|s| {
1356                        s.get_element(0) == "5"
1357                            && s.get_component(1, 0) == "9991000000078"
1358                            && s.get_component(1, 1) == "Z11"
1359                    }),
1360            );
1361        }
1362        ctx.any_group_has_co_occurrence(
1363            "LIN",
1364            1,
1365            &["Z54"],
1366            "PIA",
1367            1,
1368            0,
1369            &["9991000000078"],
1370            &["SG29"],
1371        )
1372    }
1373
1374    /// [113] Wenn LIN DE1229 mit Code Z42 (Zählzeitdefinition) vorhanden
1375    fn evaluate_113(&self, ctx: &EvaluationContext) -> ConditionResult {
1376        ctx.has_qualifier("LIN", 1, "Z42")
1377    }
1378
1379    /// [114] Wenn LIN DE1229 mit Code Z69 (Schaltzeitdefinition) vorhanden
1380    fn evaluate_114(&self, ctx: &EvaluationContext) -> ConditionResult {
1381        ctx.has_qualifier("LIN", 1, "Z69")
1382    }
1383
1384    /// [115] Wenn LIN DE1229 mit Code Z70 (Leistungskurvendefinition) vorhanden
1385    fn evaluate_115(&self, ctx: &EvaluationContext) -> ConditionResult {
1386        ctx.has_qualifier("LIN", 1, "Z70")
1387    }
1388
1389    /// [117] Wenn SG29 LIN++Z64 (Erforderliches Produkt Schaltzeitdefinitionen) vorhanden
1390    fn evaluate_117(&self, ctx: &EvaluationContext) -> ConditionResult {
1391        ctx.has_qualifier("LIN", 1, "Z64")
1392    }
1393
1394    /// [118] Wenn SG29 LIN++Z65 (Erforderliches Produkt Leistungskurvendefinitionen) vorhanden
1395    fn evaluate_118(&self, ctx: &EvaluationContext) -> ConditionResult {
1396        ctx.has_qualifier("LIN", 1, "Z65")
1397    }
1398
1399    /// [119] Wenn SG29 LIN++Z66 (Erforderliches Produkt Ad-hoc-Steuerkanal) vorhanden
1400    fn evaluate_119(&self, ctx: &EvaluationContext) -> ConditionResult {
1401        ctx.has_qualifier("LIN", 1, "Z66")
1402    }
1403
1404    /// [120] Wenn SG29 LIN++Z67 (Erforderliches Messprodukt für Werte nach Typ 2 aus Backend) vorhanden
1405    fn evaluate_120(&self, ctx: &EvaluationContext) -> ConditionResult {
1406        ctx.has_qualifier("LIN", 1, "Z67")
1407    }
1408
1409    /// [121] Wenn SG29 LIN++Z68 (Erforderliches Produkt Konfigurationserlaubnis für Werte nach Typ 2 aus SMGW) vorhanden
1410    fn evaluate_121(&self, ctx: &EvaluationContext) -> ConditionResult {
1411        ctx.has_qualifier("LIN", 1, "Z68")
1412    }
1413
1414    /// [122] Wenn SG1 RFF+Z41 (Referenznummer des Vorgangs der Anmeldung nach WiM) nicht vorhanden
1415    fn evaluate_122(&self, ctx: &EvaluationContext) -> ConditionResult {
1416        ctx.lacks_qualifier("RFF", 0, "Z41")
1417    }
1418
1419    /// [123] Wenn DTM+203 (Ausführungsdatum) nicht vorhanden
1420    fn evaluate_123(&self, ctx: &EvaluationContext) -> ConditionResult {
1421        ctx.lacks_qualifier("DTM", 0, "203")
1422    }
1423
1424    /// [124] Wenn SG1 RFF+Z41 (Referenznummer des Vorgangs der Anmeldung nach WiM) vorhanden
1425    fn evaluate_124(&self, ctx: &EvaluationContext) -> ConditionResult {
1426        ctx.has_qualifier("RFF", 0, "Z41")
1427    }
1428
1429    /// [125] Es sind nur die Konfigurations-Produkte erlaubt, die in der Codeliste der Konfigurationen im Kapitel 4.1 „Konfigurationsprodukte Schaltzeitdefinition“ enthalten sind.
1430    /// EXTERNAL: Requires context from outside the message.
1431    fn evaluate_125(&self, ctx: &EvaluationContext) -> ConditionResult {
1432        ctx.external
1433            .evaluate("konfigurationsprodukt_schaltzeitdefinition")
1434    }
1435
1436    /// [130] Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Marktlokation angegeben ist
1437    fn evaluate_130(&self, ctx: &EvaluationContext) -> ConditionResult {
1438        // Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Marktlokation angegeben ist
1439        // LOC Meldepunkt: elements[0][0]=="172", elements[1][0]==DE3225 (Identifikator)
1440        let locs = ctx.find_segments_with_qualifier("LOC", 0, "172");
1441        match locs
1442            .first()
1443            .and_then(|s| s.elements.get(1))
1444            .and_then(|e| e.first())
1445        {
1446            Some(val) if !val.is_empty() => validate_malo_id(val),
1447            Some(_) => ConditionResult::False,
1448            None => ConditionResult::False, // segment absent → condition not applicable
1449        }
1450    }
1451
1452    /// [131] Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Messlokation angegeben ist
1453    /// EXTERNAL: Requires context from outside the message.
1454    fn evaluate_131(&self, ctx: &EvaluationContext) -> ConditionResult {
1455        ctx.external.evaluate("meldepunkt_is_messlokation_id")
1456    }
1457
1458    /// [132] Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Netzlokation angegeben ist
1459    /// EXTERNAL: Requires context from outside the message.
1460    fn evaluate_132(&self, ctx: &EvaluationContext) -> ConditionResult {
1461        ctx.external.evaluate("meldepunkt_is_netzlokation_id")
1462    }
1463
1464    /// [133] Wenn in LOC+172 DE3225 (Meldepunkt) die ID einer Steuerbaren Ressource angegeben ist
1465    /// EXTERNAL: Requires context from outside the message.
1466    fn evaluate_133(&self, ctx: &EvaluationContext) -> ConditionResult {
1467        ctx.external
1468            .evaluate("meldepunkt_is_steuerbare_ressource_id")
1469    }
1470
1471    /// [134] Wenn die Position in der ursprünglichen Antwort auf die Bestellung aus SG1 RFF+Z42 vorhanden war und reklamiert werden soll
1472    // 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)
1473    fn evaluate_134(&self, ctx: &EvaluationContext) -> ConditionResult {
1474        ctx.has_qualifier("RFF", 0, "Z42")
1475    }
1476
1477    /// [135] Wenn SG29 LIN++Z64 (Erforderliches Produkt Schaltzeitdefinitionen) nicht vorhanden
1478    fn evaluate_135(&self, ctx: &EvaluationContext) -> ConditionResult {
1479        ctx.lacks_qualifier("LIN", 1, "Z64")
1480    }
1481
1482    /// [136] Wenn SG29 LIN++Z65 (Erforderliches Produkt Leistungskurvendefinitionen) nicht vorhanden
1483    fn evaluate_136(&self, ctx: &EvaluationContext) -> ConditionResult {
1484        ctx.lacks_qualifier("LIN", 1, "Z65")
1485    }
1486
1487    /// [137] Wenn SG29 LIN++Z66 (Erforderliches Produkt Ad-hoc-Steuerkanal) nicht vorhanden
1488    fn evaluate_137(&self, ctx: &EvaluationContext) -> ConditionResult {
1489        ctx.lacks_qualifier("LIN", 1, "Z66")
1490    }
1491
1492    /// [138] Wenn SG29 LIN++Z67 (Erforderliches Messprodukt für Werte nach Typ 2 aus Backend) nicht vorhanden
1493    fn evaluate_138(&self, ctx: &EvaluationContext) -> ConditionResult {
1494        ctx.lacks_qualifier("LIN", 1, "Z67")
1495    }
1496
1497    /// [139] Wenn SG29 LIN++Z68 (Erforderliches Produkt Konfigurationserlaubnis für Werte nach Typ 2 aus SMGW) nicht vorhanden
1498    fn evaluate_139(&self, ctx: &EvaluationContext) -> ConditionResult {
1499        ctx.lacks_qualifier("LIN", 1, "Z68")
1500    }
1501
1502    /// [140] Messprodukt-Code aus dem Kapitel 2.4 "Standard-Messprodukte der Netzlokation" der Codeliste der Konfigurationen
1503    /// EXTERNAL: Requires context from outside the message.
1504    fn evaluate_140(&self, ctx: &EvaluationContext) -> ConditionResult {
1505        ctx.external
1506            .evaluate("is_standard_messprodukt_netzlokation_code")
1507    }
1508
1509    /// [147] wenn im DE3155 in demselben COM der Code EM vorhanden ist
1510    fn evaluate_147(&self, ctx: &EvaluationContext) -> ConditionResult {
1511        let com_segments = ctx.find_segments("COM");
1512        ConditionResult::from(com_segments.iter().any(|s| {
1513            s.elements
1514                .first()
1515                .and_then(|e| e.get(1))
1516                .is_some_and(|v| v == "EM")
1517        }))
1518    }
1519
1520    /// [148] wenn im DE3155 in demselben COM der Code TE / FX / AJ / AL vorhanden ist
1521    fn evaluate_148(&self, ctx: &EvaluationContext) -> ConditionResult {
1522        let com_segments = ctx.find_segments("COM");
1523        ConditionResult::from(com_segments.iter().any(|s| {
1524            s.elements
1525                .first()
1526                .and_then(|e| e.get(1))
1527                .is_some_and(|v| matches!(v.as_str(), "TE" | "FX" | "AJ" | "AL"))
1528        }))
1529    }
1530
1531    /// [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...
1532    /// EXTERNAL: Requires context from outside the message.
1533    fn evaluate_153(&self, ctx: &EvaluationContext) -> ConditionResult {
1534        ctx.external.evaluate("product_code_level_messlokation")
1535    }
1536
1537    /// [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...
1538    /// EXTERNAL: Requires context from outside the message.
1539    fn evaluate_154(&self, ctx: &EvaluationContext) -> ConditionResult {
1540        ctx.external.evaluate("product_code_level_netzlokation")
1541    }
1542
1543    /// [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...
1544    /// EXTERNAL: Requires context from outside the message.
1545    fn evaluate_155(&self, ctx: &EvaluationContext) -> ConditionResult {
1546        ctx.external
1547            .evaluate("product_code_level_steuerbare_ressource")
1548    }
1549
1550    /// [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ü...
1551    /// EXTERNAL: Requires context from outside the message.
1552    fn evaluate_156(&self, ctx: &EvaluationContext) -> ConditionResult {
1553        ctx.external.evaluate("product_code_orderable_by_nb")
1554    }
1555
1556    /// [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ü...
1557    /// EXTERNAL: Requires context from outside the message.
1558    fn evaluate_157(&self, ctx: &EvaluationContext) -> ConditionResult {
1559        ctx.external.evaluate("product_code_orderable_by_lf")
1560    }
1561
1562    /// [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.
1563    /// EXTERNAL: Requires context from outside the message.
1564    fn evaluate_158(&self, ctx: &EvaluationContext) -> ConditionResult {
1565        ctx.external
1566            .evaluate("product_code_in_abrechnungsdaten_configuration_list")
1567    }
1568
1569    /// [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...
1570    /// EXTERNAL: Requires context from outside the message.
1571    fn evaluate_159(&self, ctx: &EvaluationContext) -> ConditionResult {
1572        ctx.external
1573            .evaluate("abrechnungsdaten_product_has_property_code_column")
1574    }
1575
1576    /// [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 ...
1577    /// EXTERNAL: Requires context from outside the message.
1578    fn evaluate_160(&self, ctx: &EvaluationContext) -> ConditionResult {
1579        ctx.external
1580            .evaluate("abrechnungsdaten_property_code_matches_product_row")
1581    }
1582
1583    /// [161] Wenn in derselben SG29 LIN (Erforderliches Produkt Abrechnungsdaten) das SG30 CAV+ZH9 (Code der Produkteigenschaft) nicht vorhanden ist.
1584    fn evaluate_161(&self, ctx: &EvaluationContext) -> ConditionResult {
1585        // HAND-EDITED: "in derselben SG29 LIN das SG30 CAV+ZH9 nicht vorhanden" — the enclosing SG29 only, when the scope
1586        // reaches one; the message as before otherwise.
1587        if let Some(scope) = ctx.enclosing_scope("SG29") {
1588            return ConditionResult::from(
1589                !ctx.find_segments_at(scope, "CAV")
1590                    .iter()
1591                    .any(|s| s.get_element(0) == "ZH9"),
1592            );
1593        }
1594        ctx.any_group_has_qualifier_without("PIA", 0, "5", "CAV", 0, "ZH9", &["SG4", "SG29"])
1595    }
1596
1597    /// [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...
1598    /// EXTERNAL: Requires context from outside the message.
1599    fn evaluate_162(&self, ctx: &EvaluationContext) -> ConditionResult {
1600        ctx.external
1601            .evaluate("abrechnungsdaten_value_range_matches_product_row")
1602    }
1603
1604    /// [163] Wenn innerhalb der Nachricht eine SG30 CCI+++ZA9 (Messprodukt für Übertragungsnetzbetreiber relevant) vorhanden ist.
1605    fn evaluate_163(&self, ctx: &EvaluationContext) -> ConditionResult {
1606        ctx.has_qualifier("CCI", 2, "ZA9")
1607    }
1608
1609    /// [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.
1610    /// EXTERNAL: Requires context from outside the message.
1611    fn evaluate_164(&self, ctx: &EvaluationContext) -> ConditionResult {
1612        ctx.external.evaluate("tranche_configuration_unchanged")
1613    }
1614
1615    /// [167] Wenn SG2 NAD+DP (Meldepunkt), SG3 RFF+Z20 (Referenz auf ID der Tranche) vorhanden
1616    fn evaluate_167(&self, ctx: &EvaluationContext) -> ConditionResult {
1617        match (
1618            ctx.has_qualifier("NAD", 0, "DP"),
1619            ctx.has_qualifier("RFF", 0, "Z20"),
1620        ) {
1621            (ConditionResult::True, ConditionResult::True) => ConditionResult::True,
1622            (ConditionResult::False, _) | (_, ConditionResult::False) => ConditionResult::False,
1623            _ => ConditionResult::Unknown,
1624        }
1625    }
1626
1627    /// [168] Wenn SG2 NAD+DP (Meldepunkt), SG3 RFF+Z20 (Referenz auf ID der Tranche) nicht vorhanden
1628    fn evaluate_168(&self, ctx: &EvaluationContext) -> ConditionResult {
1629        match ctx.has_qualifier("NAD", 0, "DP") {
1630            ConditionResult::True => ctx.lacks_qualifier("RFF", 0, "Z20"),
1631            other => other,
1632        }
1633    }
1634
1635    /// [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
1636    fn evaluate_169(&self, ctx: &EvaluationContext) -> ConditionResult {
1637        ctx.any_group_has_co_occurrence("LIN", 1, &["Z19"], "CCI", 0, 0, &["Z39"], &["SG29"])
1638    }
1639
1640    /// [170] Wenn in derselben SG29 LIN die SG30 CCI+Z37++ZD1 (Basis zur Bildung der Tranchengröße) (Prozentual) vorhanden
1641    fn evaluate_170(&self, ctx: &EvaluationContext) -> ConditionResult {
1642        // HAND-EDITED: "in dieser/derselben SG29" — scoped to the enclosing group.
1643        ctx.this_group_has_qualified_value("CCI", 0, "Z37", 2, 0, &["ZD1"], &["SG29"])
1644    }
1645
1646    /// [171] Wenn in derselben SG29 LIN (Erforderliches Produkt der Tranche) das IMD+++Z64 (Leistungsbeschreibung Konfiguration) (Neukonfiguration) vorhanden ist
1647    fn evaluate_171(&self, ctx: &EvaluationContext) -> ConditionResult {
1648        // HAND-EDITED: "in dieser/derselben SG29" — scoped to the enclosing group.
1649        ctx.this_group_has_qualifier("IMD", 2, "Z64", &["SG29"])
1650    }
1651
1652    /// [173] Wenn IMD++Z66 (Beendigung Konfiguration aufgrund Überführung der Marktlokation zu ruhender Marktlokation) vorhanden
1653    fn evaluate_173(&self, ctx: &EvaluationContext) -> ConditionResult {
1654        ctx.has_qualifier("IMD", 1, "Z66")
1655    }
1656
1657    /// [174] Wenn IMD++Z67 (Aktivierung Konfiguration in der derzeit ruhenden Marktlokation) vorhanden
1658    fn evaluate_174(&self, ctx: &EvaluationContext) -> ConditionResult {
1659        ctx.has_qualifier("IMD", 1, "Z67")
1660    }
1661
1662    /// [175] Wenn SG2 NAD+DP (Meldepunkt), SG3 RFF+Z59 (Referenz auf die ID der Marktlokation der Kundenanlage) vorhanden
1663    fn evaluate_175(&self, ctx: &EvaluationContext) -> ConditionResult {
1664        match (
1665            ctx.has_qualifier("NAD", 0, "DP"),
1666            ctx.has_qualifier("RFF", 0, "Z59"),
1667        ) {
1668            (ConditionResult::True, ConditionResult::True) => ConditionResult::True,
1669            (ConditionResult::False, _) | (_, ConditionResult::False) => ConditionResult::False,
1670            _ => ConditionResult::Unknown,
1671        }
1672    }
1673
1674    /// [176] Wenn SG2 NAD+DP (Meldepunkt), SG3 RFF+Z59 (Referenz auf die ID der Marktlokation der Kundenanlage) nicht vorhanden
1675    fn evaluate_176(&self, ctx: &EvaluationContext) -> ConditionResult {
1676        match ctx.has_qualifier("NAD", 0, "DP") {
1677            ConditionResult::True => ctx.lacks_qualifier("RFF", 0, "Z59"),
1678            other => other,
1679        }
1680    }
1681
1682    /// [177] Wenn IMD++Z66 (Beendigung Konfiguration aufgrund Überführung der Marktlokation zu ruhender Marktlokation) nicht vorhanden
1683    fn evaluate_177(&self, ctx: &EvaluationContext) -> ConditionResult {
1684        ctx.lacks_qualifier("IMD", 1, "Z66")
1685    }
1686
1687    /// [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...
1688    fn evaluate_490(&self, ctx: &EvaluationContext) -> ConditionResult {
1689        match ctx.resolved_value {
1690            Some(val) => is_mesz_utc(val),
1691            None => ConditionResult::False,
1692        }
1693    }
1694
1695    /// [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)...
1696    fn evaluate_491(&self, ctx: &EvaluationContext) -> ConditionResult {
1697        match ctx.resolved_value {
1698            Some(val) => is_mez_utc(val),
1699            None => ConditionResult::False,
1700        }
1701    }
1702
1703    /// [492] wenn MP-ID in NAD+MR aus Sparte Strom
1704    /// EXTERNAL: Requires context from outside the message.
1705    // 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)
1706    fn evaluate_492(&self, ctx: &EvaluationContext) -> ConditionResult {
1707        ctx.external.evaluate("recipient_is_strom")
1708    }
1709
1710    /// [493] wenn MP-ID in NAD+MR aus Sparte Gas
1711    /// EXTERNAL: Requires context from outside the message.
1712    // 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)
1713    fn evaluate_493(&self, ctx: &EvaluationContext) -> ConditionResult {
1714        ctx.external.evaluate("recipient_is_gas")
1715    }
1716
1717    /// [494] Das hier genannte Datum muss der Zeitpunkt sein, zu dem das Dokument erstellt wurde, oder ein Zeitpunkt, der davor liegt.
1718    // 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)
1719    fn evaluate_494(&self, ctx: &EvaluationContext) -> ConditionResult {
1720        // The date here must be the document creation time (DTM+137 Nachrichtendatum) or earlier.
1721        // DTM+137: elements[0][0]=qualifier(137), elements[0][1]=DE2380 (actual value), elements[0][2]=format(303)
1722        // Applied to Ausführungsdatum (DTM+203) as the most likely subject in ORDERS.
1723        let dtm137_segs = ctx.find_segments_with_qualifier("DTM", 0, "137");
1724        let dtm203_segs = ctx.find_segments_with_qualifier("DTM", 0, "203");
1725        let ref_val = dtm137_segs
1726            .first()
1727            .and_then(|s| s.elements.first())
1728            .and_then(|e| e.get(1));
1729        let cmp_val = dtm203_segs
1730            .first()
1731            .and_then(|s| s.elements.first())
1732            .and_then(|e| e.get(1));
1733        match (cmp_val, ref_val) {
1734            (Some(cv), Some(rv)) => ConditionResult::from(cv.as_str() <= rv.as_str()),
1735            _ => ConditionResult::Unknown,
1736        }
1737    }
1738
1739    /// [495] Der Zeitpunkt muss ≤ dem Wert im DE2380 des DTM+137 sein
1740    // 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)
1741    fn evaluate_495(&self, ctx: &EvaluationContext) -> ConditionResult {
1742        // The point in time must be <= DE2380 of DTM+137 (Nachrichtendatum).
1743        // DTM element layout per MIG: elements[0][0]=qualifier, elements[0][1]=DE2380 value, elements[0][2]=format code.
1744        // Applied to Ausführungsdatum (DTM+203) as the most relevant cross-date check in ORDERS.
1745        let dtm137_segs = ctx.find_segments_with_qualifier("DTM", 0, "137");
1746        let dtm203_segs = ctx.find_segments_with_qualifier("DTM", 0, "203");
1747        let ref_val = dtm137_segs
1748            .first()
1749            .and_then(|s| s.elements.first())
1750            .and_then(|e| e.get(1));
1751        let cmp_val = dtm203_segs
1752            .first()
1753            .and_then(|s| s.elements.first())
1754            .and_then(|e| e.get(1));
1755        match (cmp_val, ref_val) {
1756            (Some(cv), Some(rv)) => ConditionResult::from(cv.as_str() <= rv.as_str()),
1757            _ => ConditionResult::Unknown,
1758        }
1759    }
1760
1761    /// [500] Hinweis: Zählpunkt der BAS
1762    fn evaluate_500(&self, _ctx: &EvaluationContext) -> ConditionResult {
1763        ConditionResult::Unknown
1764    }
1765
1766    /// [501] Hinweis: Zählpunkt der DZR
1767    fn evaluate_501(&self, _ctx: &EvaluationContext) -> ConditionResult {
1768        ConditionResult::Unknown
1769    }
1770
1771    /// [503] Hinweis: Angabe eines technischen Ansprechpartners für die Geräteübernahme
1772    fn evaluate_503(&self, _ctx: &EvaluationContext) -> ConditionResult {
1773        ConditionResult::Unknown
1774    }
1775
1776    /// [506] Hinweis: Datum, bis zu dem der MSBA zur Fortführung verpflichtet wird
1777    fn evaluate_506(&self, _ctx: &EvaluationContext) -> ConditionResult {
1778        ConditionResult::Unknown
1779    }
1780
1781    /// [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...
1782    fn evaluate_507(&self, _ctx: &EvaluationContext) -> ConditionResult {
1783        ConditionResult::Unknown
1784    }
1785
1786    /// [514] Hinweis: Das Abonnement kann frühestens ab dem aktuellen Liefermonat beim Netzbetreiber gestartet werden.
1787    fn evaluate_514(&self, _ctx: &EvaluationContext) -> ConditionResult {
1788        ConditionResult::Unknown
1789    }
1790
1791    /// [515] Hinweis: Das angegebene Betrachtungszeitintervall bestimmt beim Start Abo bzw. Ende Abo ab bzw. bis wann (einschließlich) das Abo laufen soll.
1792    fn evaluate_515(&self, _ctx: &EvaluationContext) -> ConditionResult {
1793        ConditionResult::Unknown
1794    }
1795
1796    /// [517] Hinweis: Zählpunkt der LF-AASZR
1797    fn evaluate_517(&self, _ctx: &EvaluationContext) -> ConditionResult {
1798        ConditionResult::Unknown
1799    }
1800
1801    /// [518] Hinweis: Das angegebene Ausführungsdatum bestimmt beim Start Abo bzw. Ende Abo ab bzw. bis wann (einschließlich) das Abo laufen soll.
1802    fn evaluate_518(&self, _ctx: &EvaluationContext) -> ConditionResult {
1803        ConditionResult::Unknown
1804    }
1805
1806    /// [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.
1807    fn evaluate_519(&self, _ctx: &EvaluationContext) -> ConditionResult {
1808        ConditionResult::Unknown
1809    }
1810
1811    /// [521] Hinweis: Verwendung der ID der Marktlokation
1812    fn evaluate_521(&self, _ctx: &EvaluationContext) -> ConditionResult {
1813        // Hinweis: Verwendung der ID der Marktlokation — informational note, always applies
1814        ConditionResult::True
1815    }
1816
1817    /// [522] Hinweis: Verwendung der ID der Messlokation
1818    fn evaluate_522(&self, _ctx: &EvaluationContext) -> ConditionResult {
1819        // Hinweis: Verwendung der ID der Messlokation — informational note, always applies
1820        ConditionResult::True
1821    }
1822
1823    /// [523] Hinweis: Verwendung der ID der Tranche
1824    fn evaluate_523(&self, _ctx: &EvaluationContext) -> ConditionResult {
1825        // Hinweis: Verwendung der ID der Tranche — informational note, always applies
1826        ConditionResult::True
1827    }
1828
1829    /// [525] Hinweis: Wert aus BGM DE1004 der MSCONS
1830    fn evaluate_525(&self, _ctx: &EvaluationContext) -> ConditionResult {
1831        // Hinweis: Wert aus BGM DE1004 der MSCONS — informational note, always applies
1832        ConditionResult::True
1833    }
1834
1835    /// [527] Hinweis: Zählpunkt der BG-SZR (Kategorie B)
1836    fn evaluate_527(&self, _ctx: &EvaluationContext) -> ConditionResult {
1837        // Hinweis: Zählpunkt der BG-SZR (Kategorie B) — informational note, always applies
1838        ConditionResult::True
1839    }
1840
1841    /// [530] Hinweis: Wert aus BGM+310 DE1004 der QUOTES mit der das Angebot erfolgt ist.
1842    fn evaluate_530(&self, _ctx: &EvaluationContext) -> ConditionResult {
1843        // Hinweis: Wert aus BGM+310 DE1004 der QUOTES mit der das Angebot erfolgt ist — informational note, always applies
1844        ConditionResult::True
1845    }
1846
1847    /// [531] Hinweis: Wert aus LIN DE1082 der QUOTES, mit der das Angebot erfolgt ist
1848    fn evaluate_531(&self, _ctx: &EvaluationContext) -> ConditionResult {
1849        // Hinweis: Wert aus LIN DE1082 der QUOTES, mit der das Angebot erfolgt ist — informational note, always applies
1850        ConditionResult::True
1851    }
1852
1853    /// [532] Hinweis: Wert aus BGM+Z29 DE1004 der QUOTES, mit der das Angebot zur Abrechnung des Messstellenbetriebs erfolgt ist.
1854    fn evaluate_532(&self, _ctx: &EvaluationContext) -> ConditionResult {
1855        // Hinweis: Wert aus BGM+Z29 DE1004 der QUOTES, mit der das Angebot zur Abrechnung des Messstellenbetriebs erfolgt ist — informational note, always applies
1856        ConditionResult::True
1857    }
1858
1859    /// [533] Hinweis: Gerichtsvollzieher hat Termin vorgegeben
1860    fn evaluate_533(&self, _ctx: &EvaluationContext) -> ConditionResult {
1861        // Hinweis: Gerichtsvollzieher hat Termin vorgegeben — informational note, always applies
1862        ConditionResult::True
1863    }
1864
1865    /// [535] Hinweis: Verwendung der ID der Messlokation der Sparte Strom
1866    fn evaluate_535(&self, _ctx: &EvaluationContext) -> ConditionResult {
1867        // Hinweis: Verwendung der ID der Messlokation der Sparte Strom — informational note, always applies
1868        ConditionResult::True
1869    }
1870
1871    /// [536] Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z59
1872    fn evaluate_536(&self, _ctx: &EvaluationContext) -> ConditionResult {
1873        // Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z59 — informational note, always applies
1874        ConditionResult::True
1875    }
1876
1877    /// [539] Hinweis: Es sind nur Codes von Zählzeiten aus Liste des NB anzugeben
1878    fn evaluate_539(&self, _ctx: &EvaluationContext) -> ConditionResult {
1879        // Hinweis: Es sind nur Codes von Zählzeiten aus Liste des NB anzugeben — informational note, always applies
1880        ConditionResult::True
1881    }
1882
1883    /// [540] Hinweis: Es sind nur Codes von Zählzeiten aus Liste des LF anzugeben
1884    fn evaluate_540(&self, _ctx: &EvaluationContext) -> ConditionResult {
1885        // Hinweis: Es sind nur Codes von Zählzeiten aus Liste des LF anzugeben — informational note, always applies
1886        ConditionResult::True
1887    }
1888
1889    /// [542] Hinweis: Wert aus BGM+Z57 DE1004 der QUOTES mit der das Angebot erfolgt ist.
1890    fn evaluate_542(&self, _ctx: &EvaluationContext) -> ConditionResult {
1891        // Hinweis: Wert aus BGM+Z57 DE1004 der QUOTES mit der das Angebot erfolgt ist — informational note, always applies
1892        ConditionResult::True
1893    }
1894
1895    /// [543] Hinweis: Wert aus BGM+Z57 DE1004 der ORDERS mit der die Bestellung der Werte erfolgt ist.
1896    fn evaluate_543(&self, _ctx: &EvaluationContext) -> ConditionResult {
1897        // Hinweis: Wert aus BGM+Z57 DE1004 der ORDERS mit der die Bestellung der Werte erfolgt ist — informational note, always applies
1898        ConditionResult::True
1899    }
1900
1901    /// [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...
1902    fn evaluate_545(&self, _ctx: &EvaluationContext) -> ConditionResult {
1903        // Hinweis: Es werden nur die Messprodukte der Messlokationen angegeben... — informational note, always applies
1904        ConditionResult::True
1905    }
1906
1907    /// [547] Hinweis: Dokumentennummer aus BGM+Z60 DE1004 der UTILTS
1908    fn evaluate_547(&self, _ctx: &EvaluationContext) -> ConditionResult {
1909        // Hinweis: Dokumentennummer aus BGM+Z60 DE1004 der UTILTS — informational note, always applies
1910        ConditionResult::True
1911    }
1912
1913    /// [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...
1914    fn evaluate_548(&self, _ctx: &EvaluationContext) -> ConditionResult {
1915        // Hinweis: MP-ID des Eigentümers der Zählzeitliste — informational note, always applies
1916        ConditionResult::True
1917    }
1918
1919    /// [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, ...
1920    fn evaluate_549(&self, _ctx: &EvaluationContext) -> ConditionResult {
1921        // Hinweis: Reklamation von Zählerständen — Zeitpunktangabe vs. Zeitintervall — informational note, always applies
1922        ConditionResult::True
1923    }
1924
1925    /// [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...
1926    fn evaluate_550(&self, _ctx: &EvaluationContext) -> ConditionResult {
1927        // Hinweis: Reklamation fehlender Zählerstand bei Turnusablesung — informational note, always applies
1928        ConditionResult::True
1929    }
1930
1931    /// [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 ...
1932    fn evaluate_551(&self, _ctx: &EvaluationContext) -> ConditionResult {
1933        // Hinweis: SG29 Wiederholung für alle Messprodukte und Zählzeiten — informational note, always applies
1934        ConditionResult::True
1935    }
1936
1937    /// [552] Hinweis: Verwendung der ID der Netzlokation
1938    fn evaluate_552(&self, _ctx: &EvaluationContext) -> ConditionResult {
1939        // Hinweis: Verwendung der ID der Netzlokation — informational note, always applies
1940        ConditionResult::True
1941    }
1942
1943    /// [553] Hinweis: Verwendung der ID der Steuerbaren Ressource
1944    fn evaluate_553(&self, _ctx: &EvaluationContext) -> ConditionResult {
1945        // Hinweis: Verwendung der ID der Steuerbaren Ressource — informational note, always applies
1946        ConditionResult::True
1947    }
1948
1949    /// [554] Hinweis: Wert aus BGM+Z74 DE1004 der QUOTES mit der das Angebot erfolgt ist.
1950    fn evaluate_554(&self, _ctx: &EvaluationContext) -> ConditionResult {
1951        // Hinweis: Wert aus BGM+Z74 DE1004 der QUOTES — informational note about value origin, always applies
1952        ConditionResult::True
1953    }
1954
1955    /// [555] Hinweis: Vorgangsnummer aus SG4 IDE+24 DE7402 der UTILMD mit BGM+E01 mit der die Anmeldung des MSB-Wechsels erfolgt ist.
1956    fn evaluate_555(&self, _ctx: &EvaluationContext) -> ConditionResult {
1957        // Hinweis: Vorgangsnummer aus SG4 IDE+24 DE7402 der UTILMD — informational note about value origin, always applies
1958        ConditionResult::True
1959    }
1960
1961    /// [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...
1962    fn evaluate_557(&self, _ctx: &EvaluationContext) -> ConditionResult {
1963        // Hinweis: Only Messprodukte for Messlokationen required for the named Netzlokation are specified — informational note, always applies
1964        ConditionResult::True
1965    }
1966
1967    /// [558] Hinweis: Dokumentennummer aus BGM+Z78 DE1004 der UTILTS
1968    fn evaluate_558(&self, _ctx: &EvaluationContext) -> ConditionResult {
1969        // Hinweis: Dokumentennummer aus BGM+Z78 DE1004 der UTILTS — informational note, always applies
1970        ConditionResult::True
1971    }
1972
1973    /// [559] Hinweis: Dokumentennummer aus BGM+Z79 DE1004 der UTILTS
1974    fn evaluate_559(&self, _ctx: &EvaluationContext) -> ConditionResult {
1975        // Hinweis: Dokumentennummer aus BGM+Z79 DE1004 der UTILTS — informational note, always applies
1976        ConditionResult::True
1977    }
1978
1979    /// [560] Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z80
1980    fn evaluate_560(&self, _ctx: &EvaluationContext) -> ConditionResult {
1981        // Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z80 — informational note, always applies
1982        ConditionResult::True
1983    }
1984
1985    /// [561] Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z81
1986    fn evaluate_561(&self, _ctx: &EvaluationContext) -> ConditionResult {
1987        // Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z81 — informational note, always applies
1988        ConditionResult::True
1989    }
1990
1991    /// [562] Hinweis: Wert aus BGM+Z73 DE1004 der IFTSTA mit der die Antwort auf die Bestellung der Konfiguration übermittelt wurde
1992    fn evaluate_562(&self, _ctx: &EvaluationContext) -> ConditionResult {
1993        // Hinweis: Wert aus BGM+Z73 DE1004 der IFTSTA — informational note, always applies
1994        ConditionResult::True
1995    }
1996
1997    /// [563] Hinweis: Vorgangsnummer aus CNI DE1490 der IFTSTA mit BGM+Z73 mit der die Antwort auf die Bestellung der Konfiguration übermittelt wurde
1998    fn evaluate_563(&self, _ctx: &EvaluationContext) -> ConditionResult {
1999        // 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
2000        ConditionResult::True
2001    }
2002
2003    /// [564] Hinweis: Für den Empfang der Werte nach Typ 2 aus dem SMGW.
2004    fn evaluate_564(&self, _ctx: &EvaluationContext) -> ConditionResult {
2005        // Hinweis: Für den Empfang der Werte nach Typ 2 aus dem SMGW — informational note, always applies
2006        ConditionResult::True
2007    }
2008
2009    /// [566] Hinweis: Verwendung der ID der Technischen Ressource
2010    fn evaluate_566(&self, _ctx: &EvaluationContext) -> ConditionResult {
2011        // Hinweis: Verwendung der ID der Technischen Ressource — informational note, always applies
2012        ConditionResult::True
2013    }
2014
2015    /// [567] Hinweis: Es darf nur eine Information im DE3148 übermittelt werden
2016    fn evaluate_567(&self, _ctx: &EvaluationContext) -> ConditionResult {
2017        // Hinweis: Es darf nur eine Information im DE3148 übermittelt werden — informational note, always applies
2018        ConditionResult::True
2019    }
2020
2021    /// [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.
2022    fn evaluate_568(&self, _ctx: &EvaluationContext) -> ConditionResult {
2023        // 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
2024        ConditionResult::True
2025    }
2026
2027    /// [569] Hinweis: MaBiS-Zählpunkt der LF-SZR
2028    fn evaluate_569(&self, _ctx: &EvaluationContext) -> ConditionResult {
2029        // Hinweis: MaBiS-Zählpunkt der LF-SZR — informational note, always applies
2030        ConditionResult::True
2031    }
2032
2033    /// [570] Hinweis: zur Angabe von Kontaktdaten des Kunden des Lieferanten um die Änderung an der Technik zu vereinfachen.
2034    fn evaluate_570(&self, _ctx: &EvaluationContext) -> ConditionResult {
2035        // Hinweis: zur Angabe von Kontaktdaten des Kunden des Lieferanten um die Änderung an der Technik zu vereinfachen — informational note, always applies
2036        ConditionResult::True
2037    }
2038
2039    /// [571] Hinweis: MSB der Marktlokation, an den die Werte der weiteren Energieflussrichtung der Messlokation zu übermitteln sind.
2040    fn evaluate_571(&self, _ctx: &EvaluationContext) -> ConditionResult {
2041        // Hinweis: MSB der Marktlokation, an den die Werte der weiteren Energieflussrichtung der Messlokation zu übermitteln sind — informational note, always applies
2042        ConditionResult::True
2043    }
2044
2045    /// [572] Hinweis: MSB der Marktlokation der Kundenanlage, in der die betroffene Lokation integriert wird.
2046    fn evaluate_572(&self, _ctx: &EvaluationContext) -> ConditionResult {
2047        // Hinweis: MSB der Marktlokation der Kundenanlage, in der die betroffene Lokation integriert wird — informational note, always applies
2048        ConditionResult::True
2049    }
2050
2051    /// [573] Hinweis: Es ist eine URI IPv4 für die Bereitstellung der Werte anzugeben.
2052    fn evaluate_573(&self, _ctx: &EvaluationContext) -> ConditionResult {
2053        // Hinweis: Es ist eine URI IPv4 für die Bereitstellung der Werte anzugeben — informational note, always applies
2054        ConditionResult::True
2055    }
2056
2057    /// [574] Hinweis: Es ist eine URI IPv6 für die Bereitstellung der Werte anzugeben.
2058    fn evaluate_574(&self, _ctx: &EvaluationContext) -> ConditionResult {
2059        // Hinweis: Es ist eine URI IPv6 für die Bereitstellung der Werte anzugeben.
2060        ConditionResult::True
2061    }
2062
2063    /// [575] Hinweis: Wenn der gewünschte Änderungszeitpunkt ein fixer Zeitpunkt ist.
2064    fn evaluate_575(&self, _ctx: &EvaluationContext) -> ConditionResult {
2065        // Hinweis: Wenn der gewünschte Änderungszeitpunkt ein fixer Zeitpunkt ist.
2066        ConditionResult::True
2067    }
2068
2069    /// [576] Hinweis: Wenn der gewünschte Änderungszeitpunkt ein nächst möglicher Termin zum oder nach dem angegebenen Zeitpunkt ist.
2070    fn evaluate_576(&self, _ctx: &EvaluationContext) -> ConditionResult {
2071        // Hinweis: Wenn der gewünschte Änderungszeitpunkt ein nächst möglicher Termin zum oder nach dem angegebenen Zeitpunkt ist.
2072        ConditionResult::True
2073    }
2074
2075    /// [903] Format: Möglicher Wert: 1
2076    fn evaluate_903(&self, _ctx: &EvaluationContext) -> ConditionResult {
2077        ConditionResult::True
2078    }
2079
2080    /// [906] Format: max. 3 Nachkommastellen
2081    fn evaluate_906(&self, ctx: &EvaluationContext) -> ConditionResult {
2082        ctx.format_check("QTY", 0, 1, |val| validate_max_decimal_places(val, 3))
2083    }
2084
2085    /// [911] Format: Mögliche Werte: 1 bis n, je Nachricht oder Segmentgruppe bei 1 beginnend und fortlaufend aufsteigend
2086    fn evaluate_911(&self, _ctx: &EvaluationContext) -> ConditionResult {
2087        // Hinweis: Mögliche Werte: 1 bis n, je Nachricht oder Segmentgruppe bei 1 beginnend und fortlaufend aufsteigend
2088        // This is a cardinality/sequencing annotation — informational, always applies
2089        ConditionResult::True
2090    }
2091
2092    /// [914] Format: Möglicher Wert: &gt;0
2093    fn evaluate_914(&self, ctx: &EvaluationContext) -> ConditionResult {
2094        ctx.format_check("QTY", 0, 1, |val| validate_numeric(val, ">", 0.0))
2095    }
2096
2097    /// [922] Format: TR-ID
2098    // 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)
2099    fn evaluate_922(&self, ctx: &EvaluationContext) -> ConditionResult {
2100        // Format: TR-ID — Transaktionsreferenz-ID, max 35 alphanumeric characters
2101        // In ORDERS, TR-ID typically appears in BGM element 1 (C106 document identifier)
2102        let segs = ctx.find_segments("BGM");
2103        match segs
2104            .first()
2105            .and_then(|s| s.elements.get(1))
2106            .and_then(|e| e.first())
2107        {
2108            Some(val) if !val.is_empty() => validate_max_length(val, 35),
2109            Some(_) => ConditionResult::False,
2110            None => ConditionResult::False, // segment absent → condition not applicable
2111        }
2112    }
2113
2114    /// [930] Format: max. 2 Nachkommastellen
2115    fn evaluate_930(&self, ctx: &EvaluationContext) -> ConditionResult {
2116        ctx.format_check("QTY", 0, 1, |val| validate_max_decimal_places(val, 2))
2117    }
2118
2119    /// [931] Format: ZZZ = +00
2120    fn evaluate_931(&self, ctx: &EvaluationContext) -> ConditionResult {
2121        ctx.format_check("DTM", 0, 1, validate_timezone_utc)
2122    }
2123
2124    /// [932] Format: HHMM = 2200
2125    // 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)
2126    fn evaluate_932(&self, ctx: &EvaluationContext) -> ConditionResult {
2127        ctx.format_check_qualified("DTM", 0, "163", 0, 1, |val| {
2128            validate_hhmm_equals(val, "2200")
2129        })
2130    }
2131
2132    /// [933] Format: HHMM = 2300
2133    fn evaluate_933(&self, ctx: &EvaluationContext) -> ConditionResult {
2134        ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "2300"))
2135    }
2136
2137    /// [934] Format: HHMM = 0400
2138    fn evaluate_934(&self, ctx: &EvaluationContext) -> ConditionResult {
2139        ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "0400"))
2140    }
2141
2142    /// [935] Format: HHMM = 0500
2143    fn evaluate_935(&self, ctx: &EvaluationContext) -> ConditionResult {
2144        ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "0500"))
2145    }
2146
2147    /// [939] Format: Die Zeichenkette muss die Zeichen @ und . enthalten
2148    fn evaluate_939(&self, ctx: &EvaluationContext) -> ConditionResult {
2149        ctx.format_check("COM", 0, 0, validate_email)
2150    }
2151
2152    /// [940] Format: Die Zeichenkette muss mit dem Zeichen + beginnen und danach dürfen nur noch Ziffern folgen
2153    fn evaluate_940(&self, ctx: &EvaluationContext) -> ConditionResult {
2154        ctx.format_check("COM", 0, 0, validate_phone)
2155    }
2156
2157    /// [950] Format: Marktlokations-ID
2158    fn evaluate_950(&self, ctx: &EvaluationContext) -> ConditionResult {
2159        ctx.format_check_qualified("LOC", 0, "Z16", 1, 0, validate_malo_id)
2160    }
2161
2162    /// [951] Format: Zählpunktbezeichnung
2163    fn evaluate_951(&self, ctx: &EvaluationContext) -> ConditionResult {
2164        ctx.format_check_qualified("LOC", 0, "Z17", 1, 0, validate_zahlpunkt)
2165    }
2166
2167    /// [955] Format: Möglicher Wert: &lt;100
2168    // 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)
2169    fn evaluate_955(&self, ctx: &EvaluationContext) -> ConditionResult {
2170        ctx.format_check("QTY", 0, 1, |val| validate_numeric(val, "<", 100.0))
2171    }
2172
2173    /// [960] Format: Netzlokations-ID
2174    // HAND-EDITED: a Netzlokations-ID is "E" + ten alphanumerics (`E1688117482`),
2175    // not MaLo-shaped; `validate_malo_id` rejected every real one (#173).
2176    fn evaluate_960(&self, ctx: &EvaluationContext) -> ConditionResult {
2177        ctx.format_check_qualified("LOC", 0, "Z18", 1, 0, validate_nelo_id)
2178    }
2179
2180    /// [961] Format: SR-ID
2181    fn evaluate_961(&self, ctx: &EvaluationContext) -> ConditionResult {
2182        ctx.format_check_qualified("LOC", 0, "Z19", 1, 0, validate_malo_id)
2183    }
2184
2185    /// [962] Format: max. 6 Vorkommastellen
2186    // 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)
2187    fn evaluate_962(&self, ctx: &EvaluationContext) -> ConditionResult {
2188        ctx.format_check("QTY", 0, 1, |val| validate_max_integer_digits(val, 6))
2189    }
2190
2191    /// [2002] Ist mindestens zwei Mal anzugeben
2192    // 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)
2193    fn evaluate_2002(&self, ctx: &EvaluationContext) -> ConditionResult {
2194        // "Ist mindestens zwei Mal anzugeben" — SG29 must appear at least twice.
2195        // DTM+203 (Ausführungsdatum) occurs exactly once per SG29 instance,
2196        // so counting DTM+203 segments gives the SG29 repetition count.
2197        let count = ctx.find_segments_with_qualifier("DTM", 0, "203").len();
2198        ConditionResult::from(count >= 2)
2199    }
2200
2201    /// [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...
2202    fn evaluate_2003(&self, _ctx: &EvaluationContext) -> ConditionResult {
2203        // Hinweis: SG29 repetition cardinality rule — informational annotation documenting that
2204        // SG29 must repeat once per Messlokation associated with the Marktlokation from DTM+203,
2205        // and all Messprodukte for each Messlokation (including Tranchen) must be listed.
2206        // This is a structural cardinality guidance note, always applies.
2207        ConditionResult::True
2208    }
2209
2210    /// [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.
2211    fn evaluate_2004(&self, _ctx: &EvaluationContext) -> ConditionResult {
2212        // Hinweis: Die SG29 ist so oft zu wiederholen, dass alle Geräte der betroffenen Geräteart
2213        // die im Rahmen des Gerätewechsels aufgrund MSB-Wechsel getauscht werden sollen, genannt sind.
2214        // Informational cardinality note — always applies.
2215        ConditionResult::True
2216    }
2217
2218    /// [2005] Pro SG29 LIN ist die SG34 RFF+Z09 (Gerätenummer) genau einmal anzugeben
2219    // 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)
2220    fn evaluate_2005(&self, ctx: &EvaluationContext) -> ConditionResult {
2221        {
2222            let rffs = ctx.find_segments_with_qualifier("RFF", 0, "Z09");
2223            ConditionResult::from(rffs.len() == 1)
2224        }
2225    }
2226
2227    /// [2006] Pro SG29 LIN ist die SG34 RFF+Z09 (Gerätenummer) bis zu dreimal anzugeben
2228    // 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)
2229    fn evaluate_2006(&self, ctx: &EvaluationContext) -> ConditionResult {
2230        {
2231            let rffs = ctx.find_segments_with_qualifier("RFF", 0, "Z09");
2232            ConditionResult::from(rffs.len() <= 3)
2233        }
2234    }
2235
2236    /// [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...
2237    fn evaluate_2007(&self, _ctx: &EvaluationContext) -> ConditionResult {
2238        // Hinweis: Die SG29 ist so oft zu wiederholen, wie ab dem DTM+203 (Ausführungsdatum)
2239        // Messlokationen zu der in der SG2 genannten Netzlokation vorhanden sind und für jede
2240        // dieser Messlokationen müssen alle Messprodukte genannt sein, die ab dem DTM+203
2241        // (Ausführungsdatum) in der SG2 genannten Netzlokation vorhanden sind.
2242        // Informational cardinality note — always applies.
2243        ConditionResult::True
2244    }
2245
2246    /// [2044] Pro SG29 LIN ist die SG29 PIA genau einmal anzugeben
2247    // 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)
2248    fn evaluate_2044(&self, ctx: &EvaluationContext) -> ConditionResult {
2249        {
2250            let pias = ctx.find_segments("PIA");
2251            ConditionResult::from(pias.len() == 1)
2252        }
2253    }
2254
2255    /// [2050] Pro Nachricht ist die SG29 genau einmal anzugeben
2256    // 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)
2257    fn evaluate_2050(&self, ctx: &EvaluationContext) -> ConditionResult {
2258        {
2259            let lins = ctx.find_segments("LIN");
2260            ConditionResult::from(lins.len() == 1)
2261        }
2262    }
2263
2264    /// [2060] Pro Nachricht ist die SG29 LIN+Z64 (Erforderliches Produkt Schaltzeitdefinitionen) maximal einmal anzugeben
2265    fn evaluate_2060(&self, ctx: &EvaluationContext) -> ConditionResult {
2266        {
2267            let lins = ctx.find_segments("LIN");
2268            let count = lins
2269                .iter()
2270                .filter(|s| {
2271                    s.elements
2272                        .get(1)
2273                        .and_then(|e| e.first())
2274                        .is_some_and(|v| v == "Z64")
2275                })
2276                .count();
2277            ConditionResult::from(count <= 1)
2278        }
2279    }
2280
2281    /// [2061] Pro Nachricht ist die SG29 LIN++Z65 (Erforderliches Produkt Leistungskurvendefinitionen) maximal einmal anzugeben
2282    fn evaluate_2061(&self, ctx: &EvaluationContext) -> ConditionResult {
2283        {
2284            let lins = ctx.find_segments("LIN");
2285            let count = lins
2286                .iter()
2287                .filter(|s| {
2288                    s.elements
2289                        .get(1)
2290                        .and_then(|e| e.first())
2291                        .is_some_and(|v| v == "Z65")
2292                })
2293                .count();
2294            ConditionResult::from(count <= 1)
2295        }
2296    }
2297
2298    /// [2062] Pro Nachricht ist die SG29 LIN++Z66 (Erforderliches Produkt Ad-hoc-Steuerkanal) maximal einmal anzugeben
2299    // 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)
2300    fn evaluate_2062(&self, ctx: &EvaluationContext) -> ConditionResult {
2301        let count = ctx
2302            .find_segments("LIN")
2303            .iter()
2304            .filter(|s| {
2305                s.elements
2306                    .get(1)
2307                    .and_then(|e| e.first())
2308                    .is_some_and(|v| v == "Z66")
2309            })
2310            .count();
2311        ConditionResult::from(count <= 1)
2312    }
2313
2314    /// [2063] Pro Nachricht ist die SG29 LIN++Z67 (Erforderliches Messprodukt für Werte nach Typ 2 aus Backend) maximal einmal anzugeben
2315    // 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)
2316    fn evaluate_2063(&self, ctx: &EvaluationContext) -> ConditionResult {
2317        let count = ctx
2318            .find_segments("LIN")
2319            .iter()
2320            .filter(|s| {
2321                s.elements
2322                    .get(1)
2323                    .and_then(|e| e.first())
2324                    .is_some_and(|v| v == "Z67")
2325            })
2326            .count();
2327        ConditionResult::from(count <= 1)
2328    }
2329
2330    /// [2064] Pro Nachricht ist die SG29 LIN++Z68 (Erforderliches Produkt Konfigurationserlaubnis für Werte nach Typ 2 aus SMGW) maximal einmal anzugeben
2331    // 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)
2332    fn evaluate_2064(&self, ctx: &EvaluationContext) -> ConditionResult {
2333        let count = ctx
2334            .find_segments("LIN")
2335            .iter()
2336            .filter(|s| {
2337                s.elements
2338                    .get(1)
2339                    .and_then(|e| e.first())
2340                    .is_some_and(|v| v == "Z68")
2341            })
2342            .count();
2343        ConditionResult::from(count <= 1)
2344    }
2345
2346    /// [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...
2347    fn evaluate_2066(&self, _ctx: &EvaluationContext) -> ConditionResult {
2348        // Hinweis: Die SG3 RFF+Z37 ist so oft zu wiederholen, bis alle IDs der Technischen
2349        // Ressourcen angegeben sind, die der Steuerbaren Ressource in LOC+172 DE3225 (Meldepunkt)
2350        // mit diesem Vorgang zugeordnet werden sollen.
2351        // Informational cardinality note — always applies.
2352        ConditionResult::True
2353    }
2354
2355    /// [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.
2356    fn evaluate_2088(&self, _ctx: &EvaluationContext) -> ConditionResult {
2357        // Hinweis: Die SG29 ist so oft zu wiederholen, dass alle Messprodukte ab dem DTM+203
2358        // (Ausführungsdatum) zu der in der SG2 genannten Netzlokation genannt sind.
2359        // Informational cardinality note — always applies.
2360        ConditionResult::True
2361    }
2362
2363    /// [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.
2364    fn evaluate_2089(&self, _ctx: &EvaluationContext) -> ConditionResult {
2365        // Hinweis: Die SG29 ist so oft zu wiederholen, dass alle Messprodukte ab dem DTM+203
2366        // (Ausführungsdatum) zu der in der SG2 genannten Marktlokation genannt sind.
2367        // Informational cardinality note about SG29 repetition count — always applies.
2368        ConditionResult::True
2369    }
2370
2371    /// [2090] Für 33-stellige ID im SG2 LOC+172 (Meldepunkt) DE3225 mindestens einmal anzugeben
2372    fn evaluate_2090(&self, ctx: &EvaluationContext) -> ConditionResult {
2373        let locs = ctx.find_segments_with_qualifier("LOC", 0, "172");
2374        ConditionResult::from(locs.iter().any(|s| {
2375            s.elements
2376                .get(1)
2377                .and_then(|e| e.first())
2378                .is_some_and(|v| v.len() == 33)
2379        }))
2380    }
2381
2382    /// [2092] Pro Nachricht ist die SG29 maximal einmal anzugeben
2383    // 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)
2384    fn evaluate_2092(&self, ctx: &EvaluationContext) -> ConditionResult {
2385        ConditionResult::from(ctx.find_segments("LIN").len() <= 1)
2386    }
2387
2388    /// [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.
2389    fn evaluate_2094(&self, _ctx: &EvaluationContext) -> ConditionResult {
2390        // Hinweis: Pro Nachricht ist die SG29 LIN (Positionsdaten) so oft anzugeben, wie
2391        // Positionen aus dem Angebot (referenziert in SG1 RFF+AAG DE1154) bestellt werden sollen.
2392        // Informational cardinality note — the required repetition count depends on an external
2393        // offer document that cannot be inspected from within this EDIFACT message.
2394        ConditionResult::True
2395    }
2396
2397    /// [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...
2398    fn evaluate_2095(&self, _ctx: &EvaluationContext) -> ConditionResult {
2399        // Hinweis: Diese SG29 ist so oft zu wiederholen, dass alle Produkte zur Lokation
2400        // ab dem DTM+203 (Ausführungsdatum) genannt sind, deren Kombination gemäß
2401        // Codeliste der Konfigurationen Kapitel 7 möglich sind.
2402        // Informational cardinality note — valid combinations are defined by an external
2403        // code list (Kapitel 7) and cannot be validated from EDIFACT content alone.
2404        ConditionResult::True
2405    }
2406
2407    /// [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.
2408    fn evaluate_2096(&self, _ctx: &EvaluationContext) -> ConditionResult {
2409        // Hinweis: Die SG3 Referenz auf die ID der Tranche ist so oft zu wiederholen, wie
2410        // ab dem DTM+203 (Ausführungsdatum) Tranchen zu der in der SG2 genannten
2411        // Marktlokation vorhanden sind.
2412        // Informational cardinality note — the number of Tranchen for a Marktlokation is
2413        // business context that cannot be determined from the EDIFACT message alone.
2414        ConditionResult::True
2415    }
2416
2417    /// [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.
2418    fn evaluate_2097(&self, _ctx: &EvaluationContext) -> ConditionResult {
2419        // Hinweis: Die SG29 ist so oft zu wiederholen, dass für alle in SG3 RFF+Z20
2420        // (Referenz auf ID der Tranche) genannten Tranchen mindestens eine SG29 vorhanden ist.
2421        // Informational completeness note — each Tranche referenced in SG3 must have
2422        // at least one corresponding SG29. Documents structural pairing requirements.
2423        ConditionResult::True
2424    }
2425
2426    /// [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.
2427    // 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)
2428    fn evaluate_2098(&self, ctx: &EvaluationContext) -> ConditionResult {
2429        // SG2 Lieferant an der Lokation must repeat once per SG3 tranche reference.
2430        // Count SG2 group instances (NAD as entry segment) and SG3 RFF tranche references.
2431        // Both counts must be equal and non-zero for the condition to be satisfied.
2432        let sg2_count = ctx.count_in_group("NAD", &["SG29", "SG2"]);
2433        let sg3_count = ctx.count_in_group("RFF", &["SG29", "SG3"]);
2434        if sg2_count == 0 || sg3_count == 0 {
2435            return ConditionResult::Unknown;
2436        }
2437        ConditionResult::from(sg2_count == sg3_count)
2438    }
2439
2440    /// [2099] Die SG2 Lieferant an der Lokation ist genau einmal anzugeben.
2441    // 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)
2442    fn evaluate_2099(&self, ctx: &EvaluationContext) -> ConditionResult {
2443        // SG2 Lieferant an der Lokation must appear exactly once.
2444        // Count NAD segments (entry segment of SG2) within the SG29 SG2 group path.
2445        let count = ctx.count_in_group("NAD", &["SG29", "SG2"]);
2446        if count == 0 {
2447            return ConditionResult::Unknown;
2448        }
2449        ConditionResult::from(count == 1)
2450    }
2451}