Skip to main content

automapper_validation/generated/fv2510/
orders_conditions_fv2510.rs

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