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