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