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