automapper_validation/generated/fv2504/utilmd_strom_conditions_fv2504.rs
1// <auto-generated>
2// Generated by automapper-generator generate-conditions
3// AHB: xml-migs-and-ahbs/FV2504/UTILMD_AHB_Strom_2_1_Fehlerkorrektur_20250623.xml
4// Generated: 2026-03-12T10:15:42Z
5// </auto-generated>
6
7#[allow(unused_imports)]
8use crate::eval::format_validators::*;
9use crate::eval::{ConditionEvaluator, ConditionResult, EvaluationContext};
10
11/// Generated condition evaluator for UTILMD_Strom FV2504.
12pub struct UtilmdStromConditionEvaluatorFV2504 {
13 // External condition IDs that require runtime context.
14 external_conditions: std::collections::HashSet<u32>,
15}
16
17impl Default for UtilmdStromConditionEvaluatorFV2504 {
18 fn default() -> Self {
19 let mut external_conditions = std::collections::HashSet::new();
20 external_conditions.insert(1);
21 external_conditions.insert(4);
22 external_conditions.insert(5);
23 external_conditions.insert(6);
24 external_conditions.insert(8);
25 external_conditions.insert(9);
26 external_conditions.insert(10);
27 external_conditions.insert(14);
28 external_conditions.insert(31);
29 external_conditions.insert(33);
30 external_conditions.insert(36);
31 external_conditions.insert(37);
32 external_conditions.insert(38);
33 external_conditions.insert(39);
34 external_conditions.insert(40);
35 external_conditions.insert(75);
36 external_conditions.insert(98);
37 external_conditions.insert(99);
38 external_conditions.insert(151);
39 external_conditions.insert(233);
40 external_conditions.insert(241);
41 external_conditions.insert(251);
42 external_conditions.insert(292);
43 external_conditions.insert(314);
44 external_conditions.insert(315);
45 external_conditions.insert(323);
46 external_conditions.insert(412);
47 external_conditions.insert(425);
48 external_conditions.insert(426);
49 external_conditions.insert(427);
50 external_conditions.insert(428);
51 external_conditions.insert(429);
52 external_conditions.insert(433);
53 external_conditions.insert(435);
54 external_conditions.insert(453);
55 external_conditions.insert(459);
56 external_conditions.insert(460);
57 external_conditions.insert(706);
58 external_conditions.insert(717);
59 external_conditions.insert(2011);
60 Self {
61 external_conditions,
62 }
63 }
64}
65
66impl ConditionEvaluator for UtilmdStromConditionEvaluatorFV2504 {
67 fn message_type(&self) -> &str {
68 "UTILMD_Strom"
69 }
70
71 fn format_version(&self) -> &str {
72 "FV2504"
73 }
74
75 fn evaluate(&self, condition: u32, ctx: &EvaluationContext) -> ConditionResult {
76 match condition {
77 1 => self.evaluate_1(ctx),
78 4 => self.evaluate_4(ctx),
79 5 => self.evaluate_5(ctx),
80 6 => self.evaluate_6(ctx),
81 7 => self.evaluate_7(ctx),
82 8 => self.evaluate_8(ctx),
83 9 => self.evaluate_9(ctx),
84 10 => self.evaluate_10(ctx),
85 11 => self.evaluate_11(ctx),
86 12 => self.evaluate_12(ctx),
87 13 => self.evaluate_13(ctx),
88 14 => self.evaluate_14(ctx),
89 15 => self.evaluate_15(ctx),
90 16 => self.evaluate_16(ctx),
91 17 => self.evaluate_17(ctx),
92 18 => self.evaluate_18(ctx),
93 19 => self.evaluate_19(ctx),
94 20 => self.evaluate_20(ctx),
95 21 => self.evaluate_21(ctx),
96 22 => self.evaluate_22(ctx),
97 23 => self.evaluate_23(ctx),
98 24 => self.evaluate_24(ctx),
99 25 => self.evaluate_25(ctx),
100 27 => self.evaluate_27(ctx),
101 30 => self.evaluate_30(ctx),
102 31 => self.evaluate_31(ctx),
103 32 => self.evaluate_32(ctx),
104 33 => self.evaluate_33(ctx),
105 34 => self.evaluate_34(ctx),
106 35 => self.evaluate_35(ctx),
107 36 => self.evaluate_36(ctx),
108 37 => self.evaluate_37(ctx),
109 38 => self.evaluate_38(ctx),
110 39 => self.evaluate_39(ctx),
111 40 => self.evaluate_40(ctx),
112 41 => self.evaluate_41(ctx),
113 42 => self.evaluate_42(ctx),
114 43 => self.evaluate_43(ctx),
115 44 => self.evaluate_44(ctx),
116 45 => self.evaluate_45(ctx),
117 46 => self.evaluate_46(ctx),
118 47 => self.evaluate_47(ctx),
119 48 => self.evaluate_48(ctx),
120 49 => self.evaluate_49(ctx),
121 50 => self.evaluate_50(ctx),
122 51 => self.evaluate_51(ctx),
123 52 => self.evaluate_52(ctx),
124 53 => self.evaluate_53(ctx),
125 54 => self.evaluate_54(ctx),
126 55 => self.evaluate_55(ctx),
127 56 => self.evaluate_56(ctx),
128 57 => self.evaluate_57(ctx),
129 58 => self.evaluate_58(ctx),
130 60 => self.evaluate_60(ctx),
131 61 => self.evaluate_61(ctx),
132 62 => self.evaluate_62(ctx),
133 63 => self.evaluate_63(ctx),
134 64 => self.evaluate_64(ctx),
135 65 => self.evaluate_65(ctx),
136 66 => self.evaluate_66(ctx),
137 67 => self.evaluate_67(ctx),
138 68 => self.evaluate_68(ctx),
139 69 => self.evaluate_69(ctx),
140 70 => self.evaluate_70(ctx),
141 71 => self.evaluate_71(ctx),
142 72 => self.evaluate_72(ctx),
143 73 => self.evaluate_73(ctx),
144 74 => self.evaluate_74(ctx),
145 75 => self.evaluate_75(ctx),
146 76 => self.evaluate_76(ctx),
147 77 => self.evaluate_77(ctx),
148 78 => self.evaluate_78(ctx),
149 83 => self.evaluate_83(ctx),
150 84 => self.evaluate_84(ctx),
151 85 => self.evaluate_85(ctx),
152 86 => self.evaluate_86(ctx),
153 87 => self.evaluate_87(ctx),
154 88 => self.evaluate_88(ctx),
155 89 => self.evaluate_89(ctx),
156 90 => self.evaluate_90(ctx),
157 91 => self.evaluate_91(ctx),
158 92 => self.evaluate_92(ctx),
159 93 => self.evaluate_93(ctx),
160 94 => self.evaluate_94(ctx),
161 95 => self.evaluate_95(ctx),
162 96 => self.evaluate_96(ctx),
163 97 => self.evaluate_97(ctx),
164 98 => self.evaluate_98(ctx),
165 99 => self.evaluate_99(ctx),
166 100 => self.evaluate_100(ctx),
167 101 => self.evaluate_101(ctx),
168 102 => self.evaluate_102(ctx),
169 103 => self.evaluate_103(ctx),
170 104 => self.evaluate_104(ctx),
171 105 => self.evaluate_105(ctx),
172 106 => self.evaluate_106(ctx),
173 107 => self.evaluate_107(ctx),
174 108 => self.evaluate_108(ctx),
175 110 => self.evaluate_110(ctx),
176 111 => self.evaluate_111(ctx),
177 112 => self.evaluate_112(ctx),
178 113 => self.evaluate_113(ctx),
179 114 => self.evaluate_114(ctx),
180 115 => self.evaluate_115(ctx),
181 116 => self.evaluate_116(ctx),
182 117 => self.evaluate_117(ctx),
183 118 => self.evaluate_118(ctx),
184 119 => self.evaluate_119(ctx),
185 120 => self.evaluate_120(ctx),
186 121 => self.evaluate_121(ctx),
187 122 => self.evaluate_122(ctx),
188 123 => self.evaluate_123(ctx),
189 124 => self.evaluate_124(ctx),
190 125 => self.evaluate_125(ctx),
191 126 => self.evaluate_126(ctx),
192 127 => self.evaluate_127(ctx),
193 128 => self.evaluate_128(ctx),
194 129 => self.evaluate_129(ctx),
195 130 => self.evaluate_130(ctx),
196 131 => self.evaluate_131(ctx),
197 132 => self.evaluate_132(ctx),
198 133 => self.evaluate_133(ctx),
199 134 => self.evaluate_134(ctx),
200 135 => self.evaluate_135(ctx),
201 136 => self.evaluate_136(ctx),
202 137 => self.evaluate_137(ctx),
203 138 => self.evaluate_138(ctx),
204 139 => self.evaluate_139(ctx),
205 140 => self.evaluate_140(ctx),
206 141 => self.evaluate_141(ctx),
207 142 => self.evaluate_142(ctx),
208 143 => self.evaluate_143(ctx),
209 144 => self.evaluate_144(ctx),
210 145 => self.evaluate_145(ctx),
211 146 => self.evaluate_146(ctx),
212 147 => self.evaluate_147(ctx),
213 148 => self.evaluate_148(ctx),
214 149 => self.evaluate_149(ctx),
215 150 => self.evaluate_150(ctx),
216 151 => self.evaluate_151(ctx),
217 152 => self.evaluate_152(ctx),
218 153 => self.evaluate_153(ctx),
219 156 => self.evaluate_156(ctx),
220 161 => self.evaluate_161(ctx),
221 162 => self.evaluate_162(ctx),
222 163 => self.evaluate_163(ctx),
223 164 => self.evaluate_164(ctx),
224 165 => self.evaluate_165(ctx),
225 166 => self.evaluate_166(ctx),
226 167 => self.evaluate_167(ctx),
227 170 => self.evaluate_170(ctx),
228 172 => self.evaluate_172(ctx),
229 173 => self.evaluate_173(ctx),
230 174 => self.evaluate_174(ctx),
231 175 => self.evaluate_175(ctx),
232 176 => self.evaluate_176(ctx),
233 177 => self.evaluate_177(ctx),
234 178 => self.evaluate_178(ctx),
235 179 => self.evaluate_179(ctx),
236 180 => self.evaluate_180(ctx),
237 184 => self.evaluate_184(ctx),
238 190 => self.evaluate_190(ctx),
239 191 => self.evaluate_191(ctx),
240 192 => self.evaluate_192(ctx),
241 193 => self.evaluate_193(ctx),
242 194 => self.evaluate_194(ctx),
243 195 => self.evaluate_195(ctx),
244 196 => self.evaluate_196(ctx),
245 197 => self.evaluate_197(ctx),
246 198 => self.evaluate_198(ctx),
247 199 => self.evaluate_199(ctx),
248 201 => self.evaluate_201(ctx),
249 202 => self.evaluate_202(ctx),
250 203 => self.evaluate_203(ctx),
251 204 => self.evaluate_204(ctx),
252 205 => self.evaluate_205(ctx),
253 206 => self.evaluate_206(ctx),
254 209 => self.evaluate_209(ctx),
255 210 => self.evaluate_210(ctx),
256 212 => self.evaluate_212(ctx),
257 213 => self.evaluate_213(ctx),
258 215 => self.evaluate_215(ctx),
259 216 => self.evaluate_216(ctx),
260 217 => self.evaluate_217(ctx),
261 219 => self.evaluate_219(ctx),
262 220 => self.evaluate_220(ctx),
263 221 => self.evaluate_221(ctx),
264 223 => self.evaluate_223(ctx),
265 224 => self.evaluate_224(ctx),
266 227 => self.evaluate_227(ctx),
267 229 => self.evaluate_229(ctx),
268 232 => self.evaluate_232(ctx),
269 233 => self.evaluate_233(ctx),
270 234 => self.evaluate_234(ctx),
271 237 => self.evaluate_237(ctx),
272 238 => self.evaluate_238(ctx),
273 239 => self.evaluate_239(ctx),
274 240 => self.evaluate_240(ctx),
275 241 => self.evaluate_241(ctx),
276 243 => self.evaluate_243(ctx),
277 244 => self.evaluate_244(ctx),
278 248 => self.evaluate_248(ctx),
279 249 => self.evaluate_249(ctx),
280 251 => self.evaluate_251(ctx),
281 252 => self.evaluate_252(ctx),
282 254 => self.evaluate_254(ctx),
283 255 => self.evaluate_255(ctx),
284 256 => self.evaluate_256(ctx),
285 257 => self.evaluate_257(ctx),
286 259 => self.evaluate_259(ctx),
287 261 => self.evaluate_261(ctx),
288 262 => self.evaluate_262(ctx),
289 265 => self.evaluate_265(ctx),
290 266 => self.evaluate_266(ctx),
291 267 => self.evaluate_267(ctx),
292 268 => self.evaluate_268(ctx),
293 269 => self.evaluate_269(ctx),
294 270 => self.evaluate_270(ctx),
295 273 => self.evaluate_273(ctx),
296 279 => self.evaluate_279(ctx),
297 280 => self.evaluate_280(ctx),
298 282 => self.evaluate_282(ctx),
299 284 => self.evaluate_284(ctx),
300 285 => self.evaluate_285(ctx),
301 286 => self.evaluate_286(ctx),
302 287 => self.evaluate_287(ctx),
303 288 => self.evaluate_288(ctx),
304 291 => self.evaluate_291(ctx),
305 292 => self.evaluate_292(ctx),
306 293 => self.evaluate_293(ctx),
307 294 => self.evaluate_294(ctx),
308 295 => self.evaluate_295(ctx),
309 296 => self.evaluate_296(ctx),
310 297 => self.evaluate_297(ctx),
311 298 => self.evaluate_298(ctx),
312 299 => self.evaluate_299(ctx),
313 300 => self.evaluate_300(ctx),
314 301 => self.evaluate_301(ctx),
315 302 => self.evaluate_302(ctx),
316 303 => self.evaluate_303(ctx),
317 304 => self.evaluate_304(ctx),
318 305 => self.evaluate_305(ctx),
319 306 => self.evaluate_306(ctx),
320 307 => self.evaluate_307(ctx),
321 309 => self.evaluate_309(ctx),
322 314 => self.evaluate_314(ctx),
323 315 => self.evaluate_315(ctx),
324 316 => self.evaluate_316(ctx),
325 317 => self.evaluate_317(ctx),
326 318 => self.evaluate_318(ctx),
327 321 => self.evaluate_321(ctx),
328 322 => self.evaluate_322(ctx),
329 323 => self.evaluate_323(ctx),
330 327 => self.evaluate_327(ctx),
331 329 => self.evaluate_329(ctx),
332 331 => self.evaluate_331(ctx),
333 332 => self.evaluate_332(ctx),
334 333 => self.evaluate_333(ctx),
335 334 => self.evaluate_334(ctx),
336 335 => self.evaluate_335(ctx),
337 336 => self.evaluate_336(ctx),
338 337 => self.evaluate_337(ctx),
339 338 => self.evaluate_338(ctx),
340 339 => self.evaluate_339(ctx),
341 340 => self.evaluate_340(ctx),
342 341 => self.evaluate_341(ctx),
343 342 => self.evaluate_342(ctx),
344 344 => self.evaluate_344(ctx),
345 345 => self.evaluate_345(ctx),
346 346 => self.evaluate_346(ctx),
347 347 => self.evaluate_347(ctx),
348 348 => self.evaluate_348(ctx),
349 349 => self.evaluate_349(ctx),
350 350 => self.evaluate_350(ctx),
351 351 => self.evaluate_351(ctx),
352 352 => self.evaluate_352(ctx),
353 355 => self.evaluate_355(ctx),
354 356 => self.evaluate_356(ctx),
355 357 => self.evaluate_357(ctx),
356 358 => self.evaluate_358(ctx),
357 359 => self.evaluate_359(ctx),
358 360 => self.evaluate_360(ctx),
359 363 => self.evaluate_363(ctx),
360 365 => self.evaluate_365(ctx),
361 366 => self.evaluate_366(ctx),
362 367 => self.evaluate_367(ctx),
363 368 => self.evaluate_368(ctx),
364 370 => self.evaluate_370(ctx),
365 371 => self.evaluate_371(ctx),
366 372 => self.evaluate_372(ctx),
367 373 => self.evaluate_373(ctx),
368 375 => self.evaluate_375(ctx),
369 376 => self.evaluate_376(ctx),
370 377 => self.evaluate_377(ctx),
371 378 => self.evaluate_378(ctx),
372 379 => self.evaluate_379(ctx),
373 380 => self.evaluate_380(ctx),
374 384 => self.evaluate_384(ctx),
375 386 => self.evaluate_386(ctx),
376 387 => self.evaluate_387(ctx),
377 388 => self.evaluate_388(ctx),
378 391 => self.evaluate_391(ctx),
379 392 => self.evaluate_392(ctx),
380 393 => self.evaluate_393(ctx),
381 394 => self.evaluate_394(ctx),
382 395 => self.evaluate_395(ctx),
383 396 => self.evaluate_396(ctx),
384 397 => self.evaluate_397(ctx),
385 398 => self.evaluate_398(ctx),
386 399 => self.evaluate_399(ctx),
387 401 => self.evaluate_401(ctx),
388 402 => self.evaluate_402(ctx),
389 403 => self.evaluate_403(ctx),
390 404 => self.evaluate_404(ctx),
391 405 => self.evaluate_405(ctx),
392 406 => self.evaluate_406(ctx),
393 407 => self.evaluate_407(ctx),
394 408 => self.evaluate_408(ctx),
395 409 => self.evaluate_409(ctx),
396 410 => self.evaluate_410(ctx),
397 411 => self.evaluate_411(ctx),
398 412 => self.evaluate_412(ctx),
399 413 => self.evaluate_413(ctx),
400 414 => self.evaluate_414(ctx),
401 415 => self.evaluate_415(ctx),
402 416 => self.evaluate_416(ctx),
403 417 => self.evaluate_417(ctx),
404 419 => self.evaluate_419(ctx),
405 420 => self.evaluate_420(ctx),
406 421 => self.evaluate_421(ctx),
407 425 => self.evaluate_425(ctx),
408 426 => self.evaluate_426(ctx),
409 427 => self.evaluate_427(ctx),
410 428 => self.evaluate_428(ctx),
411 429 => self.evaluate_429(ctx),
412 430 => self.evaluate_430(ctx),
413 431 => self.evaluate_431(ctx),
414 432 => self.evaluate_432(ctx),
415 433 => self.evaluate_433(ctx),
416 435 => self.evaluate_435(ctx),
417 436 => self.evaluate_436(ctx),
418 437 => self.evaluate_437(ctx),
419 438 => self.evaluate_438(ctx),
420 440 => self.evaluate_440(ctx),
421 441 => self.evaluate_441(ctx),
422 442 => self.evaluate_442(ctx),
423 444 => self.evaluate_444(ctx),
424 445 => self.evaluate_445(ctx),
425 446 => self.evaluate_446(ctx),
426 447 => self.evaluate_447(ctx),
427 448 => self.evaluate_448(ctx),
428 449 => self.evaluate_449(ctx),
429 450 => self.evaluate_450(ctx),
430 451 => self.evaluate_451(ctx),
431 452 => self.evaluate_452(ctx),
432 453 => self.evaluate_453(ctx),
433 454 => self.evaluate_454(ctx),
434 455 => self.evaluate_455(ctx),
435 456 => self.evaluate_456(ctx),
436 457 => self.evaluate_457(ctx),
437 458 => self.evaluate_458(ctx),
438 459 => self.evaluate_459(ctx),
439 460 => self.evaluate_460(ctx),
440 461 => self.evaluate_461(ctx),
441 462 => self.evaluate_462(ctx),
442 463 => self.evaluate_463(ctx),
443 465 => self.evaluate_465(ctx),
444 466 => self.evaluate_466(ctx),
445 467 => self.evaluate_467(ctx),
446 468 => self.evaluate_468(ctx),
447 469 => self.evaluate_469(ctx),
448 470 => self.evaluate_470(ctx),
449 471 => self.evaluate_471(ctx),
450 472 => self.evaluate_472(ctx),
451 473 => self.evaluate_473(ctx),
452 474 => self.evaluate_474(ctx),
453 475 => self.evaluate_475(ctx),
454 476 => self.evaluate_476(ctx),
455 477 => self.evaluate_477(ctx),
456 478 => self.evaluate_478(ctx),
457 479 => self.evaluate_479(ctx),
458 480 => self.evaluate_480(ctx),
459 481 => self.evaluate_481(ctx),
460 483 => self.evaluate_483(ctx),
461 484 => self.evaluate_484(ctx),
462 487 => self.evaluate_487(ctx),
463 489 => self.evaluate_489(ctx),
464 490 => self.evaluate_490(ctx),
465 491 => self.evaluate_491(ctx),
466 494 => self.evaluate_494(ctx),
467 500 => self.evaluate_500(ctx),
468 501 => self.evaluate_501(ctx),
469 502 => self.evaluate_502(ctx),
470 503 => self.evaluate_503(ctx),
471 504 => self.evaluate_504(ctx),
472 505 => self.evaluate_505(ctx),
473 506 => self.evaluate_506(ctx),
474 507 => self.evaluate_507(ctx),
475 508 => self.evaluate_508(ctx),
476 509 => self.evaluate_509(ctx),
477 510 => self.evaluate_510(ctx),
478 511 => self.evaluate_511(ctx),
479 512 => self.evaluate_512(ctx),
480 513 => self.evaluate_513(ctx),
481 514 => self.evaluate_514(ctx),
482 515 => self.evaluate_515(ctx),
483 516 => self.evaluate_516(ctx),
484 517 => self.evaluate_517(ctx),
485 518 => self.evaluate_518(ctx),
486 519 => self.evaluate_519(ctx),
487 520 => self.evaluate_520(ctx),
488 521 => self.evaluate_521(ctx),
489 522 => self.evaluate_522(ctx),
490 523 => self.evaluate_523(ctx),
491 524 => self.evaluate_524(ctx),
492 525 => self.evaluate_525(ctx),
493 526 => self.evaluate_526(ctx),
494 527 => self.evaluate_527(ctx),
495 528 => self.evaluate_528(ctx),
496 529 => self.evaluate_529(ctx),
497 530 => self.evaluate_530(ctx),
498 531 => self.evaluate_531(ctx),
499 532 => self.evaluate_532(ctx),
500 533 => self.evaluate_533(ctx),
501 555 => self.evaluate_555(ctx),
502 556 => self.evaluate_556(ctx),
503 558 => self.evaluate_558(ctx),
504 559 => self.evaluate_559(ctx),
505 563 => self.evaluate_563(ctx),
506 566 => self.evaluate_566(ctx),
507 567 => self.evaluate_567(ctx),
508 568 => self.evaluate_568(ctx),
509 569 => self.evaluate_569(ctx),
510 570 => self.evaluate_570(ctx),
511 572 => self.evaluate_572(ctx),
512 576 => self.evaluate_576(ctx),
513 577 => self.evaluate_577(ctx),
514 579 => self.evaluate_579(ctx),
515 580 => self.evaluate_580(ctx),
516 581 => self.evaluate_581(ctx),
517 586 => self.evaluate_586(ctx),
518 590 => self.evaluate_590(ctx),
519 594 => self.evaluate_594(ctx),
520 599 => self.evaluate_599(ctx),
521 601 => self.evaluate_601(ctx),
522 606 => self.evaluate_606(ctx),
523 609 => self.evaluate_609(ctx),
524 611 => self.evaluate_611(ctx),
525 614 => self.evaluate_614(ctx),
526 617 => self.evaluate_617(ctx),
527 618 => self.evaluate_618(ctx),
528 619 => self.evaluate_619(ctx),
529 621 => self.evaluate_621(ctx),
530 622 => self.evaluate_622(ctx),
531 623 => self.evaluate_623(ctx),
532 630 => self.evaluate_630(ctx),
533 631 => self.evaluate_631(ctx),
534 632 => self.evaluate_632(ctx),
535 637 => self.evaluate_637(ctx),
536 638 => self.evaluate_638(ctx),
537 639 => self.evaluate_639(ctx),
538 640 => self.evaluate_640(ctx),
539 641 => self.evaluate_641(ctx),
540 642 => self.evaluate_642(ctx),
541 643 => self.evaluate_643(ctx),
542 645 => self.evaluate_645(ctx),
543 646 => self.evaluate_646(ctx),
544 647 => self.evaluate_647(ctx),
545 648 => self.evaluate_648(ctx),
546 651 => self.evaluate_651(ctx),
547 653 => self.evaluate_653(ctx),
548 655 => self.evaluate_655(ctx),
549 659 => self.evaluate_659(ctx),
550 660 => self.evaluate_660(ctx),
551 662 => self.evaluate_662(ctx),
552 663 => self.evaluate_663(ctx),
553 664 => self.evaluate_664(ctx),
554 665 => self.evaluate_665(ctx),
555 667 => self.evaluate_667(ctx),
556 668 => self.evaluate_668(ctx),
557 670 => self.evaluate_670(ctx),
558 671 => self.evaluate_671(ctx),
559 672 => self.evaluate_672(ctx),
560 673 => self.evaluate_673(ctx),
561 674 => self.evaluate_674(ctx),
562 675 => self.evaluate_675(ctx),
563 677 => self.evaluate_677(ctx),
564 678 => self.evaluate_678(ctx),
565 679 => self.evaluate_679(ctx),
566 680 => self.evaluate_680(ctx),
567 682 => self.evaluate_682(ctx),
568 683 => self.evaluate_683(ctx),
569 684 => self.evaluate_684(ctx),
570 685 => self.evaluate_685(ctx),
571 687 => self.evaluate_687(ctx),
572 688 => self.evaluate_688(ctx),
573 689 => self.evaluate_689(ctx),
574 690 => self.evaluate_690(ctx),
575 693 => self.evaluate_693(ctx),
576 694 => self.evaluate_694(ctx),
577 695 => self.evaluate_695(ctx),
578 696 => self.evaluate_696(ctx),
579 698 => self.evaluate_698(ctx),
580 699 => self.evaluate_699(ctx),
581 700 => self.evaluate_700(ctx),
582 704 => self.evaluate_704(ctx),
583 705 => self.evaluate_705(ctx),
584 706 => self.evaluate_706(ctx),
585 707 => self.evaluate_707(ctx),
586 708 => self.evaluate_708(ctx),
587 709 => self.evaluate_709(ctx),
588 710 => self.evaluate_710(ctx),
589 711 => self.evaluate_711(ctx),
590 712 => self.evaluate_712(ctx),
591 713 => self.evaluate_713(ctx),
592 714 => self.evaluate_714(ctx),
593 715 => self.evaluate_715(ctx),
594 716 => self.evaluate_716(ctx),
595 717 => self.evaluate_717(ctx),
596 718 => self.evaluate_718(ctx),
597 719 => self.evaluate_719(ctx),
598 902 => self.evaluate_902(ctx),
599 910 => self.evaluate_910(ctx),
600 914 => self.evaluate_914(ctx),
601 922 => self.evaluate_922(ctx),
602 926 => self.evaluate_926(ctx),
603 930 => self.evaluate_930(ctx),
604 931 => self.evaluate_931(ctx),
605 932 => self.evaluate_932(ctx),
606 933 => self.evaluate_933(ctx),
607 937 => self.evaluate_937(ctx),
608 938 => self.evaluate_938(ctx),
609 939 => self.evaluate_939(ctx),
610 940 => self.evaluate_940(ctx),
611 942 => self.evaluate_942(ctx),
612 943 => self.evaluate_943(ctx),
613 946 => self.evaluate_946(ctx),
614 948 => self.evaluate_948(ctx),
615 950 => self.evaluate_950(ctx),
616 951 => self.evaluate_951(ctx),
617 952 => self.evaluate_952(ctx),
618 955 => self.evaluate_955(ctx),
619 957 => self.evaluate_957(ctx),
620 960 => self.evaluate_960(ctx),
621 961 => self.evaluate_961(ctx),
622 967 => self.evaluate_967(ctx),
623 2001 => self.evaluate_2001(ctx),
624 2002 => self.evaluate_2002(ctx),
625 2003 => self.evaluate_2003(ctx),
626 2004 => self.evaluate_2004(ctx),
627 2005 => self.evaluate_2005(ctx),
628 2006 => self.evaluate_2006(ctx),
629 2007 => self.evaluate_2007(ctx),
630 2008 => self.evaluate_2008(ctx),
631 2009 => self.evaluate_2009(ctx),
632 2010 => self.evaluate_2010(ctx),
633 2011 => self.evaluate_2011(ctx),
634 2012 => self.evaluate_2012(ctx),
635 2013 => self.evaluate_2013(ctx),
636 2014 => self.evaluate_2014(ctx),
637 2015 => self.evaluate_2015(ctx),
638 2016 => self.evaluate_2016(ctx),
639 2017 => self.evaluate_2017(ctx),
640 2018 => self.evaluate_2018(ctx),
641 2060 => self.evaluate_2060(ctx),
642 2061 => self.evaluate_2061(ctx),
643 2071 => self.evaluate_2071(ctx),
644 2073 => self.evaluate_2073(ctx),
645 2075 => self.evaluate_2075(ctx),
646 2080 => self.evaluate_2080(ctx),
647 2095 => self.evaluate_2095(ctx),
648 2096 => self.evaluate_2096(ctx),
649 2119 => self.evaluate_2119(ctx),
650 2140 => self.evaluate_2140(ctx),
651 2182 => self.evaluate_2182(ctx),
652 2183 => self.evaluate_2183(ctx),
653 2207 => self.evaluate_2207(ctx),
654 2225 => self.evaluate_2225(ctx),
655 2236 => self.evaluate_2236(ctx),
656 2252 => self.evaluate_2252(ctx),
657 2261 => self.evaluate_2261(ctx),
658 2284 => self.evaluate_2284(ctx),
659 2286 => self.evaluate_2286(ctx),
660 2287 => self.evaluate_2287(ctx),
661 2288 => self.evaluate_2288(ctx),
662 2307 => self.evaluate_2307(ctx),
663 2308 => self.evaluate_2308(ctx),
664 2309 => self.evaluate_2309(ctx),
665 2310 => self.evaluate_2310(ctx),
666 2311 => self.evaluate_2311(ctx),
667 2312 => self.evaluate_2312(ctx),
668 2313 => self.evaluate_2313(ctx),
669 2317 => self.evaluate_2317(ctx),
670 2318 => self.evaluate_2318(ctx),
671 2344 => self.evaluate_2344(ctx),
672 2350 => self.evaluate_2350(ctx),
673 2351 => self.evaluate_2351(ctx),
674 2352 => self.evaluate_2352(ctx),
675 2356 => self.evaluate_2356(ctx),
676 2357 => self.evaluate_2357(ctx),
677 2358 => self.evaluate_2358(ctx),
678 2359 => self.evaluate_2359(ctx),
679 2360 => self.evaluate_2360(ctx),
680 2361 => self.evaluate_2361(ctx),
681 _ => ConditionResult::Unknown,
682 }
683 }
684
685 fn is_external(&self, condition: u32) -> bool {
686 self.external_conditions.contains(&condition)
687 }
688 fn is_known(&self, condition: u32) -> bool {
689 matches!(
690 condition,
691 1 | 4
692 | 5
693 | 6
694 | 7
695 | 8
696 | 9
697 | 10
698 | 11
699 | 12
700 | 13
701 | 14
702 | 15
703 | 16
704 | 17
705 | 18
706 | 19
707 | 20
708 | 21
709 | 22
710 | 23
711 | 24
712 | 25
713 | 27
714 | 30
715 | 31
716 | 32
717 | 33
718 | 34
719 | 35
720 | 36
721 | 37
722 | 38
723 | 39
724 | 40
725 | 41
726 | 42
727 | 43
728 | 44
729 | 45
730 | 46
731 | 47
732 | 48
733 | 49
734 | 50
735 | 51
736 | 52
737 | 53
738 | 54
739 | 55
740 | 56
741 | 57
742 | 58
743 | 60
744 | 61
745 | 62
746 | 63
747 | 64
748 | 65
749 | 66
750 | 67
751 | 68
752 | 69
753 | 70
754 | 71
755 | 72
756 | 73
757 | 74
758 | 75
759 | 76
760 | 77
761 | 78
762 | 83
763 | 84
764 | 85
765 | 86
766 | 87
767 | 88
768 | 89
769 | 90
770 | 91
771 | 92
772 | 93
773 | 94
774 | 95
775 | 96
776 | 97
777 | 98
778 | 99
779 | 100
780 | 101
781 | 102
782 | 103
783 | 104
784 | 105
785 | 106
786 | 107
787 | 108
788 | 110
789 | 111
790 | 112
791 | 113
792 | 114
793 | 115
794 | 116
795 | 117
796 | 118
797 | 119
798 | 120
799 | 121
800 | 122
801 | 123
802 | 124
803 | 125
804 | 126
805 | 127
806 | 128
807 | 129
808 | 130
809 | 131
810 | 132
811 | 133
812 | 134
813 | 135
814 | 136
815 | 137
816 | 138
817 | 139
818 | 140
819 | 141
820 | 142
821 | 143
822 | 144
823 | 145
824 | 146
825 | 147
826 | 148
827 | 149
828 | 150
829 | 151
830 | 152
831 | 153
832 | 156
833 | 161
834 | 162
835 | 163
836 | 164
837 | 165
838 | 166
839 | 167
840 | 170
841 | 172
842 | 173
843 | 174
844 | 175
845 | 176
846 | 177
847 | 178
848 | 179
849 | 180
850 | 184
851 | 190
852 | 191
853 | 192
854 | 193
855 | 194
856 | 195
857 | 196
858 | 197
859 | 198
860 | 199
861 | 201
862 | 202
863 | 203
864 | 204
865 | 205
866 | 206
867 | 209
868 | 210
869 | 212
870 | 213
871 | 215
872 | 216
873 | 217
874 | 219
875 | 220
876 | 221
877 | 223
878 | 224
879 | 227
880 | 229
881 | 232
882 | 233
883 | 234
884 | 237
885 | 238
886 | 239
887 | 240
888 | 241
889 | 243
890 | 244
891 | 248
892 | 249
893 | 251
894 | 252
895 | 254
896 | 255
897 | 256
898 | 257
899 | 259
900 | 261
901 | 262
902 | 265
903 | 266
904 | 267
905 | 268
906 | 269
907 | 270
908 | 273
909 | 279
910 | 280
911 | 282
912 | 284
913 | 285
914 | 286
915 | 287
916 | 288
917 | 291
918 | 292
919 | 293
920 | 294
921 | 295
922 | 296
923 | 297
924 | 298
925 | 299
926 | 300
927 | 301
928 | 302
929 | 303
930 | 304
931 | 305
932 | 306
933 | 307
934 | 309
935 | 314
936 | 315
937 | 316
938 | 317
939 | 318
940 | 321
941 | 322
942 | 323
943 | 327
944 | 329
945 | 331
946 | 332
947 | 333
948 | 334
949 | 335
950 | 336
951 | 337
952 | 338
953 | 339
954 | 340
955 | 341
956 | 342
957 | 344
958 | 345
959 | 346
960 | 347
961 | 348
962 | 349
963 | 350
964 | 351
965 | 352
966 | 355
967 | 356
968 | 357
969 | 358
970 | 359
971 | 360
972 | 363
973 | 365
974 | 366
975 | 367
976 | 368
977 | 370
978 | 371
979 | 372
980 | 373
981 | 375
982 | 376
983 | 377
984 | 378
985 | 379
986 | 380
987 | 384
988 | 386
989 | 387
990 | 388
991 | 391
992 | 392
993 | 393
994 | 394
995 | 395
996 | 396
997 | 397
998 | 398
999 | 399
1000 | 401
1001 | 402
1002 | 403
1003 | 404
1004 | 405
1005 | 406
1006 | 407
1007 | 408
1008 | 409
1009 | 410
1010 | 411
1011 | 412
1012 | 413
1013 | 414
1014 | 415
1015 | 416
1016 | 417
1017 | 419
1018 | 420
1019 | 421
1020 | 425
1021 | 426
1022 | 427
1023 | 428
1024 | 429
1025 | 430
1026 | 431
1027 | 432
1028 | 433
1029 | 435
1030 | 436
1031 | 437
1032 | 438
1033 | 440
1034 | 441
1035 | 442
1036 | 444
1037 | 445
1038 | 446
1039 | 447
1040 | 448
1041 | 449
1042 | 450
1043 | 451
1044 | 452
1045 | 453
1046 | 454
1047 | 455
1048 | 456
1049 | 457
1050 | 458
1051 | 459
1052 | 460
1053 | 461
1054 | 462
1055 | 463
1056 | 465
1057 | 466
1058 | 467
1059 | 468
1060 | 469
1061 | 470
1062 | 471
1063 | 472
1064 | 473
1065 | 474
1066 | 475
1067 | 476
1068 | 477
1069 | 478
1070 | 479
1071 | 480
1072 | 481
1073 | 483
1074 | 484
1075 | 487
1076 | 489
1077 | 490
1078 | 491
1079 | 494
1080 | 500
1081 | 501
1082 | 502
1083 | 503
1084 | 504
1085 | 505
1086 | 506
1087 | 507
1088 | 508
1089 | 509
1090 | 510
1091 | 511
1092 | 512
1093 | 513
1094 | 514
1095 | 515
1096 | 516
1097 | 517
1098 | 518
1099 | 519
1100 | 520
1101 | 521
1102 | 522
1103 | 523
1104 | 524
1105 | 525
1106 | 526
1107 | 527
1108 | 528
1109 | 529
1110 | 530
1111 | 531
1112 | 532
1113 | 533
1114 | 555
1115 | 556
1116 | 558
1117 | 559
1118 | 563
1119 | 566
1120 | 567
1121 | 568
1122 | 569
1123 | 570
1124 | 572
1125 | 576
1126 | 577
1127 | 579
1128 | 580
1129 | 581
1130 | 586
1131 | 590
1132 | 594
1133 | 599
1134 | 601
1135 | 606
1136 | 609
1137 | 611
1138 | 614
1139 | 617
1140 | 618
1141 | 619
1142 | 621
1143 | 622
1144 | 623
1145 | 630
1146 | 631
1147 | 632
1148 | 637
1149 | 638
1150 | 639
1151 | 640
1152 | 641
1153 | 642
1154 | 643
1155 | 645
1156 | 646
1157 | 647
1158 | 648
1159 | 651
1160 | 653
1161 | 655
1162 | 659
1163 | 660
1164 | 662
1165 | 663
1166 | 664
1167 | 665
1168 | 667
1169 | 668
1170 | 670
1171 | 671
1172 | 672
1173 | 673
1174 | 674
1175 | 675
1176 | 677
1177 | 678
1178 | 679
1179 | 680
1180 | 682
1181 | 683
1182 | 684
1183 | 685
1184 | 687
1185 | 688
1186 | 689
1187 | 690
1188 | 693
1189 | 694
1190 | 695
1191 | 696
1192 | 698
1193 | 699
1194 | 700
1195 | 704
1196 | 705
1197 | 706
1198 | 707
1199 | 708
1200 | 709
1201 | 710
1202 | 711
1203 | 712
1204 | 713
1205 | 714
1206 | 715
1207 | 716
1208 | 717
1209 | 718
1210 | 719
1211 | 902
1212 | 910
1213 | 914
1214 | 922
1215 | 926
1216 | 930
1217 | 931
1218 | 932
1219 | 933
1220 | 937
1221 | 938
1222 | 939
1223 | 940
1224 | 942
1225 | 943
1226 | 946
1227 | 948
1228 | 950
1229 | 951
1230 | 952
1231 | 955
1232 | 957
1233 | 960
1234 | 961
1235 | 967
1236 | 2001
1237 | 2002
1238 | 2003
1239 | 2004
1240 | 2005
1241 | 2006
1242 | 2007
1243 | 2008
1244 | 2009
1245 | 2010
1246 | 2011
1247 | 2012
1248 | 2013
1249 | 2014
1250 | 2015
1251 | 2016
1252 | 2017
1253 | 2018
1254 | 2060
1255 | 2061
1256 | 2071
1257 | 2073
1258 | 2075
1259 | 2080
1260 | 2095
1261 | 2096
1262 | 2119
1263 | 2140
1264 | 2182
1265 | 2183
1266 | 2207
1267 | 2225
1268 | 2236
1269 | 2252
1270 | 2261
1271 | 2284
1272 | 2286
1273 | 2287
1274 | 2288
1275 | 2307
1276 | 2308
1277 | 2309
1278 | 2310
1279 | 2311
1280 | 2312
1281 | 2313
1282 | 2317
1283 | 2318
1284 | 2344
1285 | 2350
1286 | 2351
1287 | 2352
1288 | 2356
1289 | 2357
1290 | 2358
1291 | 2359
1292 | 2360
1293 | 2361
1294 )
1295 }
1296}
1297
1298impl UtilmdStromConditionEvaluatorFV2504 {
1299 /// [2006] Segmentgruppe ist genau einmal für jede SG8 SEQ+Z01 (Daten der Marktlokation) anzugeben, bei der die Bedingung [199] an der Segmentgruppe erfüllt ist. Dabei ist die selbe Zeitraum-ID im nachfolge...
1300 // REVIEW: Counts SG8 instances with SEQ+Z01 where condition [199] is fulfilled and collects their Zeitraum-IDs from SEQ elements[1][0]. Returns True if at least one qualifying parent exists (cardinality enforcement is partial — full 'exactly once' check requires knowing the current SG type). The recursive call self.evaluate(199, ctx) operates at message scope, which is the best available approximation. (medium confidence)
1301 fn evaluate_2006(&self, ctx: &EvaluationContext) -> ConditionResult {
1302 let nav = match ctx.navigator() {
1303 Some(n) => n,
1304 None => return ConditionResult::Unknown,
1305 };
1306 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
1307 let mut qualifying_zeitraum_ids: Vec<String> = Vec::new();
1308 for i in 0..sg8_count {
1309 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
1310 let is_z01 = seq_segs.iter().any(|s| {
1311 s.elements
1312 .first()
1313 .and_then(|e| e.first())
1314 .is_some_and(|v| v == "Z01")
1315 });
1316 if is_z01 && matches!(self.evaluate(199, ctx), ConditionResult::True) {
1317 for seq in &seq_segs {
1318 if seq
1319 .elements
1320 .first()
1321 .and_then(|e| e.first())
1322 .is_some_and(|v| v == "Z01")
1323 {
1324 if let Some(zid) = seq.elements.get(1).and_then(|e| e.first()) {
1325 if !zid.is_empty() {
1326 qualifying_zeitraum_ids.push(zid.clone());
1327 }
1328 }
1329 }
1330 }
1331 }
1332 }
1333 if qualifying_zeitraum_ids.is_empty() {
1334 return ConditionResult::Unknown;
1335 }
1336 ConditionResult::True
1337 }
1338
1339 /// [2007] Segmentgruppe ist genau einmal für jede SG8 SEQ+Z01 (Daten der Marktlokation) anzugeben, bei der die Bedingungen [199] an der Segmentgruppe erfüllt ist. Dabei ist die selbe Zeitraum-ID im nachfol...
1340 // REVIEW: Semantically identical to [2006] — 'Bedingungen' (plural) vs 'Bedingung' (singular) is a grammatical variation with no functional difference. Same logic: collects qualifying SG8 SEQ+Z01 Zeitraum-IDs where condition [199] is fulfilled. Recursive call self.evaluate(199, ctx) operates at message scope. (medium confidence)
1341 fn evaluate_2007(&self, ctx: &EvaluationContext) -> ConditionResult {
1342 let nav = match ctx.navigator() {
1343 Some(n) => n,
1344 None => return ConditionResult::Unknown,
1345 };
1346 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
1347 let mut qualifying_zeitraum_ids: Vec<String> = Vec::new();
1348 for i in 0..sg8_count {
1349 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
1350 let is_z01 = seq_segs.iter().any(|s| {
1351 s.elements
1352 .first()
1353 .and_then(|e| e.first())
1354 .is_some_and(|v| v == "Z01")
1355 });
1356 if is_z01 && matches!(self.evaluate(199, ctx), ConditionResult::True) {
1357 for seq in &seq_segs {
1358 if seq
1359 .elements
1360 .first()
1361 .and_then(|e| e.first())
1362 .is_some_and(|v| v == "Z01")
1363 {
1364 if let Some(zid) = seq.elements.get(1).and_then(|e| e.first()) {
1365 if !zid.is_empty() {
1366 qualifying_zeitraum_ids.push(zid.clone());
1367 }
1368 }
1369 }
1370 }
1371 }
1372 }
1373 if qualifying_zeitraum_ids.is_empty() {
1374 return ConditionResult::Unknown;
1375 }
1376 ConditionResult::True
1377 }
1378
1379 /// [2008] Segmentgruppe ist genau einmal für jede SG8 SEQ+Z01 (Daten der Marktlokation) anzugeben, bei der die Bedingung [89] an der Segmentgruppe erfüllt ist. Dabei ist die selbe Zeitraum-ID im nachfolgen...
1380 // REVIEW: Same structure as [2006/2007] but references condition [89] instead of [199]. Counts qualifying SG8 SEQ+Z01 instances where condition [89] is fulfilled and collects their Zeitraum-IDs from SEQ elements[1][0]. The recursive self.evaluate(89, ctx) call operates at message scope. (medium confidence)
1381 fn evaluate_2008(&self, ctx: &EvaluationContext) -> ConditionResult {
1382 let nav = match ctx.navigator() {
1383 Some(n) => n,
1384 None => return ConditionResult::Unknown,
1385 };
1386 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
1387 let mut qualifying_zeitraum_ids: Vec<String> = Vec::new();
1388 for i in 0..sg8_count {
1389 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
1390 let is_z01 = seq_segs.iter().any(|s| {
1391 s.elements
1392 .first()
1393 .and_then(|e| e.first())
1394 .is_some_and(|v| v == "Z01")
1395 });
1396 if is_z01 && matches!(self.evaluate(89, ctx), ConditionResult::True) {
1397 for seq in &seq_segs {
1398 if seq
1399 .elements
1400 .first()
1401 .and_then(|e| e.first())
1402 .is_some_and(|v| v == "Z01")
1403 {
1404 if let Some(zid) = seq.elements.get(1).and_then(|e| e.first()) {
1405 if !zid.is_empty() {
1406 qualifying_zeitraum_ids.push(zid.clone());
1407 }
1408 }
1409 }
1410 }
1411 }
1412 }
1413 if qualifying_zeitraum_ids.is_empty() {
1414 return ConditionResult::Unknown;
1415 }
1416 ConditionResult::True
1417 }
1418
1419 /// [2009] Segmentgruppe ist genau einmal für jede SG8 SEQ+Z01 (Daten der Marktlokation) anzugeben, bei der die Bedingungen [89] an der Segmentgruppe erfüllt ist. Dabei ist die selbe Zeitraum-ID im nachfolg...
1420 // REVIEW: Semantically identical to [2008] — 'Bedingungen' (plural) vs 'Bedingung' (singular) is a grammatical variation. Same logic: collects qualifying SG8 SEQ+Z01 Zeitraum-IDs where condition [89] is fulfilled. Recursive call self.evaluate(89, ctx) operates at message scope. (medium confidence)
1421 fn evaluate_2009(&self, ctx: &EvaluationContext) -> ConditionResult {
1422 let nav = match ctx.navigator() {
1423 Some(n) => n,
1424 None => return ConditionResult::Unknown,
1425 };
1426 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
1427 let mut qualifying_zeitraum_ids: Vec<String> = Vec::new();
1428 for i in 0..sg8_count {
1429 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
1430 let is_z01 = seq_segs.iter().any(|s| {
1431 s.elements
1432 .first()
1433 .and_then(|e| e.first())
1434 .is_some_and(|v| v == "Z01")
1435 });
1436 if is_z01 && matches!(self.evaluate(89, ctx), ConditionResult::True) {
1437 for seq in &seq_segs {
1438 if seq
1439 .elements
1440 .first()
1441 .and_then(|e| e.first())
1442 .is_some_and(|v| v == "Z01")
1443 {
1444 if let Some(zid) = seq.elements.get(1).and_then(|e| e.first()) {
1445 if !zid.is_empty() {
1446 qualifying_zeitraum_ids.push(zid.clone());
1447 }
1448 }
1449 }
1450 }
1451 }
1452 }
1453 if qualifying_zeitraum_ids.is_empty() {
1454 return ConditionResult::Unknown;
1455 }
1456 ConditionResult::True
1457 }
1458
1459 /// [1] Wenn Aufteilung vorhanden
1460 fn evaluate_1(&self, ctx: &EvaluationContext) -> ConditionResult {
1461 ctx.external.evaluate("message_splitting")
1462 }
1463
1464 /// [4] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle LF
1465 fn evaluate_4(&self, ctx: &EvaluationContext) -> ConditionResult {
1466 ctx.external.evaluate("recipient_is_lf")
1467 }
1468
1469 /// [5] Wenn MP-ID in SG2 NAD+MS (Nachrichtenabsender) in der Rolle LF
1470 fn evaluate_5(&self, ctx: &EvaluationContext) -> ConditionResult {
1471 ctx.external.evaluate("sender_is_lf")
1472 }
1473
1474 /// [6] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle ÜNB
1475 fn evaluate_6(&self, ctx: &EvaluationContext) -> ConditionResult {
1476 ctx.external.evaluate("recipient_role_check")
1477 }
1478
1479 /// [7] Wenn SG4 STS+7++ZG9/ZH1/ZH2 (Transaktionsgrund: Aufhebung einer zukünftigen Zuordnung wegen Auszug des Kunden / -wegen Stilllegung / -wegen aufgehobenem Vertragsverhältnis) vorhanden
1480 fn evaluate_7(&self, _ctx: &EvaluationContext) -> ConditionResult {
1481 // TODO: implement
1482 ConditionResult::Unknown
1483 }
1484
1485 /// [8] Wenn für Datenclearing erforderlich
1486 fn evaluate_8(&self, ctx: &EvaluationContext) -> ConditionResult {
1487 ctx.external.evaluate("data_clearing_required")
1488 }
1489
1490 /// [9] Wenn MP-ID in SG2 NAD+MS (Nachrichtenabsender) in der Rolle MSB
1491 fn evaluate_9(&self, ctx: &EvaluationContext) -> ConditionResult {
1492 ctx.external.evaluate("sender_role_check")
1493 }
1494
1495 /// [10] Wenn SG4 STS+7++xxx+xxx+E01/E03 (Transaktionsgrund befristete Anmeldung) vorhanden
1496 fn evaluate_10(&self, ctx: &EvaluationContext) -> ConditionResult {
1497 ctx.external.evaluate("registration_is_time_limited")
1498 }
1499
1500 /// [11] Wenn SG4 STS+7++ZG9/ZH1/ZH2 (Transaktionsgrund: Aufhebung einer zukünftigen Zuordnung wegen Auszug des Kunden / -wegen Stilllegung / -wegen aufgehobenem Vertragsverhältnis) nicht vorhanden
1501 fn evaluate_11(&self, _ctx: &EvaluationContext) -> ConditionResult {
1502 // TODO: implement
1503 ConditionResult::Unknown
1504 }
1505
1506 /// [12] Wenn SG4 DTM+471 (Ende zum nächstmöglichem Termin) nicht vorhanden
1507 fn evaluate_12(&self, _ctx: &EvaluationContext) -> ConditionResult {
1508 // TODO: implement
1509 ConditionResult::Unknown
1510 }
1511
1512 /// [13] Wenn SG4 STS+E01++Z01 (Status der Antwort: Zustimmung mit Terminänderung) nicht vorhanden
1513 fn evaluate_13(&self, _ctx: &EvaluationContext) -> ConditionResult {
1514 // TODO: implement
1515 ConditionResult::Unknown
1516 }
1517
1518 /// [14] Wenn Datum bekannt
1519 fn evaluate_14(&self, ctx: &EvaluationContext) -> ConditionResult {
1520 ctx.external.evaluate("date_known")
1521 }
1522
1523 /// [15] Wenn in derselben SG8 das SEQ+Z98 (Informative Daten der Marktlokation) vorhanden
1524 fn evaluate_15(&self, _ctx: &EvaluationContext) -> ConditionResult {
1525 // TODO: implement
1526 ConditionResult::Unknown
1527 }
1528
1529 /// [16] Wenn SG4 STS+E01++Z12 (Status der Antwort: Ablehnung Vertragsbindung) vorhanden
1530 fn evaluate_16(&self, _ctx: &EvaluationContext) -> ConditionResult {
1531 // TODO: implement
1532 ConditionResult::Unknown
1533 }
1534
1535 /// [17] Wenn in derselben SG8 das SEQ+Z01/Z80/Z81 (Daten der Marktlokation) vorhanden
1536 fn evaluate_17(&self, _ctx: &EvaluationContext) -> ConditionResult {
1537 // TODO: implement
1538 ConditionResult::Unknown
1539 }
1540
1541 /// [18] Wenn SG4 DTM+93 (Ende zum) nicht vorhanden
1542 fn evaluate_18(&self, _ctx: &EvaluationContext) -> ConditionResult {
1543 // TODO: implement
1544 ConditionResult::Unknown
1545 }
1546
1547 /// [19] Wenn SG8 SEQ+Z01/ Z98 (Daten der Marktlokation) SG10 CCI+++ZC0 (Prognose auf Basis von Werten) vorhanden
1548 fn evaluate_19(&self, _ctx: &EvaluationContext) -> ConditionResult {
1549 // TODO: implement
1550 ConditionResult::Unknown
1551 }
1552
1553 /// [20] Wenn SG8 SEQ+Z01 (Daten der Marktlokation) SG10 CCI+Z30++Z07 (Verbrauch) vorhanden
1554 fn evaluate_20(&self, _ctx: &EvaluationContext) -> ConditionResult {
1555 // TODO: implement
1556 ConditionResult::Unknown
1557 }
1558
1559 /// [21] Wenn SG10 CCI+++ZA6 (Prognose auf Basis von Profilen) in dieser SG8 vorhanden
1560 fn evaluate_21(&self, _ctx: &EvaluationContext) -> ConditionResult {
1561 // TODO: implement
1562 ConditionResult::Unknown
1563 }
1564
1565 /// [22] Es ist die Zeitraum-ID vom DE1156 aus einem passenden SG6 RFF+Z47/ Z48/ Z49 (Verwendungszeitraum der Daten) einzutragen
1566 // REVIEW: Checks if any SG6 RFF+Z47/Z48/Z49 Zeitraum-ID (DE1156 at elements[0][2]) matches any SG8 SEQ Zeitraum-ID reference (DE1050 at elements[1][0]). Uses groups_share_qualified_value for cross-group correlation across all three qualifying codes. (medium confidence)
1567 fn evaluate_22(&self, ctx: &EvaluationContext) -> ConditionResult {
1568 for qual in &["Z47", "Z48", "Z49"] {
1569 if matches!(
1570 ctx.groups_share_qualified_value(
1571 "RFF",
1572 0,
1573 qual,
1574 0,
1575 2,
1576 &["SG4", "SG6"],
1577 "SEQ",
1578 1,
1579 0,
1580 &["SG4", "SG8"],
1581 ),
1582 ConditionResult::True
1583 ) {
1584 return ConditionResult::True;
1585 }
1586 }
1587 ConditionResult::False
1588 }
1589
1590 /// [23] Wenn in dieser SG4 das STS+E01++A05/A99 (Status der Antwort) vorhanden
1591 fn evaluate_23(&self, _ctx: &EvaluationContext) -> ConditionResult {
1592 // TODO: implement
1593 ConditionResult::Unknown
1594 }
1595
1596 /// [24] Wenn in dieser SG4 das STS+E01++A25/A99 (Status der Antwort) vorhanden
1597 fn evaluate_24(&self, _ctx: &EvaluationContext) -> ConditionResult {
1598 // TODO: implement
1599 ConditionResult::Unknown
1600 }
1601
1602 /// [25] Wenn die Veräußerungsform der erzeugenden Marktlokation der Marktprämie zugeordnet ist
1603 fn evaluate_25(&self, _ctx: &EvaluationContext) -> ConditionResult {
1604 // TODO: implement
1605 ConditionResult::Unknown
1606 }
1607
1608 /// [27] Wenn das DE2380 von SG4 DTM+Z01 (Kündigungsfrist des Vertrags) an vierter Stelle ein T oder R enthält
1609 fn evaluate_27(&self, _ctx: &EvaluationContext) -> ConditionResult {
1610 // TODO: implement
1611 ConditionResult::Unknown
1612 }
1613
1614 /// [30] Wenn Antwort auf Aktivierung übermittelt wird
1615 fn evaluate_30(&self, _ctx: &EvaluationContext) -> ConditionResult {
1616 // TODO: implement
1617 ConditionResult::Unknown
1618 }
1619
1620 /// [31] Wenn eine Korrektur erfolgt
1621 fn evaluate_31(&self, ctx: &EvaluationContext) -> ConditionResult {
1622 ctx.external.evaluate("correction_in_progress")
1623 }
1624
1625 /// [32] Wenn mehr als ein SG8 (Referenz auf die Lokationsbündelstruktur) vorhanden
1626 fn evaluate_32(&self, _ctx: &EvaluationContext) -> ConditionResult {
1627 // TODO: implement
1628 ConditionResult::Unknown
1629 }
1630
1631 /// [33] Wenn in einer SG8 SEQ+Z79 im PIA+5 (Erforderliches Produkt) DE7140 ein Produkt-Code genannt ist, der in der Codeliste der Konfigurationen im Kapitel 6 \"Produkte zur Bestellung / Änderung von Date...
1632 fn evaluate_33(&self, ctx: &EvaluationContext) -> ConditionResult {
1633 ctx.external.evaluate("code_list_membership_check")
1634 }
1635
1636 /// [34] Wenn Antwort auf Deaktivierung übermittelt wird
1637 fn evaluate_34(&self, _ctx: &EvaluationContext) -> ConditionResult {
1638 // TODO: implement
1639 ConditionResult::Unknown
1640 }
1641
1642 /// [35] Wenn das DE2380 von SG4 DTM+Z01 (Kündigungsfrist des Vertrags) an vierter Stelle T (Termin) enthält
1643 fn evaluate_35(&self, _ctx: &EvaluationContext) -> ConditionResult {
1644 // TODO: implement
1645 ConditionResult::Unknown
1646 }
1647
1648 /// [36] Wenn in derselben SG8 SEQ+Z79 im PIA+5 (Erforderliches Produkt) DE7140 ein Produkt-Code genannt ist, der in der Codeliste der Konfigurationen im Kapitel 6.1 \"Anmeldung einer Zuordnung des LFN (UTI...
1649 fn evaluate_36(&self, ctx: &EvaluationContext) -> ConditionResult {
1650 ctx.external.evaluate("code_list_membership_check")
1651 }
1652
1653 /// [37] Wenn Anmeldung/ Änderung befristet
1654 fn evaluate_37(&self, ctx: &EvaluationContext) -> ConditionResult {
1655 ctx.external.evaluate("registration_is_time_limited")
1656 }
1657
1658 /// [38] Es sind nur die Code der Produkteigenschaft zu dem in derselben SG8 SEQ+Z79 im PIA+5 (Erforderliches Produkt) DE7140 erlaubt, die in der Codeliste der Konfigurationen im Kapitel 6.1 \"Anmeldung ei...
1659 fn evaluate_38(&self, ctx: &EvaluationContext) -> ConditionResult {
1660 ctx.external.evaluate("code_list_membership_check")
1661 }
1662
1663 /// [39] Wenn in derselben SG8 SEQ+Z79 m PIA+5 (Erforderliches Produkt) DE7140 ein Produkt-Code genannt ist, der in der Codeliste der Konfigurationen im Kapitel 6.1 \"Anmeldung einer Zuordnung des LFN (UTIL...
1664 fn evaluate_39(&self, ctx: &EvaluationContext) -> ConditionResult {
1665 ctx.external.evaluate("code_list_membership_check")
1666 }
1667
1668 /// [40] Es ist nur der Wertebereich erlaubt, der zu dem in derselben SG8 SEQ+Z79 im PIA+5 (Erforderliches Produkt) DE7140 genannten Produkt, das in der Codeliste der Konfigurationen im Kapitel 6.1 \"Anmeld...
1669 fn evaluate_40(&self, ctx: &EvaluationContext) -> ConditionResult {
1670 ctx.external.evaluate("code_list_membership_check")
1671 }
1672
1673 /// [41] Es ist eine Produktpaket-ID aus dem DE1050 von einem SG8 SEQ+Z79 (Erforderliches Produkt) zu nennen
1674 fn evaluate_41(&self, _ctx: &EvaluationContext) -> ConditionResult {
1675 // TODO: implement
1676 ConditionResult::Unknown
1677 }
1678
1679 /// [42] Wenn mehr als ein SG8 SEQ+ZH0 (Priorisierung erforderliches Produktpaket) vorhanden
1680 fn evaluate_42(&self, _ctx: &EvaluationContext) -> ConditionResult {
1681 // TODO: implement
1682 ConditionResult::Unknown
1683 }
1684
1685 /// [43] Wenn in dieser SG4 das STS+E01++A12 / A13 (Status der Antwort) vorhanden
1686 fn evaluate_43(&self, _ctx: &EvaluationContext) -> ConditionResult {
1687 // TODO: implement
1688 ConditionResult::Unknown
1689 }
1690
1691 /// [44] Es ist die Zeitraum-ID vom DE1156 aus einem passenden SG6 RFF+Z49/ Z53 (Verwendungszeitraum der Daten: "Gültige Daten", "Keine Daten") aus der Anfragennachricht aus SG6 RFF+TN DE1154 ((Referenz Vo...
1692 fn evaluate_44(&self, _ctx: &EvaluationContext) -> ConditionResult {
1693 // Hinweis: Zeitraum-ID aus passendem SG6 RFF+Z49/Z53 der Anfragenachricht eintragen — informational data population rule
1694 ConditionResult::True
1695 }
1696
1697 /// [45] Wenn in derselben SG8 das SG10 CCI+Z01++Z82 (Verwendungsumfang: ID der prozessual behandelten Messlokation) vorhanden
1698 fn evaluate_45(&self, _ctx: &EvaluationContext) -> ConditionResult {
1699 // TODO: implement
1700 ConditionResult::Unknown
1701 }
1702
1703 /// [46] Wenn ID für Objekt vergeben wurde
1704 fn evaluate_46(&self, _ctx: &EvaluationContext) -> ConditionResult {
1705 // TODO: implement
1706 ConditionResult::Unknown
1707 }
1708
1709 /// [47] Wenn SG10 CCI+15++Z21 (Summenzeitreihentyp) CAV+DBA/ VZR/ EGS/ LGS/ SLS/ SES/ TLS/ TES/ BIL/ BIP/ BIT/ GAL/ GAP/ GAT/ GEL/ GEP/ GET/ SOL/ SOP/ SOT/ WFL/ WFP/ WFT/ WNL/ WNP/ WNT vorhanden
1710 // REVIEW: Iterates all SG8 instances and their SG10 children looking for CCI with elements[0][0]=="15" and elements[2][0]=="Z21" (Zeitreihentyp), then checks if the same SG10 has a CAV with elements[0][0] in the Summenzeitreihentyp code list. Uses navigator for parent-child group traversal. (medium confidence)
1711 fn evaluate_47(&self, ctx: &EvaluationContext) -> ConditionResult {
1712 const CODES: &[&str] = &[
1713 "DBA", "VZR", "EGS", "LGS", "SLS", "SES", "TLS", "TES", "BIL", "BIP", "BIT", "GAL",
1714 "GAP", "GAT", "GEL", "GEP", "GET", "SOL", "SOP", "SOT", "WFL", "WFP", "WFT", "WNL",
1715 "WNP", "WNT",
1716 ];
1717 let nav = match ctx.navigator {
1718 Some(n) => n,
1719 None => return ConditionResult::Unknown,
1720 };
1721 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
1722 for i in 0..sg8_count {
1723 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
1724 for j in 0..sg10_count {
1725 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
1726 let has_cci_15_z21 = ccis.iter().any(|s| {
1727 s.elements
1728 .first()
1729 .and_then(|e: &Vec<String>| e.first())
1730 .is_some_and(|v: &String| v == "15")
1731 && s.elements
1732 .get(2)
1733 .and_then(|e: &Vec<String>| e.first())
1734 .is_some_and(|v: &String| v == "Z21")
1735 });
1736 if has_cci_15_z21 {
1737 let cavs =
1738 nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
1739 if cavs.iter().any(|s| {
1740 s.elements
1741 .first()
1742 .and_then(|e: &Vec<String>| e.first())
1743 .is_some_and(|v: &String| CODES.contains(&v.as_str()))
1744 }) {
1745 return ConditionResult::True;
1746 }
1747 }
1748 }
1749 }
1750 ConditionResult::False
1751 }
1752
1753 /// [48] Wenn in dieser SG4 das STS+E01++A99 (Status der Antwort: Sonstiges) vorhanden
1754 fn evaluate_48(&self, _ctx: &EvaluationContext) -> ConditionResult {
1755 // TODO: implement
1756 ConditionResult::Unknown
1757 }
1758
1759 /// [49] Wenn in dieser SG4 das STS+E01++E14 (Status der Antwort: Ablehnung Sonstiges) vorhanden
1760 fn evaluate_49(&self, _ctx: &EvaluationContext) -> ConditionResult {
1761 // TODO: implement
1762 ConditionResult::Unknown
1763 }
1764
1765 /// [50] Wenn kein SG8 SEQ+ZE7 (Informative Daten der Tranche) mit derselben Zeitraum-ID im DE1050 auf die gleiche Marktlokation-ID mit dem RFF+Z18 (Marktlokation) referenziert wie dieses SG8 SEQ+Z98 (Infor...
1766 // REVIEW: Collects (Zeitraum-ID from SEQ.elements[1][0], Marktlok-ID from sibling RFF+Z18.elements[0][1]) for all SG8 instances with SEQ+Z98 and SEQ+ZE7. Returns True if any Z98 group has no ZE7 group matching on both values. Uses collect_group_values with instance-index correlation via HashMap, assuming each SG8 has at most one SEQ (guaranteed as entry segment) and the zip ordering is stable. (medium confidence)
1767 fn evaluate_50(&self, ctx: &EvaluationContext) -> ConditionResult {
1768 use std::collections::HashMap;
1769
1770 let seq_quals = ctx.collect_group_values("SEQ", 0, 0, &["SG4", "SG8"]);
1771 let seq_zeitraum = ctx.collect_group_values("SEQ", 1, 0, &["SG4", "SG8"]);
1772 let rff_quals = ctx.collect_group_values("RFF", 0, 0, &["SG4", "SG8"]);
1773 let rff_ids = ctx.collect_group_values("RFF", 0, 1, &["SG4", "SG8"]);
1774
1775 // Build per-instance RFF lookup: instance_idx -> list of (qualifier, id)
1776 let mut rff_by_instance: HashMap<usize, Vec<(String, String)>> = HashMap::new();
1777 for ((idx, q), (_, id)) in rff_quals.iter().zip(rff_ids.iter()) {
1778 rff_by_instance
1779 .entry(*idx)
1780 .or_default()
1781 .push((q.clone(), id.clone()));
1782 }
1783
1784 // Build (zeitraum_id, marktlok_id) for Z98 and ZE7 SG8 instances
1785 let mut seq_zeitraum_map: HashMap<usize, String> = HashMap::new();
1786 for (idx, z) in &seq_zeitraum {
1787 seq_zeitraum_map.insert(*idx, z.clone());
1788 }
1789
1790 let z98_data: Vec<(String, String)> = seq_quals
1791 .iter()
1792 .filter(|(_, q)| q == "Z98")
1793 .map(|(idx, _)| {
1794 let zeitraum = seq_zeitraum_map.get(idx).cloned().unwrap_or_default();
1795 let marktlok = rff_by_instance
1796 .get(idx)
1797 .and_then(|rffs| rffs.iter().find(|(q, _)| q == "Z18"))
1798 .map(|(_, id)| id.clone())
1799 .unwrap_or_default();
1800 (zeitraum, marktlok)
1801 })
1802 .collect();
1803
1804 if z98_data.is_empty() {
1805 return ConditionResult::Unknown;
1806 }
1807
1808 let ze7_data: Vec<(String, String)> = seq_quals
1809 .iter()
1810 .filter(|(_, q)| q == "ZE7")
1811 .map(|(idx, _)| {
1812 let zeitraum = seq_zeitraum_map.get(idx).cloned().unwrap_or_default();
1813 let marktlok = rff_by_instance
1814 .get(idx)
1815 .and_then(|rffs| rffs.iter().find(|(q, _)| q == "Z18"))
1816 .map(|(_, id)| id.clone())
1817 .unwrap_or_default();
1818 (zeitraum, marktlok)
1819 })
1820 .collect();
1821
1822 ConditionResult::from(z98_data.iter().any(|(z98_zeit, z98_lok)| {
1823 !ze7_data
1824 .iter()
1825 .any(|(ze7_zeit, ze7_lok)| ze7_zeit == z98_zeit && ze7_lok == z98_lok)
1826 }))
1827 }
1828
1829 /// [51] Wenn die Marktlokations-ID im SG8 RFF+Z18 derselben SG8 SEQ+Z98 (Informative Daten der Marktlokation) mit derselben Zeitraum-ID im DE1050 nicht auf ein SG8 SEQ+Z78 (Referenz auf die Lokationsbünde...
1830 // REVIEW: Condition is True when no Z98 SG8 (Informative Daten der Marktlokation) references — via matching Zeitraum-ID in SEQ.C286.DE1050 — a Z78 SG8 (Referenz auf Lokationsbündelstruktur) that carries the pauschal bundle code 9992000000018 in RFF+Z31.DE1154. Requires navigator for cross-SG8 Zeitraum-ID correlation. (medium confidence)
1831 fn evaluate_51(&self, ctx: &EvaluationContext) -> ConditionResult {
1832 let nav = match ctx.navigator() {
1833 Some(n) => n,
1834 None => return ConditionResult::Unknown,
1835 };
1836 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
1837 let pauschal_id = "9992000000018";
1838 // Collect Zeitraum-IDs from Z78 SG8s that carry the pauschal RFF+Z31 ID
1839 let mut pauschal_zeitraum_ids: Vec<String> = Vec::new();
1840 for i in 0..sg8_count {
1841 let seqs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
1842 let has_z78 = seqs.iter().any(|s| {
1843 s.elements
1844 .first()
1845 .and_then(|e| e.first())
1846 .is_some_and(|v| v == "Z78")
1847 });
1848 if !has_z78 {
1849 continue;
1850 }
1851 let rffs = nav.find_segments_in_group("RFF", &["SG4", "SG8"], i);
1852 let has_pauschal = rffs.iter().any(|s| {
1853 s.elements
1854 .first()
1855 .and_then(|e| e.first())
1856 .is_some_and(|v| v == "Z31")
1857 && s.elements
1858 .first()
1859 .and_then(|e| e.get(1))
1860 .is_some_and(|v| v.replace(' ', "") == pauschal_id)
1861 });
1862 if has_pauschal {
1863 for seq in &seqs {
1864 if seq
1865 .elements
1866 .first()
1867 .and_then(|e| e.first())
1868 .is_some_and(|v| v == "Z78")
1869 {
1870 if let Some(zid) = seq.elements.get(1).and_then(|e| e.first()) {
1871 if !zid.is_empty() {
1872 pauschal_zeitraum_ids.push(zid.clone());
1873 }
1874 }
1875 }
1876 }
1877 }
1878 }
1879 // For each Z98 SG8, check whether its Zeitraum-ID (SEQ.C286.DE1050) maps to a pauschal Z78
1880 for i in 0..sg8_count {
1881 let seqs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
1882 for seq in &seqs {
1883 if seq
1884 .elements
1885 .first()
1886 .and_then(|e| e.first())
1887 .is_some_and(|v| v == "Z98")
1888 {
1889 let zid = seq
1890 .elements
1891 .get(1)
1892 .and_then(|e| e.first())
1893 .map(|s| s.as_str())
1894 .unwrap_or("");
1895 if !zid.is_empty() && pauschal_zeitraum_ids.iter().any(|z| z == zid) {
1896 // Z98 SG8 references a pauschal Z78 → condition is False
1897 return ConditionResult::False;
1898 }
1899 }
1900 }
1901 }
1902 // No Z98 SG8 references the pauschal bundle → condition is True
1903 ConditionResult::True
1904 }
1905
1906 /// [52] Wenn SG10 CCI+Z07++Z55/ Z56 (Profiltyp: sonstige verbrauchende Marktlokation / sonstige erzeugende Marktlokation) vorhanden
1907 fn evaluate_52(&self, _ctx: &EvaluationContext) -> ConditionResult {
1908 // TODO: implement
1909 ConditionResult::Unknown
1910 }
1911
1912 /// [53] Wenn weitere Präzisierungen als über CCI+Z07 (Profiltyp) möglich sind
1913 fn evaluate_53(&self, _ctx: &EvaluationContext) -> ConditionResult {
1914 // TODO: implement
1915 ConditionResult::Unknown
1916 }
1917
1918 /// [54] Wenn SG8 SEQ+Z01 (Daten der Marktlokation) SG10 CCI+Z30++Z06 (Lieferrichtung: Erzeugung) vorhanden
1919 fn evaluate_54(&self, _ctx: &EvaluationContext) -> ConditionResult {
1920 // TODO: implement
1921 ConditionResult::Unknown
1922 }
1923
1924 /// [55] Wenn in dieser SG4 das STS+E01++A06/ A99 (Status der Antwort) vorhanden
1925 fn evaluate_55(&self, _ctx: &EvaluationContext) -> ConditionResult {
1926 // TODO: implement
1927 ConditionResult::Unknown
1928 }
1929
1930 /// [56] Wenn im STS+E01 im DE9013 (Status der Antwort) ein Antwortcode aus dem Cluster Zustimmung vorhanden ist
1931 fn evaluate_56(&self, _ctx: &EvaluationContext) -> ConditionResult {
1932 // TODO: implement
1933 ConditionResult::Unknown
1934 }
1935
1936 /// [57] Wenn in derselben SG8 das CCI+Z45++ZD9 (Abrechnung findet statt) vorhanden ist
1937 fn evaluate_57(&self, _ctx: &EvaluationContext) -> ConditionResult {
1938 // TODO: implement
1939 ConditionResult::Unknown
1940 }
1941
1942 /// [58] Wenn in diesem CCI das DE3055 mit dem Code 293 vorhanden
1943 fn evaluate_58(&self, _ctx: &EvaluationContext) -> ConditionResult {
1944 // TODO: implement
1945 ConditionResult::Unknown
1946 }
1947
1948 /// [60] Wenn BGM+Z90 (Beendigung der Zuordnung zur Lokation) vorhanden
1949 fn evaluate_60(&self, _ctx: &EvaluationContext) -> ConditionResult {
1950 // TODO: implement
1951 ConditionResult::Unknown
1952 }
1953
1954 /// [61] Wenn BGM+Z89 (Zuordnung zur Lokation) vorhanden
1955 fn evaluate_61(&self, _ctx: &EvaluationContext) -> ConditionResult {
1956 // TODO: implement
1957 ConditionResult::Unknown
1958 }
1959
1960 /// [62] Wenn mehr als eine SG8 SEQ+Z45 (Netznutzungsabrechnungsdaten der Marktlokation), mit derselben Zeitraum-ID im DE1050, mit einer Gruppen-/Artikel-ID im SG8 PIA+Z02 (Gruppenartikel-ID / Artikel-ID), ...
1961 // REVIEW: Iterates SG8 instances within each SG4, finds those with SEQ+Z45 and a non-empty Zeitraum-ID in elements[1][0]. Checks if PIA+Z02 in the same SG8 has a product code (elements[1][0]) beginning with 1-08-1 through 1-08-5. Groups by Zeitraum-ID and checks if any ID appears more than once. Requires navigator for per-instance group segment access; returns Unknown without one. (medium confidence)
1962 fn evaluate_62(&self, ctx: &EvaluationContext) -> ConditionResult {
1963 let nav = match ctx.navigator {
1964 Some(n) => n,
1965 None => return ConditionResult::Unknown,
1966 };
1967 use std::collections::HashMap;
1968 let mut count_by_zid: HashMap<String, u32> = HashMap::new();
1969 let sg4_count = nav.group_instance_count(&["SG4"]);
1970 for sg4_idx in 0..sg4_count {
1971 let sg8_count = nav.child_group_instance_count(&["SG4"], sg4_idx, "SG8");
1972 for sg8_idx in 0..sg8_count {
1973 let seqs =
1974 nav.find_segments_in_child_group("SEQ", &["SG4"], sg4_idx, "SG8", sg8_idx);
1975 let zeitraum_opt = seqs
1976 .iter()
1977 .filter(|s| {
1978 s.elements
1979 .first()
1980 .and_then(|e: &Vec<String>| e.first())
1981 .is_some_and(|v: &String| v == "Z45")
1982 })
1983 .filter_map(|s| {
1984 s.elements
1985 .get(1)
1986 .and_then(|e: &Vec<String>| e.first())
1987 .filter(|v| !v.is_empty())
1988 .cloned()
1989 })
1990 .next();
1991 let Some(zid) = zeitraum_opt else { continue };
1992 let pias =
1993 nav.find_segments_in_child_group("PIA", &["SG4"], sg4_idx, "SG8", sg8_idx);
1994 let has_qualifying_pia = pias.iter().any(|s| {
1995 s.elements
1996 .first()
1997 .and_then(|e: &Vec<String>| e.first())
1998 .is_some_and(|v: &String| v == "Z02")
1999 && s.elements
2000 .get(1)
2001 .and_then(|e: &Vec<String>| e.first())
2002 .map(|code| {
2003 code.starts_with("1-08-1")
2004 || code.starts_with("1-08-2")
2005 || code.starts_with("1-08-3")
2006 || code.starts_with("1-08-4")
2007 || code.starts_with("1-08-5")
2008 })
2009 .unwrap_or(false)
2010 });
2011 if has_qualifying_pia {
2012 *count_by_zid.entry(zid).or_insert(0) += 1;
2013 }
2014 }
2015 }
2016 ConditionResult::from(count_by_zid.values().any(|&c| c > 1))
2017 }
2018
2019 /// [63] Wenn in dieser SG4 das STS+E01++A15/ A99 (Status der Antwort) vorhanden
2020 fn evaluate_63(&self, _ctx: &EvaluationContext) -> ConditionResult {
2021 // TODO: implement
2022 ConditionResult::Unknown
2023 }
2024
2025 /// [64] Wenn mehr als eine SG8 SEQ+ZE1 (Informative Netznutzungsabrechnungsdaten der Marktlokation) mit einer Gruppen-/ Artikel-ID im SG8 PIA+Z02 (Gruppenartikel-ID / Artikel-ID), welche mit 1-08-1/2/3/4/5...
2026 fn evaluate_64(&self, _ctx: &EvaluationContext) -> ConditionResult {
2027 // TODO: implement
2028 ConditionResult::Unknown
2029 }
2030
2031 /// [65] Wenn in derselben SG8 SEQ+ZE1 (Informative Netznutzungsabrechnungsdaten der Marktlokation) eine Gruppen-/Artikel-ID im PIA+Z02 (Gruppenartikel-ID / Artikel-ID), welche mit 1-08-1/2/3/4/5 beginnt, v...
2032 fn evaluate_65(&self, _ctx: &EvaluationContext) -> ConditionResult {
2033 // TODO: implement
2034 ConditionResult::Unknown
2035 }
2036
2037 /// [66] Wenn SG8 SEQ+ZH0 (Priorisierung erforderliches Produktpaket) mehr als einmal vorhanden
2038 fn evaluate_66(&self, _ctx: &EvaluationContext) -> ConditionResult {
2039 // TODO: implement
2040 ConditionResult::Unknown
2041 }
2042
2043 /// [67] Wenn in keinem SG8 SEQ+Z79 (Bestandteil eine Produktpaketes CCI+Z66/CAV+ZH9 (Produkteigenschaft/ Code der Produkteigenschaft) der Code 9991000002933 (Ruhende Marktlokation ausprägen) vorhanden ist.
2044 fn evaluate_67(&self, _ctx: &EvaluationContext) -> ConditionResult {
2045 // TODO: implement
2046 ConditionResult::Unknown
2047 }
2048
2049 /// [68] Wenn SG8 SEQ+ZH0 (Priorisierung erforderliches Produktpaket) mehr als zweimal vorhanden
2050 fn evaluate_68(&self, _ctx: &EvaluationContext) -> ConditionResult {
2051 // TODO: implement
2052 ConditionResult::Unknown
2053 }
2054
2055 /// [69] Wenn SG8 SEQ+ZH0 (Priorisierung erforderliches Produktpaket) mehr als dreimal vorhanden
2056 fn evaluate_69(&self, _ctx: &EvaluationContext) -> ConditionResult {
2057 // TODO: implement
2058 ConditionResult::Unknown
2059 }
2060
2061 /// [70] Wenn SG8 SEQ+ZH0 (Priorisierung erforderliches Produktpaket) fünfmal vorhanden
2062 fn evaluate_70(&self, _ctx: &EvaluationContext) -> ConditionResult {
2063 // TODO: implement
2064 ConditionResult::Unknown
2065 }
2066
2067 /// [71] Wenn Antwort auf Zuordnung übermittelt wird
2068 fn evaluate_71(&self, _ctx: &EvaluationContext) -> ConditionResult {
2069 // TODO: implement
2070 ConditionResult::Unknown
2071 }
2072
2073 /// [72] Wenn Antwort auf Beendigung der Zuordnung übermittelt wird
2074 fn evaluate_72(&self, _ctx: &EvaluationContext) -> ConditionResult {
2075 // TODO: implement
2076 ConditionResult::Unknown
2077 }
2078
2079 /// [73] Wenn in derselben SG8 im PIA DE7140 ein Code aus der Codeliste der Gruppenartikel- und Artikel-ID vorhanden ist, der in der Spalte UTILMD/Preisangabe mit X gekennzeichnet ist
2080 fn evaluate_73(&self, _ctx: &EvaluationContext) -> ConditionResult {
2081 // TODO: implement
2082 ConditionResult::Unknown
2083 }
2084
2085 /// [74] Wenn in der selben SG8 SEQ+Z59 (Produkt-Daten der Marktlokation) das PIA+5 (Produkt-Daten der Marktlokation) vorhanden
2086 fn evaluate_74(&self, _ctx: &EvaluationContext) -> ConditionResult {
2087 // TODO: implement
2088 ConditionResult::Unknown
2089 }
2090
2091 /// [75] Wenn in diesem PIA+5 in DE7140 der Code 9991000000721 (vgl.: Kapitel 4.2. Konfigurationsprodukte Leistungskurvendefinition der Codeliste der Konfigurationen) vorhanden
2092 fn evaluate_75(&self, ctx: &EvaluationContext) -> ConditionResult {
2093 ctx.external.evaluate("code_list_membership_check")
2094 }
2095
2096 /// [76] Wenn Summenzeitreihe auf Ebene des Bilanzierungsgebiet
2097 // REVIEW: SEQ+Z49 is 'Abgerechnete Daten der Bilanzierungsgebietssummenzeitreihe' — the only SEQ code in the reference that explicitly names a Bilanzierungsgebiet-level Summenzeitreihe. Checking its presence is the most direct mapping of the condition text. A broader interpretation involving CAV codes (Bezeichnung der Summenzeitreihe) is possible but those codes are not fully enumerated in the provided reference. (medium confidence)
2098 fn evaluate_76(&self, ctx: &EvaluationContext) -> ConditionResult {
2099 ctx.has_qualifier("SEQ", 0, "Z49")
2100 }
2101
2102 /// [77] Wenn SG8 SEQ+Z03 (Zähleinrichtungsdaten) CAV+Z30 (Identifikation/Nummer des Gerätes) nicht vorhanden
2103 fn evaluate_77(&self, _ctx: &EvaluationContext) -> ConditionResult {
2104 // TODO: implement
2105 ConditionResult::Unknown
2106 }
2107
2108 /// [78] Wenn SG4 STS+7++E02 (Transaktionsgrund: Einzug in Neuanlage) nicht vorhanden
2109 fn evaluate_78(&self, _ctx: &EvaluationContext) -> ConditionResult {
2110 // TODO: implement
2111 ConditionResult::Unknown
2112 }
2113
2114 /// [83] Wenn in dieser SG4 das STS+E01++A08/ A16/ A99 (Status der Antwort) vorhanden
2115 fn evaluate_83(&self, _ctx: &EvaluationContext) -> ConditionResult {
2116 // TODO: implement
2117 ConditionResult::Unknown
2118 }
2119
2120 /// [84] Wenn SG4 STS+E01++A57 (Status der Antwort) vorhanden
2121 fn evaluate_84(&self, _ctx: &EvaluationContext) -> ConditionResult {
2122 // TODO: implement
2123 ConditionResult::Unknown
2124 }
2125
2126 /// [85] Wenn das DE2380 von SG4 DTM+Z01 (Kündigungsfrist des Vertrags) an vierter Stelle M, Q, H oder J enthält
2127 fn evaluate_85(&self, _ctx: &EvaluationContext) -> ConditionResult {
2128 // TODO: implement
2129 ConditionResult::Unknown
2130 }
2131
2132 /// [86] Wenn das RFF+Z50 (Termine der Marktlokation) aus dieser SG6 (Termine der Marktlokation) auf das gleiche SG5 LOC+Z16 (Marktlokation), wie ein RFF+Z18 (Marktlokation) aus einer SG8 SEQ+Z01 (Daten der...
2133 fn evaluate_86(&self, _ctx: &EvaluationContext) -> ConditionResult {
2134 // TODO: implement
2135 ConditionResult::Unknown
2136 }
2137
2138 /// [87] Es ist ein Monatserster 0 Uhr (gem. deutscher Zeit) anzugeben
2139 fn evaluate_87(&self, _ctx: &EvaluationContext) -> ConditionResult {
2140 // TODO: implement
2141 ConditionResult::Unknown
2142 }
2143
2144 /// [88] Wert muss identisch mit DE2380 aus dem SG4 DTM+157 (Änderung zum) sein
2145 fn evaluate_88(&self, _ctx: &EvaluationContext) -> ConditionResult {
2146 // TODO: implement
2147 ConditionResult::Unknown
2148 }
2149
2150 /// [89] Wenn im SG8 SEQ+Z01 (Daten der Marktlokation) mit identischer Zeitraum-ID im DE1050 wie in diesem SG8, das SG10 CCI+++ZA6 (Prognosegrundlage der Marktlokation: Prognose auf Basis von Profilen) CAV+...
2151 // REVIEW: Checks whether any SG8 instance contains an SG10 child with CCI at elements[2][0]=ZA6 and CAV at elements[0][0]=E14. The condition text requires the Zeitraum-ID in DE1050 to match 'this SG8', but a per-group evaluation context is not available in the current API — the Zeitraum-ID cross-reference is therefore not enforced and is instead approximated as a message-wide check. The CCI qualifier position (elements[2][0]) is confirmed by the MIG reference for CCI segments in SG10. (medium confidence)
2152 fn evaluate_89(&self, ctx: &EvaluationContext) -> ConditionResult {
2153 let nav = match ctx.navigator {
2154 Some(n) => n,
2155 None => {
2156 return ctx.filtered_parent_child_has_qualifier(
2157 &["SG4", "SG8"],
2158 "SEQ",
2159 0,
2160 "Z01",
2161 "SG10",
2162 "CCI",
2163 2,
2164 "ZA6",
2165 )
2166 }
2167 };
2168 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
2169 for i in 0..sg8_count {
2170 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
2171 for j in 0..sg10_count {
2172 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
2173 let has_cci_za6 = ccis.iter().any(|s| {
2174 s.elements
2175 .get(2)
2176 .and_then(|e: &Vec<String>| e.first())
2177 .is_some_and(|v: &String| v == "ZA6")
2178 });
2179 if !has_cci_za6 {
2180 continue;
2181 }
2182 let cavs = nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
2183 if cavs.iter().any(|s| {
2184 s.elements
2185 .first()
2186 .and_then(|e: &Vec<String>| e.first())
2187 .is_some_and(|v: &String| v == "E14")
2188 }) {
2189 return ConditionResult::True;
2190 }
2191 }
2192 }
2193 ConditionResult::False
2194 }
2195
2196 /// [90] Wenn SG10 CCI+++ZA6 (Prognosegrundlage der Marktlokation: Prognose auf Basis von Profilen) einmal mit CAV+E14 (TLP/TEP) und einmal mit CAV+E02 (SLP/SEP) in dieser SG8 vorhanden
2197 // REVIEW: Within each SG8, iterates all SG10 child instances. For each SG10 that has a CCI with elements[2][0]=ZA6, checks the CAV elements[0][0] value. Tracks whether E14 and E02 have both been seen within the same SG8. Returns True when both are found in a single SG8, satisfying the requirement that both Prognosegrundlage options appear 'in dieser SG8'. (medium confidence)
2198 fn evaluate_90(&self, ctx: &EvaluationContext) -> ConditionResult {
2199 let nav = match ctx.navigator {
2200 Some(n) => n,
2201 None => return ConditionResult::Unknown,
2202 };
2203 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
2204 for i in 0..sg8_count {
2205 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
2206 let mut has_za6_e14 = false;
2207 let mut has_za6_e02 = false;
2208 for j in 0..sg10_count {
2209 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
2210 let has_cci_za6 = ccis.iter().any(|s| {
2211 s.elements
2212 .get(2)
2213 .and_then(|e: &Vec<String>| e.first())
2214 .is_some_and(|v: &String| v == "ZA6")
2215 });
2216 if !has_cci_za6 {
2217 continue;
2218 }
2219 let cavs = nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
2220 for cav in &cavs {
2221 if let Some(code) = cav.elements.first().and_then(|e: &Vec<String>| e.first()) {
2222 if code == "E14" {
2223 has_za6_e14 = true;
2224 }
2225 if code == "E02" {
2226 has_za6_e02 = true;
2227 }
2228 }
2229 }
2230 }
2231 if has_za6_e14 && has_za6_e02 {
2232 return ConditionResult::True;
2233 }
2234 }
2235 ConditionResult::False
2236 }
2237
2238 /// [91] Wenn nicht SG10 CCI+++ZA6 (Prognosegrundlage der Marktlokation: Prognose auf Basis von Profilen) einmal mit CAV+E14 (TLP/ TEP) und einmal mit CAV+E02 (SLP/SEP) in dieser SG8 vorhanden
2239 // REVIEW: Logical negation of condition 90. Condition 91 is explicitly defined as 'Wenn NICHT (CCI+++ZA6 einmal mit CAV+E14 und einmal mit CAV+E02 in dieser SG8 vorhanden)', which is the exact complement of condition 90. Preserving Unknown propagation handles the no-navigator fallback case correctly. (medium confidence)
2240 fn evaluate_91(&self, ctx: &EvaluationContext) -> ConditionResult {
2241 match self.evaluate_90(ctx) {
2242 ConditionResult::True => ConditionResult::False,
2243 ConditionResult::False => ConditionResult::True,
2244 ConditionResult::Unknown => ConditionResult::Unknown,
2245 }
2246 }
2247
2248 /// [92] Wenn Wert innerhalb SG bzw. Segment geändert wird
2249 fn evaluate_92(&self, _ctx: &EvaluationContext) -> ConditionResult {
2250 // TODO: implement
2251 ConditionResult::Unknown
2252 }
2253
2254 /// [93] Erlaubte Codes aus der PRICAT BGM+Z32 (Preisblatt Messstellenbetrieb) des verantwortlichen MSB
2255 fn evaluate_93(&self, _ctx: &EvaluationContext) -> ConditionResult {
2256 // TODO: implement
2257 ConditionResult::Unknown
2258 }
2259
2260 /// [94] Wenn ein Segment innerhalb der SG vorhanden
2261 fn evaluate_94(&self, _ctx: &EvaluationContext) -> ConditionResult {
2262 // TODO: implement
2263 ConditionResult::Unknown
2264 }
2265
2266 /// [95] Wenn in derselben SG10 das CCI+Z17 (Stromverbrauchsart) CAV+ZE5 (E-Mobilität) vorhanden
2267 fn evaluate_95(&self, _ctx: &EvaluationContext) -> ConditionResult {
2268 // TODO: implement
2269 ConditionResult::Unknown
2270 }
2271
2272 /// [96] Wenn SG4 STS+7++xxx+ZAP (Transaktionsgrundergänzung ruhende Marktlokation) vorhanden
2273 fn evaluate_96(&self, _ctx: &EvaluationContext) -> ConditionResult {
2274 // TODO: implement
2275 ConditionResult::Unknown
2276 }
2277
2278 /// [97] Wenn in einem SG10 CAV+ZH9 DE7110 der Code der Produkteigenschaft (Wertebereich) 9991000002420 (Marktprämie) vorhanden ist
2279 fn evaluate_97(&self, _ctx: &EvaluationContext) -> ConditionResult {
2280 // TODO: implement
2281 ConditionResult::Unknown
2282 }
2283
2284 /// [98] Wenn MP-ID in SG2 NAD+MS (Nachrichtenabsender) in der Rolle NB
2285 fn evaluate_98(&self, ctx: &EvaluationContext) -> ConditionResult {
2286 ctx.external.evaluate("sender_role_check")
2287 }
2288
2289 /// [99] Wenn MP-ID in SG2 NAD+MS (Nachrichtenabsender) in der Rolle ÜNB
2290 fn evaluate_99(&self, ctx: &EvaluationContext) -> ConditionResult {
2291 ctx.external.evaluate("sender_role_check")
2292 }
2293
2294 /// [100] Wenn SG10 CAV+TLS/ TES/ BIT/ GET/ GAT/ SOT/ WNT/ WFT/ WAT vorhanden
2295 fn evaluate_100(&self, _ctx: &EvaluationContext) -> ConditionResult {
2296 // TODO: implement
2297 ConditionResult::Unknown
2298 }
2299
2300 /// [101] Wenn SG10 CCI+++ZA6 (Prognosegrundlage der Marktlokation: Prognose auf Basis von Profilen) CAV+E14/ Z36 (TLP/ TEP/ TEP mit Ref.messung) in dieser SG8 vorhanden
2301 fn evaluate_101(&self, _ctx: &EvaluationContext) -> ConditionResult {
2302 // TODO: implement
2303 ConditionResult::Unknown
2304 }
2305
2306 /// [102] Wenn SG10 CCI+++ZA6 (Prognosegrundlage der Marktlokation: Prognose auf Basis von Profilen) CAV+Z36 (TEP mit Ref.messung) in dieser SG8 vorhanden
2307 fn evaluate_102(&self, _ctx: &EvaluationContext) -> ConditionResult {
2308 // TODO: implement
2309 ConditionResult::Unknown
2310 }
2311
2312 /// [103] Wenn SG9 QTY+265 (Arbeit / Leistung für tagesparameterabhängig e Marktlokation: Veranschlagte Jahresmenge Gesamt) in dieser SG8 vorhanden
2313 fn evaluate_103(&self, _ctx: &EvaluationContext) -> ConditionResult {
2314 // TODO: implement
2315 ConditionResult::Unknown
2316 }
2317
2318 /// [104] Wenn SG9 QTY+Z08 (Arbeit / Leistung für tagesparameterabhängige Marktlokation: angepasste elektrische Arbeit nach Anhang D) in dieser SG8 vorhanden
2319 fn evaluate_104(&self, _ctx: &EvaluationContext) -> ConditionResult {
2320 // TODO: implement
2321 ConditionResult::Unknown
2322 }
2323
2324 /// [105] Wenn SG9 QTY+Z10 (Arbeit / Leistung für tagesparameterabhängige Marktlokation: Leistung der Marktlokation) in dieser SG8 vorhanden
2325 fn evaluate_105(&self, _ctx: &EvaluationContext) -> ConditionResult {
2326 // TODO: implement
2327 ConditionResult::Unknown
2328 }
2329
2330 /// [106] Wenn in dieser SG8 SEQ+Z01 SG10 CCI+++ZA6 (Prognosegrundlage der Marktlokation: Prognose auf Basis von Profilen) CAV+E02 (SLP/SEP) vorhanden
2331 fn evaluate_106(&self, _ctx: &EvaluationContext) -> ConditionResult {
2332 // TODO: implement
2333 ConditionResult::Unknown
2334 }
2335
2336 /// [107] Wenn in derselben SG8 das SG10 CAV+SLS/ SES/ BIP/ GEP/ GAP/ SOP/ WNP/ WFP/ WAP vorhanden
2337 fn evaluate_107(&self, _ctx: &EvaluationContext) -> ConditionResult {
2338 // TODO: implement
2339 ConditionResult::Unknown
2340 }
2341
2342 /// [108] Wenn in derselben SG8 (Netznutzungsabrechnungsdaten der Marktlokation) eine Gruppen-/Artikel-ID im PIA+Z02 (Gruppenartikel-ID / Artikel-ID), welche mit 1-08-1/2/3/4/5 beginnt, vorhanden
2343 fn evaluate_108(&self, _ctx: &EvaluationContext) -> ConditionResult {
2344 // TODO: implement
2345 ConditionResult::Unknown
2346 }
2347
2348 /// [110] Wenn SG10 CAV+LGS/ EGS/ BIL/ GEL/ GAL/ SOL/ WNL/ WFL / WAL vorhanden
2349 fn evaluate_110(&self, _ctx: &EvaluationContext) -> ConditionResult {
2350 // TODO: implement
2351 ConditionResult::Unknown
2352 }
2353
2354 /// [111] Wenn in derselben SG8 SEQ+Z59 (Produkt-Daten der Marktlokation) das PIA+5 (Produkt-Daten der Marktlokation) nicht vorhanden
2355 fn evaluate_111(&self, ctx: &EvaluationContext) -> ConditionResult {
2356 ctx.any_group_has_qualifier_without("SEQ", 0, "Z59", "PIA", 0, "5", &["SG4", "SG8"])
2357 }
2358
2359 /// [112] Wenn in derselben SG8 SEQ+Z59 (Produkt-Daten der Marktlokation) das SG10 CCI+11 (Details zum Produkt der Marktlokation) nicht vorhanden
2360 fn evaluate_112(&self, ctx: &EvaluationContext) -> ConditionResult {
2361 let result = ctx.filtered_parent_child_has_qualifier(
2362 &["SG4", "SG8"],
2363 "SEQ",
2364 0,
2365 "Z59",
2366 "SG10",
2367 "CCI",
2368 0,
2369 "11",
2370 );
2371 match result {
2372 ConditionResult::True => ConditionResult::False,
2373 ConditionResult::False => ConditionResult::True,
2374 ConditionResult::Unknown => ConditionResult::Unknown,
2375 }
2376 }
2377
2378 /// [113] Wenn es sich um eine Antwort auf die Bestellung einer Zählzeit handelt
2379 fn evaluate_113(&self, _ctx: &EvaluationContext) -> ConditionResult {
2380 // TODO: implement
2381 ConditionResult::Unknown
2382 }
2383
2384 /// [114] Wenn das SG10 CCI+E03 (Spannungsebene der Marktlokation) CAV E06 (Niederspannung) in dieser SG vorhanden
2385 // REVIEW: Checks that CCI+E03 (Spannungsebene, elements[0][0]='E03' per AHB hint) and CAV+E06 (Niederspannung, elements[0][0]='E06') co-occur in the same SG10 child instance of some SG8. Uses navigator to iterate SG8→SG10 pairs and verify both segments within the same SG10 instance. Confidence medium because navigator availability is runtime-dependent and fallback is message-wide only. (medium confidence)
2386 fn evaluate_114(&self, ctx: &EvaluationContext) -> ConditionResult {
2387 let nav = match ctx.navigator {
2388 Some(n) => n,
2389 None => {
2390 return match (
2391 ctx.has_qualifier("CCI", 0, "E03"),
2392 ctx.has_qualifier("CAV", 0, "E06"),
2393 ) {
2394 (ConditionResult::True, ConditionResult::True) => ConditionResult::True,
2395 (ConditionResult::False, _) | (_, ConditionResult::False) => {
2396 ConditionResult::False
2397 }
2398 _ => ConditionResult::Unknown,
2399 };
2400 }
2401 };
2402 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
2403 for i in 0..sg8_count {
2404 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
2405 for j in 0..sg10_count {
2406 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
2407 let has_cci_e03 = ccis.iter().any(|s| {
2408 s.elements
2409 .first()
2410 .and_then(|e: &Vec<String>| e.first())
2411 .is_some_and(|v: &String| v == "E03")
2412 });
2413 if has_cci_e03 {
2414 let cavs =
2415 nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
2416 if cavs.iter().any(|s| {
2417 s.elements
2418 .first()
2419 .and_then(|e: &Vec<String>| e.first())
2420 .is_some_and(|v: &String| v == "E06")
2421 }) {
2422 return ConditionResult::True;
2423 }
2424 }
2425 }
2426 }
2427 ConditionResult::False
2428 }
2429
2430 /// [115] Wenn das SG10 CCI+E03 (Spannungsebene der Marktlokation) CAV E05 (Mittelspannung) in dieser SG vorhanden
2431 fn evaluate_115(&self, _ctx: &EvaluationContext) -> ConditionResult {
2432 // TODO: implement
2433 ConditionResult::Unknown
2434 }
2435
2436 /// [116] Wenn das SG10 CCI+E03 (Spannungsebene der Marktlokation) CAV E04 (Hochspannung) in dieser SG vorhanden
2437 fn evaluate_116(&self, _ctx: &EvaluationContext) -> ConditionResult {
2438 // TODO: implement
2439 ConditionResult::Unknown
2440 }
2441
2442 /// [117] Wenn das RFF+Z18 (Marktlokation) aus dieser SG8 auf das gleiche SG5 LOC+Z16 (Marktlokation), wie ein RFF+Z18 (Marktlokation) aus einer SG8 SEQ+Z01 (Daten der Marktlokation), in dem SG10 CCI+++ZA6 (...
2443 // REVIEW: Full condition requires: (1) current SG8 has RFF+Z18=X, (2) another SG8 with SEQ+Z01 also has RFF+Z18=X, (3) that SG8 has SG10 with CCI elements[2][0]='ZA6' AND CAV elements[0][0]='E14'. Implementation simplifies to checking whether any SG8 has SG10 with both CCI+++ZA6 and CAV+E14 co-occurring in the same SG10 instance. The cross-SG RFF+Z18 value correlation and SEQ+Z01 parent check are omitted because the navigator API only exposes child-group segments (SG10 within SG8), not SG8's own entry segments. Medium confidence due to this structural limitation. (medium confidence)
2444 fn evaluate_117(&self, ctx: &EvaluationContext) -> ConditionResult {
2445 let nav = match ctx.navigator {
2446 Some(n) => n,
2447 None => return ConditionResult::Unknown,
2448 };
2449 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
2450 for i in 0..sg8_count {
2451 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
2452 for j in 0..sg10_count {
2453 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
2454 let has_cci_za6 = ccis.iter().any(|s| {
2455 s.elements
2456 .get(2)
2457 .and_then(|e: &Vec<String>| e.first())
2458 .is_some_and(|v: &String| v == "ZA6")
2459 });
2460 if has_cci_za6 {
2461 let cavs =
2462 nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
2463 if cavs.iter().any(|s| {
2464 s.elements
2465 .first()
2466 .and_then(|e: &Vec<String>| e.first())
2467 .is_some_and(|v: &String| v == "E14")
2468 }) {
2469 return ConditionResult::True;
2470 }
2471 }
2472 }
2473 }
2474 ConditionResult::False
2475 }
2476
2477 /// [118] Wenn in dieser SG8 SEQ+Z98 SG10 CCI+++ZA6 (Prognosegrundlage der Marktlokation: Prognose auf Basis von Profilen) CAV+E02 (SLP/ SEP) vorhanden
2478 fn evaluate_118(&self, ctx: &EvaluationContext) -> ConditionResult {
2479 let has_cci = ctx.filtered_parent_child_has_qualifier(
2480 &["SG4", "SG8"],
2481 "SEQ",
2482 0,
2483 "Z98",
2484 "SG10",
2485 "CCI",
2486 2,
2487 "ZA6",
2488 );
2489 if has_cci != ConditionResult::True {
2490 return has_cci;
2491 }
2492 ctx.filtered_parent_child_has_qualifier(
2493 &["SG4", "SG8"],
2494 "SEQ",
2495 0,
2496 "Z98",
2497 "SG10",
2498 "CAV",
2499 0,
2500 "E02",
2501 )
2502 }
2503
2504 /// [119] Wenn in der SG8 SEQ+Z01/ Z98 SG10 CCI+++ZA6 (Prognosegrundlage der Marktlokation: Prognose auf Basis von Profilen) CAV+E02 (SLP/SEP) vorhanden
2505 fn evaluate_119(&self, _ctx: &EvaluationContext) -> ConditionResult {
2506 // TODO: implement
2507 ConditionResult::Unknown
2508 }
2509
2510 /// [120] Wenn von NB Abtretungserklärung benötigt wird
2511 fn evaluate_120(&self, _ctx: &EvaluationContext) -> ConditionResult {
2512 // TODO: implement
2513 ConditionResult::Unknown
2514 }
2515
2516 /// [121] Wenn in dem SEQ+Z03/ ZF5 (Zähleinrichtungsdaten) das SG8 RFF+Z14 (Referenz auf das Smartmeter-Gateway) nicht vorhanden
2517 fn evaluate_121(&self, ctx: &EvaluationContext) -> ConditionResult {
2518 let z03 =
2519 ctx.any_group_has_qualifier_without("SEQ", 0, "Z03", "RFF", 0, "Z14", &["SG4", "SG8"]);
2520 if z03 == ConditionResult::True {
2521 return ConditionResult::True;
2522 }
2523 ctx.any_group_has_qualifier_without("SEQ", 0, "ZF5", "RFF", 0, "Z14", &["SG4", "SG8"])
2524 }
2525
2526 /// [122] Wenn in dieser SG8 SEQ+Z98 SG10 CCI+++E03 (Spannungsebene der Marktlokation) CAV+E06 (Niederspannung) vorhanden
2527 // REVIEW: Uses filtered_parent_child_has_qualifier to find SG8 instances where SEQ+Z98 has an SG10 child with CCI at elements[2]='E03' (Spannungsebene der Marktlokation). Then confirms CAV+E06 (Niederspannung) exists in an SG8 group. The CAV check is group-scoped rather than strictly same-SG10-instance because the navigator API does not directly expose parent-group (SG8) segment access alongside child-group (SG10) checks in one call. (medium confidence)
2528 fn evaluate_122(&self, ctx: &EvaluationContext) -> ConditionResult {
2529 // Check: in SG8 with SEQ+Z98, SG10 child has CCI+++E03 (Spannungsebene, elements[2][0]="E03")
2530 let has_cci_e03 = ctx.filtered_parent_child_has_qualifier(
2531 &["SG4", "SG8"],
2532 "SEQ",
2533 0,
2534 "Z98",
2535 "SG10",
2536 "CCI",
2537 2,
2538 "E03",
2539 );
2540 if has_cci_e03 != ConditionResult::True {
2541 return has_cci_e03;
2542 }
2543 // Also verify CAV+E06 (Niederspannung, elements[0][0]="E06") exists in the same SG8 scope
2544 ctx.any_group_has_qualifier("CAV", 0, "E06", &["SG4", "SG8"])
2545 }
2546
2547 /// [123] Wenn noch mindestens eine weitere SG8 SEQ+Z20 (OBIS-Daten der Zähleinrichtung Smartmeter-Gateway) mit dem SG8 RFF+MG (Gerätenummer des Zählers) auf die gleiche Identifikation/Nummer des Gerätes...
2548 // REVIEW: Scans segments linearly to collect RFF+MG device IDs from each SG8 group with SEQ+Z20 (OBIS-Daten der Zähleinrichtung/Smartmeter-Gateway). A new SEQ starts a new SG8 context; RFF+MG within that context records the device number. Returns True if any device ID appears in 2+ different SG8 groups (indicating multiple OBIS datasets reference the same device). Linear scan is used because the navigator API does not expose a direct method to retrieve segments within a parent SG8 instance by absolute index. (medium confidence)
2549 fn evaluate_123(&self, ctx: &EvaluationContext) -> ConditionResult {
2550 struct Sg8Z20Entry {
2551 mg_id: Option<String>,
2552 }
2553 let mut entries: Vec<Sg8Z20Entry> = Vec::new();
2554 let mut current: Option<Sg8Z20Entry> = None;
2555 for seg in ctx.segments {
2556 match seg.id.as_str() {
2557 "SEQ" => {
2558 if let Some(entry) = current.take() {
2559 entries.push(entry);
2560 }
2561 if seg
2562 .elements
2563 .first()
2564 .and_then(|e: &Vec<String>| e.first())
2565 .is_some_and(|v: &String| v == "Z20")
2566 {
2567 current = Some(Sg8Z20Entry { mg_id: None });
2568 }
2569 }
2570 "RFF" if current.is_some() => {
2571 if seg
2572 .elements
2573 .first()
2574 .and_then(|e: &Vec<String>| e.first())
2575 .is_some_and(|v: &String| v == "MG")
2576 {
2577 if let Some(ref mut entry) = current {
2578 if entry.mg_id.is_none() {
2579 entry.mg_id = seg.elements.first().and_then(|e| e.get(1)).cloned();
2580 }
2581 }
2582 }
2583 }
2584 _ => {}
2585 }
2586 }
2587 if let Some(entry) = current {
2588 entries.push(entry);
2589 }
2590 let ids: Vec<&str> = entries
2591 .iter()
2592 .filter_map(|e| e.mg_id.as_deref().filter(|s| !s.is_empty()))
2593 .collect();
2594 for i in 0..ids.len() {
2595 for j in (i + 1)..ids.len() {
2596 if ids[i] == ids[j] {
2597 return ConditionResult::True;
2598 }
2599 }
2600 }
2601 ConditionResult::False
2602 }
2603
2604 /// [124] Wenn noch mindestens eine weitere SG8 SEQ+Z20 (OBIS-Daten der Zähleinrichtung Smartmeter-Gateway) mit derselben Zeitraum-ID aus dem DE1050 dieser SG8 mit dem SG8 RFF+MG (Gerätenummer des Zählers...
2605 // REVIEW: Extends condition 123 by also requiring that the matching SG8 groups share the same Zeitraum-ID (from SEQ.elements[1][0] = DE1050 / C286.d1050). Both the Zeitraum-ID and the RFF+MG device number must be identical across at least two different SG8 instances with SEQ+Z20 for the condition to be True. (medium confidence)
2606 fn evaluate_124(&self, ctx: &EvaluationContext) -> ConditionResult {
2607 struct Sg8Z20Entry {
2608 zeitraum_id: String,
2609 mg_id: Option<String>,
2610 }
2611 let mut entries: Vec<Sg8Z20Entry> = Vec::new();
2612 let mut current: Option<Sg8Z20Entry> = None;
2613 for seg in ctx.segments {
2614 match seg.id.as_str() {
2615 "SEQ" => {
2616 if let Some(entry) = current.take() {
2617 entries.push(entry);
2618 }
2619 if seg
2620 .elements
2621 .first()
2622 .and_then(|e: &Vec<String>| e.first())
2623 .is_some_and(|v: &String| v == "Z20")
2624 {
2625 let zeitraum_id = seg
2626 .elements
2627 .get(1)
2628 .and_then(|e: &Vec<String>| e.first())
2629 .cloned()
2630 .unwrap_or_default();
2631 current = Some(Sg8Z20Entry {
2632 zeitraum_id,
2633 mg_id: None,
2634 });
2635 }
2636 }
2637 "RFF" if current.is_some() => {
2638 if seg
2639 .elements
2640 .first()
2641 .and_then(|e: &Vec<String>| e.first())
2642 .is_some_and(|v: &String| v == "MG")
2643 {
2644 if let Some(ref mut entry) = current {
2645 if entry.mg_id.is_none() {
2646 entry.mg_id = seg.elements.first().and_then(|e| e.get(1)).cloned();
2647 }
2648 }
2649 }
2650 }
2651 _ => {}
2652 }
2653 }
2654 if let Some(entry) = current {
2655 entries.push(entry);
2656 }
2657 for i in 0..entries.len() {
2658 for j in (i + 1)..entries.len() {
2659 let ei = &entries[i];
2660 let ej = &entries[j];
2661 if !ei.zeitraum_id.is_empty()
2662 && ei.zeitraum_id == ej.zeitraum_id
2663 && ei.mg_id.is_some()
2664 && !ei.mg_id.as_deref().unwrap_or("").is_empty()
2665 && ei.mg_id == ej.mg_id
2666 {
2667 return ConditionResult::True;
2668 }
2669 }
2670 }
2671 ConditionResult::False
2672 }
2673
2674 /// [125] Wenn in derselben SG8 SEQ+Z76/ ZC5/ ZC6 (Messstellenbetriebsabrechnungsdaten der Marktlokation) im DE4347 des PIA Z02 (Gruppenartikel-ID / Artikel-ID) vorhanden
2675 fn evaluate_125(&self, _ctx: &EvaluationContext) -> ConditionResult {
2676 // TODO: implement
2677 ConditionResult::Unknown
2678 }
2679
2680 /// [126] Es ist der Wert einzutragen, der sich aus der Wiederholungshäufigkeit des SG6 RFF+Z49/ Z53 (Verwendungszeitraum der Daten: Gültige Daten/ Keine Daten) ergibt. Bedeutet: Das erste SG6 RFF+Z49/ Z53...
2681 fn evaluate_126(&self, _ctx: &EvaluationContext) -> ConditionResult {
2682 // TODO: implement
2683 ConditionResult::Unknown
2684 }
2685
2686 /// [127] Es ist der Wert einzutragen, der sich aus der Wiederholungshäufigkeit des SG6 RFF+Z48/ Z55 (Verwendungszeitraum der Daten: Erwartete Daten/ Keine Daten erwartet) ergibt. Bedeutet: Das erste SG6 R...
2687 fn evaluate_127(&self, _ctx: &EvaluationContext) -> ConditionResult {
2688 // TODO: implement
2689 ConditionResult::Unknown
2690 }
2691
2692 /// [128] Es ist der Wert einzutragen, der sich aus der Wiederholungshäufigkeit des SG6 RFF+Z47/ Z54 (Verwendungszeitraum der Daten: Im System vorhandene Daten/ Im System keine Daten vorhanden) ergibt. Bede...
2693 fn evaluate_128(&self, _ctx: &EvaluationContext) -> ConditionResult {
2694 // TODO: implement
2695 ConditionResult::Unknown
2696 }
2697
2698 /// [129] Innerhalb eines SG4 IDE müssen alle DE3225 der SG5 LOC+Z16 (Marktlokation) den identischen Wert enthalten
2699 fn evaluate_129(&self, _ctx: &EvaluationContext) -> ConditionResult {
2700 // TODO: implement
2701 ConditionResult::Unknown
2702 }
2703
2704 /// [130] Wenn an Messlokation vorhanden
2705 fn evaluate_130(&self, _ctx: &EvaluationContext) -> ConditionResult {
2706 // TODO: implement
2707 ConditionResult::Unknown
2708 }
2709
2710 /// [131] Wenn dieses DTM+Z25 (Verwendung der Daten ab) im SG6 RFF (Verwendungszeitraum der Daten) mit der Zeitraum ID \"1\" im DE1156 gekennzeichnet ist, muss das Datum in diesem DE2380 der direkt auf DTM+1...
2711 fn evaluate_131(&self, _ctx: &EvaluationContext) -> ConditionResult {
2712 // TODO: implement
2713 ConditionResult::Unknown
2714 }
2715
2716 /// [132] Wenn dieses DTM+Z25 (Verwendung der Daten ab) im SG6 RFF (Verwendungszeitraum der Daten) mit der Zeitraum ID "1" im DE1156 gekennzeichnet ist, muss das Datum in diesem DE2380 der direkt auf DTM+137...
2717 // REVIEW: Validates that when RFF in SG6 has Zeitraum-ID '1' (elements[0][2] = DE1156), the DTM+Z25 date must equal the day immediately following DTM+137 (Nachrichtendatum) at 00:00. Parses the YYYYMMDD portion of DTM+137, computes next calendar day with correct month/year rollover, then checks that DTM+Z25's first 12 characters match YYYYMMDDHHMM with HHMM=0000. Note: German timezone offset (CET/CEST) validation is not performed — this checks the stored datetime value directly, which is the common encoding in EDIFACT 303 format for this use case. (medium confidence)
2718 fn evaluate_132(&self, ctx: &EvaluationContext) -> ConditionResult {
2719 // Condition applies only when RFF in SG6 has Zeitraum-ID "1" in DE1156 (elements[0][2])
2720 let has_zeitraum_id_1 = ctx.find_segments("RFF").iter().any(|s| {
2721 s.elements
2722 .first()
2723 .and_then(|e| e.get(2))
2724 .is_some_and(|v: &String| v == "1")
2725 });
2726 if !has_zeitraum_id_1 {
2727 return ConditionResult::False;
2728 }
2729 // Get message date from DTM+137 (format 303: CCYYMMDDHHmm...)
2730 let msg_date_str = match ctx
2731 .find_segments_with_qualifier("DTM", 0, "137")
2732 .into_iter()
2733 .next()
2734 {
2735 Some(seg) => match seg.elements.first().and_then(|e| e.get(1)) {
2736 Some(v) if v.len() >= 8 => v.clone(),
2737 _ => return ConditionResult::Unknown,
2738 },
2739 None => return ConditionResult::Unknown,
2740 };
2741 // Get DTM+Z25 (Verwendung der Daten ab) value
2742 let usage_date_str = match ctx
2743 .find_segments_with_qualifier("DTM", 0, "Z25")
2744 .into_iter()
2745 .next()
2746 {
2747 Some(seg) => match seg.elements.first().and_then(|e| e.get(1)) {
2748 Some(v) if v.len() >= 12 => v.clone(),
2749 _ => return ConditionResult::Unknown,
2750 },
2751 None => return ConditionResult::Unknown,
2752 };
2753 // Parse YYYYMMDD from DTM+137 value
2754 let year: u32 = match msg_date_str[..4].parse() {
2755 Ok(v) => v,
2756 Err(_) => return ConditionResult::Unknown,
2757 };
2758 let month: u32 = match msg_date_str[4..6].parse() {
2759 Ok(v) => v,
2760 Err(_) => return ConditionResult::Unknown,
2761 };
2762 let day: u32 = match msg_date_str[6..8].parse() {
2763 Ok(v) => v,
2764 Err(_) => return ConditionResult::Unknown,
2765 };
2766 let days_in_month: u32 = match month {
2767 1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
2768 4 | 6 | 9 | 11 => 30,
2769 2 => {
2770 if year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) {
2771 29
2772 } else {
2773 28
2774 }
2775 }
2776 _ => return ConditionResult::Unknown,
2777 };
2778 let (next_year, next_month, next_day): (u32, u32, u32) = if day >= days_in_month {
2779 if month == 12 {
2780 (year + 1, 1, 1)
2781 } else {
2782 (year, month + 1, 1)
2783 }
2784 } else {
2785 (year, month, day + 1)
2786 };
2787 // Expected DTM+Z25: next day at 00:00 — format 303 prefix YYYYMMDDHHMM = 12 chars
2788 let expected_prefix = format!("{:04}{:02}{:02}0000", next_year, next_month, next_day);
2789 let actual_len = usage_date_str.len().min(12);
2790 let actual_prefix = &usage_date_str[..actual_len];
2791 ConditionResult::from(actual_prefix == expected_prefix.as_str())
2792 }
2793
2794 /// [133] Wenn an der übermittelten Marktlokation / Messlokation vorhanden
2795 fn evaluate_133(&self, _ctx: &EvaluationContext) -> ConditionResult {
2796 // TODO: implement
2797 ConditionResult::Unknown
2798 }
2799
2800 /// [134] Wenn dieses DTM+Z25 (Verwendung der Daten ab) nicht im SG6 RFF+Z48/ Z55 (Verwendungszeitraum der Daten: Erwartete Daten/ Keine Daten erwartet) mit der Zeitraum ID "1" im DE1156 ist, muss das Datum ...
2801 // REVIEW: Validates time-slice continuity for Z48/Z55 (Erwartete Daten/Keine Daten erwartet) SG6 groups: every slice with Zeitraum-ID > 1 must have its DTM+Z25 (start date) equal to the DTM+Z26 (end date) of the preceding slice. Zeitraum-ID is in RFF.C506.DE1156 = elements[0][2]. Requires navigator for per-SG6-instance DTM extraction. (medium confidence)
2802 fn evaluate_134(&self, ctx: &EvaluationContext) -> ConditionResult {
2803 let nav = match ctx.navigator() {
2804 Some(n) => n,
2805 None => return ConditionResult::Unknown,
2806 };
2807 let sg6_count = nav.group_instance_count(&["SG4", "SG6"]);
2808 // Collect (zeitraum_id, dtm_z25_value, dtm_z26_value) for every Z48/Z55 SG6
2809 let mut slices: Vec<(u32, Option<String>, Option<String>)> = Vec::new();
2810 for i in 0..sg6_count {
2811 let rffs = nav.find_segments_in_group("RFF", &["SG4", "SG6"], i);
2812 // RFF C506: [0][0]=qualifier, [0][1]=ref-id, [0][2]=Zeitraum-ID
2813 let maybe_zid = rffs.iter().find_map(|s| {
2814 let qual = s
2815 .elements
2816 .first()
2817 .and_then(|e| e.first())
2818 .map(|v| v.as_str())?;
2819 if qual == "Z48" || qual == "Z55" {
2820 s.elements
2821 .first()
2822 .and_then(|e| e.get(2))
2823 .and_then(|v| v.parse::<u32>().ok())
2824 } else {
2825 None
2826 }
2827 });
2828 if let Some(zid) = maybe_zid {
2829 let dtms = nav.find_segments_in_group("DTM", &["SG4", "SG6"], i);
2830 let z25 = dtms.iter().find_map(|s| {
2831 if s.elements
2832 .first()
2833 .and_then(|e| e.first())
2834 .map(|v| v.as_str())
2835 == Some("Z25")
2836 {
2837 s.elements.first().and_then(|e| e.get(1)).cloned()
2838 } else {
2839 None
2840 }
2841 });
2842 let z26 = dtms.iter().find_map(|s| {
2843 if s.elements
2844 .first()
2845 .and_then(|e| e.first())
2846 .map(|v| v.as_str())
2847 == Some("Z26")
2848 {
2849 s.elements.first().and_then(|e| e.get(1)).cloned()
2850 } else {
2851 None
2852 }
2853 });
2854 slices.push((zid, z25, z26));
2855 }
2856 }
2857 if slices.is_empty() {
2858 return ConditionResult::Unknown;
2859 }
2860 // For each slice with Zeitraum-ID > 1: its DTM+Z25 must equal DTM+Z26 of the previous slice
2861 for i in 0..slices.len() {
2862 let (zid, ref z25, _) = slices[i];
2863 if zid <= 1 {
2864 continue;
2865 }
2866 let prev_id = zid - 1;
2867 match slices.iter().find(|(id, _, _)| *id == prev_id) {
2868 Some((_, _, prev_z26)) => match (z25, prev_z26) {
2869 (Some(curr), Some(prev_end)) => {
2870 if curr != prev_end {
2871 return ConditionResult::False;
2872 }
2873 }
2874 _ => return ConditionResult::Unknown,
2875 },
2876 None => return ConditionResult::Unknown,
2877 }
2878 }
2879 ConditionResult::True
2880 }
2881
2882 /// [135] Wenn dieses DTM+Z25 (Verwendung der Daten ab) nicht im SG6 RFF+Z47/ Z54 (Verwendungszeitraum der Daten: Im System vorhandene Daten/ Im System keine Daten vorhanden) mit der Zeitraum ID "1" im DE115...
2883 // REVIEW: Identical time-slice continuity logic as condition 134 but applied to Z47/Z54 (Im System vorhandene Daten/Im System keine Daten vorhanden) SG6 groups. Same structural rule: DTM+Z25 of slice N must equal DTM+Z26 of slice N-1 for all N > 1. (medium confidence)
2884 fn evaluate_135(&self, ctx: &EvaluationContext) -> ConditionResult {
2885 let nav = match ctx.navigator() {
2886 Some(n) => n,
2887 None => return ConditionResult::Unknown,
2888 };
2889 let sg6_count = nav.group_instance_count(&["SG4", "SG6"]);
2890 // Collect (zeitraum_id, dtm_z25_value, dtm_z26_value) for every Z47/Z54 SG6
2891 let mut slices: Vec<(u32, Option<String>, Option<String>)> = Vec::new();
2892 for i in 0..sg6_count {
2893 let rffs = nav.find_segments_in_group("RFF", &["SG4", "SG6"], i);
2894 // RFF C506: [0][0]=qualifier, [0][1]=ref-id, [0][2]=Zeitraum-ID
2895 let maybe_zid = rffs.iter().find_map(|s| {
2896 let qual = s
2897 .elements
2898 .first()
2899 .and_then(|e| e.first())
2900 .map(|v| v.as_str())?;
2901 if qual == "Z47" || qual == "Z54" {
2902 s.elements
2903 .first()
2904 .and_then(|e| e.get(2))
2905 .and_then(|v| v.parse::<u32>().ok())
2906 } else {
2907 None
2908 }
2909 });
2910 if let Some(zid) = maybe_zid {
2911 let dtms = nav.find_segments_in_group("DTM", &["SG4", "SG6"], i);
2912 let z25 = dtms.iter().find_map(|s| {
2913 if s.elements
2914 .first()
2915 .and_then(|e| e.first())
2916 .map(|v| v.as_str())
2917 == Some("Z25")
2918 {
2919 s.elements.first().and_then(|e| e.get(1)).cloned()
2920 } else {
2921 None
2922 }
2923 });
2924 let z26 = dtms.iter().find_map(|s| {
2925 if s.elements
2926 .first()
2927 .and_then(|e| e.first())
2928 .map(|v| v.as_str())
2929 == Some("Z26")
2930 {
2931 s.elements.first().and_then(|e| e.get(1)).cloned()
2932 } else {
2933 None
2934 }
2935 });
2936 slices.push((zid, z25, z26));
2937 }
2938 }
2939 if slices.is_empty() {
2940 return ConditionResult::Unknown;
2941 }
2942 // For each slice with Zeitraum-ID > 1: its DTM+Z25 must equal DTM+Z26 of the previous slice
2943 for i in 0..slices.len() {
2944 let (zid, ref z25, _) = slices[i];
2945 if zid <= 1 {
2946 continue;
2947 }
2948 let prev_id = zid - 1;
2949 match slices.iter().find(|(id, _, _)| *id == prev_id) {
2950 Some((_, _, prev_z26)) => match (z25, prev_z26) {
2951 (Some(curr), Some(prev_end)) => {
2952 if curr != prev_end {
2953 return ConditionResult::False;
2954 }
2955 }
2956 _ => return ConditionResult::Unknown,
2957 },
2958 None => return ConditionResult::Unknown,
2959 }
2960 }
2961 ConditionResult::True
2962 }
2963
2964 /// [136] Wenn SG10 CCI+++E13 (Zählertyp) CAV+EHZ (elektronischer Haushaltszähler) vorhanden
2965 fn evaluate_136(&self, _ctx: &EvaluationContext) -> ConditionResult {
2966 // TODO: implement
2967 ConditionResult::Unknown
2968 }
2969
2970 /// [137] Nicht bei Neuanlage
2971 fn evaluate_137(&self, _ctx: &EvaluationContext) -> ConditionResult {
2972 // TODO: implement
2973 ConditionResult::Unknown
2974 }
2975
2976 /// [138] Wenn im selben QTY im DE6063 Z35 (Abschlag) vorhanden
2977 fn evaluate_138(&self, _ctx: &EvaluationContext) -> ConditionResult {
2978 // TODO: implement
2979 ConditionResult::Unknown
2980 }
2981
2982 /// [139] Wenn SG10 CAV+IVA (Individuelle Abstimmung) nicht vorhanden
2983 // REVIEW: Condition is True when SG10 CAV+IVA (Individuelle Abstimmung) is NOT present anywhere. Uses parent-child navigation to iterate all SG8 instances and their SG10 child groups, checking CAV elements[0][0] for 'IVA'. Falls back to message-wide lacks_qualifier when no navigator is available. Returns False as soon as any CAV+IVA is found, True if none found. (medium confidence)
2984 fn evaluate_139(&self, ctx: &EvaluationContext) -> ConditionResult {
2985 let nav = match ctx.navigator {
2986 Some(n) => n,
2987 None => return ctx.lacks_qualifier("CAV", 0, "IVA"),
2988 };
2989 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
2990 for i in 0..sg8_count {
2991 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
2992 for j in 0..sg10_count {
2993 let cavs = nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
2994 if cavs.iter().any(|s| {
2995 s.elements
2996 .first()
2997 .and_then(|e: &Vec<String>| e.first())
2998 .is_some_and(|v: &String| v == "IVA")
2999 }) {
3000 return ConditionResult::False;
3001 }
3002 }
3003 }
3004 ConditionResult::True
3005 }
3006
3007 /// [140] Wenn im selben QTY im DE6063 Z34/Z35 (Zuschlag/Abschlag) vorhanden
3008 fn evaluate_140(&self, _ctx: &EvaluationContext) -> ConditionResult {
3009 // TODO: implement
3010 ConditionResult::Unknown
3011 }
3012
3013 /// [141] Wenn SG10 CAV+MIW/ MPW/ MBW vorhanden
3014 fn evaluate_141(&self, _ctx: &EvaluationContext) -> ConditionResult {
3015 // TODO: implement
3016 ConditionResult::Unknown
3017 }
3018
3019 /// [142] Wenn SG8 PIA+Z01+:Z04/ Z05 (Berechnung Tagesmitteltemperatur: vom Anbieter zur Verfügung gestellte - / Äquivalente Tagesmitteltemperatur) vorhanden
3020 fn evaluate_142(&self, _ctx: &EvaluationContext) -> ConditionResult {
3021 // TODO: implement
3022 ConditionResult::Unknown
3023 }
3024
3025 /// [143] Wenn STS+7++ZX3 (Transaktionsgrund: Abrechnungsdaten BK-Abrechnung verbrauchender MaLo) vorhanden
3026 fn evaluate_143(&self, _ctx: &EvaluationContext) -> ConditionResult {
3027 // TODO: implement
3028 ConditionResult::Unknown
3029 }
3030
3031 /// [144] Wenn STS+7++ZAN (Transaktionsgrund: Korrektur Abrechnungsdaten BK-Abrechnung verbrauchender MaLo) vorhanden
3032 fn evaluate_144(&self, _ctx: &EvaluationContext) -> ConditionResult {
3033 // TODO: implement
3034 ConditionResult::Unknown
3035 }
3036
3037 /// [145] Wenn STS+7++ZX2 (Transaktionsgrund: Abrechnungsdaten BK-Abrechnung erzeugender MaLo) vorhanden
3038 fn evaluate_145(&self, _ctx: &EvaluationContext) -> ConditionResult {
3039 // TODO: implement
3040 ConditionResult::Unknown
3041 }
3042
3043 /// [146] Wenn STS+7++ZA0 (Transaktionsgrund: Korrektur Abrechnungsdaten BK-Abrechnung erzeugender MaLo) vorhanden
3044 fn evaluate_146(&self, _ctx: &EvaluationContext) -> ConditionResult {
3045 // TODO: implement
3046 ConditionResult::Unknown
3047 }
3048
3049 /// [147] Wenn in Anfrage vorhanden
3050 fn evaluate_147(&self, _ctx: &EvaluationContext) -> ConditionResult {
3051 // TODO: implement
3052 ConditionResult::Unknown
3053 }
3054
3055 /// [148] Wenn in dieser SG8 im SG8 PIA+Z02 (Gruppenartikel-ID / Artikel-ID), die Artikel-ID 1-02-0-017/ 1-02-0-018 vorhanden
3056 fn evaluate_148(&self, _ctx: &EvaluationContext) -> ConditionResult {
3057 // TODO: implement
3058 ConditionResult::Unknown
3059 }
3060
3061 /// [149] Wenn zwei SG8 SEQ+Z45 (Netznutzungsabrechnungsdaten der Marktlokation), mit derselben Zeitraum-ID im DE1050, mit Artikel-ID im SG8 PIA+Z02 (Gruppenartikel-ID / Artikel-ID), eine SG8 mit 1-02-0-017...
3062 // REVIEW: Condition checks whether two SG8 SEQ+Z45 groups with the same Zeitraum-ID (elements[1][0]) each contain PIA+Z02 (DE4347=Z02) with product codes '1-02-0-017' and '1-02-0-018'. Uses collect_group_values to gather SEQ qualifiers and Zeitraum-IDs per group instance, then PIA qualifiers and product codes (elements[1][0]=DE7140) per group instance. Positional alignment of pia_quals and pia_prods (both from same PIA segments in same order) enables reliable qualifier-to-product matching. Groups product codes by Zeitraum-ID to check co-occurrence. (medium confidence)
3063 fn evaluate_149(&self, ctx: &EvaluationContext) -> ConditionResult {
3064 use std::collections::{HashMap, HashSet};
3065 let seq_quals = ctx.collect_group_values("SEQ", 0, 0, &["SG4", "SG8"]);
3066 let seq_zeitraum = ctx.collect_group_values("SEQ", 1, 0, &["SG4", "SG8"]);
3067 let pia_quals = ctx.collect_group_values("PIA", 0, 0, &["SG4", "SG8"]);
3068 let pia_prods = ctx.collect_group_values("PIA", 1, 0, &["SG4", "SG8"]);
3069 // Map group index -> Zeitraum-ID for SG8s with SEQ+Z45
3070 let mut idx_to_zeitraum: HashMap<usize, String> = HashMap::new();
3071 for ((gi, q), (_, zid)) in seq_quals.iter().zip(seq_zeitraum.iter()) {
3072 if q == "Z45" && !zid.is_empty() {
3073 idx_to_zeitraum.insert(*gi, zid.clone());
3074 }
3075 }
3076 if idx_to_zeitraum.is_empty() {
3077 return ConditionResult::False;
3078 }
3079 // Map Zeitraum-ID -> set of PIA+Z02 product codes found in the same SG8 group
3080 let mut zeitraum_products: HashMap<String, HashSet<String>> = HashMap::new();
3081 for (i, (gi, qual)) in pia_quals.iter().enumerate() {
3082 if qual == "Z02" {
3083 if let Some(zid) = idx_to_zeitraum.get(gi) {
3084 if let Some((_, prod)) = pia_prods.get(i) {
3085 if !prod.is_empty() {
3086 zeitraum_products
3087 .entry(zid.clone())
3088 .or_default()
3089 .insert(prod.clone());
3090 }
3091 }
3092 }
3093 }
3094 }
3095 ConditionResult::from(
3096 zeitraum_products
3097 .values()
3098 .any(|codes| codes.contains("1-02-0-017") && codes.contains("1-02-0-018")),
3099 )
3100 }
3101
3102 /// [150] Wenn in dieser SG8 im SG8 PIA+Z02 (Gruppenartikel-ID / Artikel-ID), die Artikel-ID 1-02-0-002 vorhanden
3103 fn evaluate_150(&self, _ctx: &EvaluationContext) -> ConditionResult {
3104 // TODO: implement
3105 ConditionResult::Unknown
3106 }
3107
3108 /// [151] Wenn bei der Bestellung ein Messprodukt der Codeliste der Konfigurationen aus dem Kapitel 4.4 mit dem Ü̈bertragungsweg \"aus dem SMGW\" bestellt wurde. Der Empfänger der Werte kann dadurch seine...
3109 fn evaluate_151(&self, ctx: &EvaluationContext) -> ConditionResult {
3110 ctx.external.evaluate("code_list_membership_check")
3111 }
3112
3113 /// [152] Wenn FTX+Z28 (IP-Range des Absenders) nicht vorhanden
3114 fn evaluate_152(&self, _ctx: &EvaluationContext) -> ConditionResult {
3115 // TODO: implement
3116 ConditionResult::Unknown
3117 }
3118
3119 /// [153] Wenn FTX+Z27 (IP-Adresse des Absenders) nicht vorhanden
3120 fn evaluate_153(&self, _ctx: &EvaluationContext) -> ConditionResult {
3121 // TODO: implement
3122 ConditionResult::Unknown
3123 }
3124
3125 /// [156] Wenn SG4 FTX+Z17 (Zieladresse URI) vorhanden
3126 fn evaluate_156(&self, _ctx: &EvaluationContext) -> ConditionResult {
3127 // TODO: implement
3128 ConditionResult::Unknown
3129 }
3130
3131 /// [161] Wenn SG4 STS+7++E03+ZW8 (Transaktionsgrundergänzung Fall 1) vorhanden
3132 fn evaluate_161(&self, _ctx: &EvaluationContext) -> ConditionResult {
3133 // TODO: implement
3134 ConditionResult::Unknown
3135 }
3136
3137 /// [162] Wenn SG4 STS+7++E03+ZW9 (Transaktionsgrundergänzung Fall 2) vorhanden
3138 fn evaluate_162(&self, _ctx: &EvaluationContext) -> ConditionResult {
3139 // TODO: implement
3140 ConditionResult::Unknown
3141 }
3142
3143 /// [163] Wenn SG4 STS+7++E03+ZX0 (Transaktionsgrundergänzung Fall 3) vorhanden
3144 fn evaluate_163(&self, _ctx: &EvaluationContext) -> ConditionResult {
3145 // TODO: implement
3146 ConditionResult::Unknown
3147 }
3148
3149 /// [164] Wenn SG4 STS+7++E03+ZX1 (Transaktionsgrundergänzung Fall 4) vorhanden
3150 fn evaluate_164(&self, _ctx: &EvaluationContext) -> ConditionResult {
3151 // TODO: implement
3152 ConditionResult::Unknown
3153 }
3154
3155 /// [165] Wenn bekannt
3156 fn evaluate_165(&self, _ctx: &EvaluationContext) -> ConditionResult {
3157 // TODO: implement
3158 ConditionResult::Unknown
3159 }
3160
3161 /// [166] Wenn vorhanden
3162 fn evaluate_166(&self, _ctx: &EvaluationContext) -> ConditionResult {
3163 // TODO: implement
3164 ConditionResult::Unknown
3165 }
3166
3167 /// [167] Wenn SG5 LOC+Z21 (Tranche) vorhanden
3168 fn evaluate_167(&self, _ctx: &EvaluationContext) -> ConditionResult {
3169 // TODO: implement
3170 ConditionResult::Unknown
3171 }
3172
3173 /// [170] Wenn Anschrift der Marktlokation vorhanden
3174 fn evaluate_170(&self, _ctx: &EvaluationContext) -> ConditionResult {
3175 // TODO: implement
3176 ConditionResult::Unknown
3177 }
3178
3179 /// [172] Wenn im selben QTY im DE6063 Z37 (Kein Zu- und Abschlag) vorhanden
3180 fn evaluate_172(&self, _ctx: &EvaluationContext) -> ConditionResult {
3181 // TODO: implement
3182 ConditionResult::Unknown
3183 }
3184
3185 /// [173] Wenn im RFF+Z33 (Referenz auf den Objektcode in der Lokationsbündelstruktur) das DE1156 (Fortlaufende Nummer eines Lokationsbündels im Geschäftsvorfall) in derselben SG8 SEQ+Z58/ ZC9/ ZD0/ ZD6 (...
3186 // REVIEW: Condition is True when, in an SG8 with SEQ+Z58/ZC9/ZD0/ZD6 (Zuordnung Lokation zum Objektcode), RFF+Z33 exists but its DE1156 (elements[0][2] = Fortlaufende Nummer) is absent or empty. Uses collect_group_values to find target SG8 group indices by SEQ qualifier, then positionally aligns rff_quals[i] with rff_de1156[i] (same RFF segment) to check DE1156 emptiness scoped to those groups. Returns Unknown if no RFF+Z33 found in target groups (condition not applicable), False if all RFF+Z33 have DE1156 present. (medium confidence)
3187 fn evaluate_173(&self, ctx: &EvaluationContext) -> ConditionResult {
3188 use std::collections::HashSet;
3189 let seq_quals = ctx.collect_group_values("SEQ", 0, 0, &["SG4", "SG8"]);
3190 let target_indices: HashSet<usize> = seq_quals
3191 .iter()
3192 .filter(|(_, q)| matches!(q.as_str(), "Z58" | "ZC9" | "ZD0" | "ZD6"))
3193 .map(|(i, _)| *i)
3194 .collect();
3195 if target_indices.is_empty() {
3196 return ConditionResult::Unknown;
3197 }
3198 // Collect RFF qualifier (elements[0][0]) and DE1156 (elements[0][2]) with positional alignment
3199 let rff_quals = ctx.collect_group_values("RFF", 0, 0, &["SG4", "SG8"]);
3200 let rff_de1156 = ctx.collect_group_values("RFF", 0, 2, &["SG4", "SG8"]);
3201 let mut found_rff_z33 = false;
3202 for (i, (gi, qual)) in rff_quals.iter().enumerate() {
3203 if qual == "Z33" && target_indices.contains(gi) {
3204 found_rff_z33 = true;
3205 let de1156_empty = rff_de1156.get(i).map(|(_, v)| v.is_empty()).unwrap_or(true);
3206 if de1156_empty {
3207 return ConditionResult::True;
3208 }
3209 }
3210 }
3211 if found_rff_z33 {
3212 ConditionResult::False
3213 } else {
3214 ConditionResult::Unknown
3215 }
3216 }
3217
3218 /// [174] Wenn im RFF+Z33 (Referenz auf den Objektcode in der Lokationsbündelstruktur) das DE1156 Fortlaufende Nummer eines Lokationsbündels im Geschäftsvorfall) in derselben SG8 SEQ+Z58/ ZC9/ ZD0/ ZD6 (Z...
3219 fn evaluate_174(&self, _ctx: &EvaluationContext) -> ConditionResult {
3220 // TODO: implement
3221 ConditionResult::Unknown
3222 }
3223
3224 /// [175] Wenn der Objektcode im RFF+Z33 (Referenz auf den Objektcode in der Lokationsbündelstruktur) im DE1154 derselben SG8 SEQ+Z58 (Zuordnung Lokation zum Objektcode des Lokationsbündels) in einem weite...
3225 // REVIEW: Cross-SG8 check: find all SG8 instances with SEQ+Z58 that also have RFF+Z33. Check whether any Objektcode (DE1154) with the same fortlaufende Nummer (DE1156) appears in two distinct SG8 instances. Uses nav.find_segments_in_group to access SG8-level segments directly, following the existing navigator pattern. (medium confidence)
3226 fn evaluate_175(&self, ctx: &EvaluationContext) -> ConditionResult {
3227 let nav = match ctx.navigator {
3228 Some(n) => n,
3229 None => return ConditionResult::Unknown,
3230 };
3231 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
3232 let mut entries: Vec<(usize, String, String)> = Vec::new();
3233 for i in 0..sg8_count {
3234 let seqs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
3235 if !seqs.iter().any(|s| {
3236 s.elements
3237 .first()
3238 .and_then(|e: &Vec<String>| e.first())
3239 .is_some_and(|v: &String| v == "Z58")
3240 }) {
3241 continue;
3242 }
3243 let rffs = nav.find_segments_in_group("RFF", &["SG4", "SG8"], i);
3244 for rff in &rffs {
3245 let elems = match rff.elements.first() {
3246 Some(e) => e,
3247 None => continue,
3248 };
3249 if elems.first().map(|s| s.as_str()) != Some("Z33") {
3250 continue;
3251 }
3252 let objektcode = elems.get(1).cloned().unwrap_or_default();
3253 let fort_nr = elems.get(2).cloned().unwrap_or_default();
3254 if !objektcode.is_empty() {
3255 entries.push((i, objektcode, fort_nr));
3256 }
3257 }
3258 }
3259 for a in 0..entries.len() {
3260 for b in (a + 1)..entries.len() {
3261 if entries[a].0 != entries[b].0
3262 && entries[a].1 == entries[b].1
3263 && entries[a].2 == entries[b].2
3264 {
3265 return ConditionResult::True;
3266 }
3267 }
3268 }
3269 ConditionResult::False
3270 }
3271
3272 /// [176] Wenn in demselben Segment das DE1153 mit dem Code Z34 vorgelagerte Messlokation vorhanden ist
3273 fn evaluate_176(&self, _ctx: &EvaluationContext) -> ConditionResult {
3274 // TODO: implement
3275 ConditionResult::Unknown
3276 }
3277
3278 /// [177] Wenn in demselben Segment das DE1153 mit dem Code Z35 vorgelagerte Netzlokation vorhanden ist
3279 fn evaluate_177(&self, _ctx: &EvaluationContext) -> ConditionResult {
3280 // TODO: implement
3281 ConditionResult::Unknown
3282 }
3283
3284 /// [178] Wenn das LOC+Z18 (Netzlokation) vorhanden ist
3285 fn evaluate_178(&self, _ctx: &EvaluationContext) -> ConditionResult {
3286 // TODO: implement
3287 ConditionResult::Unknown
3288 }
3289
3290 /// [179] Wenn der Objektcode im RFF+Z33 (Referenz auf den Objektcode in der Lokationsbündelstruktur) im DE1154 derselben SG8 SEQ+Z58/ ZC9 / ZD0/ ZD6 (Zuordnung Lokation zum Objektcode des Lokationsbündels...
3291 fn evaluate_179(&self, _ctx: &EvaluationContext) -> ConditionResult {
3292 // TODO: implement
3293 ConditionResult::Unknown
3294 }
3295
3296 /// [180] Wenn im selben QTY im DE6063 Z46 (Kein Abschlag) vorhanden
3297 fn evaluate_180(&self, _ctx: &EvaluationContext) -> ConditionResult {
3298 // TODO: implement
3299 ConditionResult::Unknown
3300 }
3301
3302 /// [184] Wenn in derselben SG8 SEQ+Z18 (Daten der Messlokation) ein CCI+Z01++Z82 (Verwendungsumfang: ID der prozessual behandelten Messlokation) vorhanden
3303 fn evaluate_184(&self, _ctx: &EvaluationContext) -> ConditionResult {
3304 // TODO: implement
3305 ConditionResult::Unknown
3306 }
3307
3308 /// [190] Wenn in derselben SG8 SEQ+Z60/ ZG8/ ZG9/ ZE0 (Produkt-Daten der Netzlokation) PIA+5+9991000000721:Z12 vorhanden
3309 fn evaluate_190(&self, _ctx: &EvaluationContext) -> ConditionResult {
3310 // TODO: implement
3311 ConditionResult::Unknown
3312 }
3313
3314 /// [191] Wenn im SG4 IDE+Z01 (Identifikation einer Liste) STS+E01 (Status der Antwort der Liste) nicht vorhanden
3315 fn evaluate_191(&self, _ctx: &EvaluationContext) -> ConditionResult {
3316 // TODO: implement
3317 ConditionResult::Unknown
3318 }
3319
3320 /// [192] Wenn SG4 STS+7++XXX+ZW4/ZAP (Transaktionsgrund / Ergänzung: Verbrauchende Marktlokation / ruhende Marktlokation) vorhanden
3321 fn evaluate_192(&self, _ctx: &EvaluationContext) -> ConditionResult {
3322 // TODO: implement
3323 ConditionResult::Unknown
3324 }
3325
3326 /// [193] Wenn das SG10 CCI ZB5 (Spannungsebene der Summenzeitreihe) CAV E06 (Niederspannung) in dieser SG vorhanden
3327 fn evaluate_193(&self, ctx: &EvaluationContext) -> ConditionResult {
3328 let nav = match ctx.navigator {
3329 Some(n) => n,
3330 None => {
3331 let cavs = ctx.find_segments("CAV");
3332 return ConditionResult::from(cavs.iter().any(|s| {
3333 s.elements
3334 .first()
3335 .and_then(|e: &Vec<String>| e.first())
3336 .is_some_and(|v: &String| v == "E06")
3337 }));
3338 }
3339 };
3340 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
3341 for i in 0..sg8_count {
3342 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
3343 for j in 0..sg10_count {
3344 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
3345 let has_cci_zb5 = ccis.iter().any(|s| {
3346 s.elements
3347 .get(2)
3348 .and_then(|e: &Vec<String>| e.first())
3349 .is_some_and(|v: &String| v == "ZB5")
3350 });
3351 if !has_cci_zb5 {
3352 continue;
3353 }
3354 let cavs = nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
3355 if cavs.iter().any(|s| {
3356 s.elements
3357 .first()
3358 .and_then(|e: &Vec<String>| e.first())
3359 .is_some_and(|v: &String| v == "E06")
3360 }) {
3361 return ConditionResult::True;
3362 }
3363 }
3364 }
3365 ConditionResult::False
3366 }
3367
3368 /// [194] Wenn das SG10 CCI ZB5 (Spannungsebene der Summenzeitreihe) CAV E05 (Mittelspannung) in dieser SG vorhanden
3369 fn evaluate_194(&self, _ctx: &EvaluationContext) -> ConditionResult {
3370 // TODO: implement
3371 ConditionResult::Unknown
3372 }
3373
3374 /// [195] Wenn das SG10 CCI ZB5 (Spannungsebene der Summenzeitreihe) CAV E04 (Hochspannung) in dieser SG vorhanden
3375 fn evaluate_195(&self, _ctx: &EvaluationContext) -> ConditionResult {
3376 // TODO: implement
3377 ConditionResult::Unknown
3378 }
3379
3380 /// [196] Wenn der Objektcode im RFF+Z33 (Referenz auf den Objektcode in der Lokationsbündelstruktur) im DE1154 derselben SG8 SEQ+Z58/ZC9/ZD0 (Zuordnung Lokation zum Objektcode des Lokationsbündels) in ein...
3381 // REVIEW: Extended cross-SG8 check vs 175: now requires matching SEQ qualifier code (DE1229), Zeitraum-ID from SEQ DE1050 (elements[1][0]), Objektcode (RFF+Z33 DE1154), AND fortlaufende Nummer (RFF+Z33 DE1156) to all be identical between two distinct SG8 instances. SEQ qualifiers are Z58/ZC9/ZD0 per schema. (medium confidence)
3382 fn evaluate_196(&self, ctx: &EvaluationContext) -> ConditionResult {
3383 let nav = match ctx.navigator {
3384 Some(n) => n,
3385 None => return ConditionResult::Unknown,
3386 };
3387 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
3388 let mut entries: Vec<(usize, String, String, String, String)> = Vec::new();
3389 for i in 0..sg8_count {
3390 let seqs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
3391 let seq_opt = seqs.iter().find(|s| {
3392 s.elements
3393 .first()
3394 .and_then(|e: &Vec<String>| e.first())
3395 .is_some_and(|v: &String| matches!(v.as_str(), "Z58" | "ZC9" | "ZD0"))
3396 });
3397 let seq = match seq_opt {
3398 Some(s) => s,
3399 None => continue,
3400 };
3401 let seq_code = seq
3402 .elements
3403 .first()
3404 .and_then(|e: &Vec<String>| e.first())
3405 .cloned()
3406 .unwrap_or_default();
3407 let zeitraum_id = seq
3408 .elements
3409 .get(1)
3410 .and_then(|e: &Vec<String>| e.first())
3411 .cloned()
3412 .unwrap_or_default();
3413 let rffs = nav.find_segments_in_group("RFF", &["SG4", "SG8"], i);
3414 for rff in &rffs {
3415 let elems = match rff.elements.first() {
3416 Some(e) => e,
3417 None => continue,
3418 };
3419 if elems.first().map(|s| s.as_str()) != Some("Z33") {
3420 continue;
3421 }
3422 let objektcode = elems.get(1).cloned().unwrap_or_default();
3423 let fort_nr = elems.get(2).cloned().unwrap_or_default();
3424 if !objektcode.is_empty() {
3425 entries.push((
3426 i,
3427 seq_code.clone(),
3428 zeitraum_id.clone(),
3429 objektcode,
3430 fort_nr,
3431 ));
3432 }
3433 }
3434 }
3435 for a in 0..entries.len() {
3436 for b in (a + 1)..entries.len() {
3437 if entries[a].0 != entries[b].0
3438 && entries[a].1 == entries[b].1
3439 && entries[a].2 == entries[b].2
3440 && entries[a].3 == entries[b].3
3441 && entries[a].4 == entries[b].4
3442 {
3443 return ConditionResult::True;
3444 }
3445 }
3446 }
3447 ConditionResult::False
3448 }
3449
3450 /// [197] Wenn das RFF+Z18 (Marktlokation) aus dieser SG8 auf das gleiche SG5 LOC+Z16 (Marktlokation), wie ein RFF+Z18 (Marktlokation) aus einer SG8 SEQ+Z01 (Daten der Marktlokation), in dem SG10 CCI+++ZA6 (...
3451 // REVIEW: Two-phase cross-SG8 check. Phase 1: collect Marktlokation IDs from SG8 instances that (a) have SEQ+Z01 and (b) have an SG10 child with CCI elements[2][0]=ZA6 and CAV elements[0][0]=E02. Phase 2: check whether any SG8's RFF+Z18 references one of those qualifying Marktlokation IDs, establishing the cross-reference described in the condition. (medium confidence)
3452 fn evaluate_197(&self, ctx: &EvaluationContext) -> ConditionResult {
3453 let nav = match ctx.navigator {
3454 Some(n) => n,
3455 None => return ConditionResult::Unknown,
3456 };
3457 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
3458 let mut qualifying_malo_ids: Vec<String> = Vec::new();
3459 for i in 0..sg8_count {
3460 let seqs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
3461 if !seqs.iter().any(|s| {
3462 s.elements
3463 .first()
3464 .and_then(|e: &Vec<String>| e.first())
3465 .is_some_and(|v: &String| v == "Z01")
3466 }) {
3467 continue;
3468 }
3469 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
3470 let has_prog = (0..sg10_count).any(|j| {
3471 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
3472 let has_za6 = ccis.iter().any(|s| {
3473 s.elements
3474 .get(2)
3475 .and_then(|e: &Vec<String>| e.first())
3476 .is_some_and(|v: &String| v == "ZA6")
3477 });
3478 if !has_za6 {
3479 return false;
3480 }
3481 let cavs = nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
3482 cavs.iter().any(|s| {
3483 s.elements
3484 .first()
3485 .and_then(|e: &Vec<String>| e.first())
3486 .is_some_and(|v: &String| v == "E02")
3487 })
3488 });
3489 if !has_prog {
3490 continue;
3491 }
3492 let rffs = nav.find_segments_in_group("RFF", &["SG4", "SG8"], i);
3493 for rff in &rffs {
3494 let elems = match rff.elements.first() {
3495 Some(e) => e,
3496 None => continue,
3497 };
3498 if elems.first().map(|s| s.as_str()) != Some("Z18") {
3499 continue;
3500 }
3501 if let Some(malo_id) = elems.get(1) {
3502 if !malo_id.is_empty() {
3503 qualifying_malo_ids.push(malo_id.clone());
3504 }
3505 }
3506 }
3507 }
3508 if qualifying_malo_ids.is_empty() {
3509 return ConditionResult::False;
3510 }
3511 for i in 0..sg8_count {
3512 let rffs = nav.find_segments_in_group("RFF", &["SG4", "SG8"], i);
3513 for rff in &rffs {
3514 let elems = match rff.elements.first() {
3515 Some(e) => e,
3516 None => continue,
3517 };
3518 if elems.first().map(|s| s.as_str()) != Some("Z18") {
3519 continue;
3520 }
3521 if let Some(malo_id) = elems.get(1) {
3522 if qualifying_malo_ids.contains(malo_id) {
3523 return ConditionResult::True;
3524 }
3525 }
3526 }
3527 }
3528 ConditionResult::False
3529 }
3530
3531 /// [198] Wenn SG4 STS+7++E03(Transaktionsgrund: Wechsel) vorhanden
3532 fn evaluate_198(&self, _ctx: &EvaluationContext) -> ConditionResult {
3533 // TODO: implement
3534 ConditionResult::Unknown
3535 }
3536
3537 /// [199] Wenn in der SG8 SEQ+Z01/ SG10 CCI+++ZA6 (Prognosegrundlage der Marktlokation: Prognose auf Basis von Profilen) mit identischer Zeitraum-ID im DE1050 CAV+E02 (SLP/SEP) vorhanden
3538 // REVIEW: Checks whether any SG8 with SEQ+Z01 (Daten der Marktlokation) contains an SG10 child group where CCI elements[2][0]=ZA6 (Prognosegrundlage: Prognose auf Basis von Profilen) and CAV elements[0][0]=E02 (SLP/SEP) appear in the same SG10 instance. The 'identischer Zeitraum-ID' constraint from SEQ DE1050 is structurally satisfied by operating within the same SG8 instance; deeper Zeitraum-ID cross-referencing with other groups is omitted as it would require knowing the external referencing context. (medium confidence)
3539 fn evaluate_199(&self, ctx: &EvaluationContext) -> ConditionResult {
3540 let nav = match ctx.navigator {
3541 Some(n) => n,
3542 None => {
3543 return ctx.filtered_parent_child_has_qualifier(
3544 &["SG4", "SG8"],
3545 "SEQ",
3546 0,
3547 "Z01",
3548 "SG10",
3549 "CCI",
3550 2,
3551 "ZA6",
3552 )
3553 }
3554 };
3555 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
3556 for i in 0..sg8_count {
3557 let seqs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
3558 if !seqs.iter().any(|s| {
3559 s.elements
3560 .first()
3561 .and_then(|e: &Vec<String>| e.first())
3562 .is_some_and(|v: &String| v == "Z01")
3563 }) {
3564 continue;
3565 }
3566 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
3567 for j in 0..sg10_count {
3568 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
3569 if !ccis.iter().any(|s| {
3570 s.elements
3571 .get(2)
3572 .and_then(|e: &Vec<String>| e.first())
3573 .is_some_and(|v: &String| v == "ZA6")
3574 }) {
3575 continue;
3576 }
3577 let cavs = nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
3578 if cavs.iter().any(|s| {
3579 s.elements
3580 .first()
3581 .and_then(|e: &Vec<String>| e.first())
3582 .is_some_and(|v: &String| v == "E02")
3583 }) {
3584 return ConditionResult::True;
3585 }
3586 }
3587 }
3588 ConditionResult::False
3589 }
3590
3591 /// [201] Wenn die Marktlokation / Tranche nicht den ganzen Bilanzierungsmonat dem gleichen Tupel aus Bilanzkreis, Zeitreihentyp, Spannungsebene und Lieferant zugeordnet ist
3592 fn evaluate_201(&self, _ctx: &EvaluationContext) -> ConditionResult {
3593 // TODO: implement
3594 ConditionResult::Unknown
3595 }
3596
3597 /// [202] Wenn SG8 SEQ+Z78 RFF+Z39 (Keine standardisierte Lokationsbündelstruktur vorhanden), mit identischer Zeitraum-ID im DE1050 wie im DE3224 dieses Segments
3598 // REVIEW: Collects Zeitraum-IDs from SG5 LOC.DE3224 (elements[1][3]), checks SEQ+Z78 DE1050 (elements[1][0]) for a match, then verifies RFF+Z39 exists. Co-occurrence of SEQ+Z78 and RFF+Z39 in the same SG8 instance is not verified without navigator group-instance access. (medium confidence)
3599 fn evaluate_202(&self, ctx: &EvaluationContext) -> ConditionResult {
3600 use std::collections::HashSet;
3601 // Collect Zeitraum-IDs from all SG5 LOC segments (DE3224 at elements[1][3])
3602 let loc_zeitraum_ids: HashSet<String> = ctx
3603 .find_segments("LOC")
3604 .into_iter()
3605 .filter_map(|s| s.elements.get(1)?.get(3).cloned())
3606 .filter(|v| !v.is_empty())
3607 .collect();
3608 if loc_zeitraum_ids.is_empty() {
3609 return ConditionResult::False;
3610 }
3611 // Check if any SEQ+Z78 (SG8 Lokationsbündelstruktur) has DE1050 matching a LOC DE3224
3612 let matching_seq = ctx
3613 .find_segments_with_qualifier("SEQ", 0, "Z78")
3614 .into_iter()
3615 .any(|s| {
3616 s.elements
3617 .get(1)
3618 .and_then(|e: &Vec<String>| e.first())
3619 .is_some_and(|v: &String| {
3620 !v.is_empty() && loc_zeitraum_ids.contains(v.as_str())
3621 })
3622 });
3623 if !matching_seq {
3624 return ConditionResult::False;
3625 }
3626 // Verify RFF+Z39 also exists (co-occurrence in same SG8 not verified without navigator)
3627 ctx.has_qualifier("RFF", 0, "Z39")
3628 }
3629
3630 /// [203] Wenn STS+7++E06 / Z39 / ZC6 / ZC7/ ZT6/ ZT7 vorhanden
3631 fn evaluate_203(&self, _ctx: &EvaluationContext) -> ConditionResult {
3632 // TODO: implement
3633 ConditionResult::Unknown
3634 }
3635
3636 /// [204] Wenn im SG8+SEQ+Z03/ ZA3/ ZA4 (Zähleinrichtungsdaten) mit der selben Zeitraum-ID im SG8 SEQ DE1050, sowie identischer Qualität im DE1229 der SG8 SEQ für die in diesem RFF DE1154 genannte Geräte...
3637 // REVIEW: Checks each Zähleinrichtungsdaten SEQ qualifier (Z03/ZA3/ZA4) — if any SG8 instance has that SEQ qualifier but no RFF+Z14 (Smartmeter-Gateway reference), the condition is true. The additional Zeitraum-ID and Gerätenummer cross-matching from the full condition text cannot be implemented without per-instance SG8 segment access. (medium confidence)
3638 fn evaluate_204(&self, ctx: &EvaluationContext) -> ConditionResult {
3639 // True if any SG8 with Zähleinrichtungsdaten (SEQ+Z03/ZA3/ZA4) lacks RFF+Z14 (Smartmeter-Gateway)
3640 for qual in &["Z03", "ZA3", "ZA4"] {
3641 if matches!(
3642 ctx.any_group_has_qualifier_without(
3643 "SEQ",
3644 0,
3645 qual,
3646 "RFF",
3647 0,
3648 "Z14",
3649 &["SG4", "SG8"]
3650 ),
3651 ConditionResult::True
3652 ) {
3653 return ConditionResult::True;
3654 }
3655 }
3656 ConditionResult::False
3657 }
3658
3659 /// [205] Wenn SG5 LOC+Z19 (Steuerbare Ressource) vorhanden
3660 fn evaluate_205(&self, _ctx: &EvaluationContext) -> ConditionResult {
3661 // TODO: implement
3662 ConditionResult::Unknown
3663 }
3664
3665 /// [206] Wenn SG4 STS+7++ZG5 (Transaktionsgrund: Aufhebung der zukünftigen Zuordnung aufgrund §38 EEG 2014 bzw. §21b Abs. 1 Nr. 2 EEG 2017) nicht vorhanden
3666 fn evaluate_206(&self, _ctx: &EvaluationContext) -> ConditionResult {
3667 // TODO: implement
3668 ConditionResult::Unknown
3669 }
3670
3671 /// [209] Wenn im selben Segment im DE2379 der Code 303 vorhanden ist
3672 fn evaluate_209(&self, _ctx: &EvaluationContext) -> ConditionResult {
3673 // TODO: implement
3674 ConditionResult::Unknown
3675 }
3676
3677 /// [210] Wenn SG10 CCI+++ZA6 (Prognose auf Basis von Profilen) in dieser SG8 vorhanden
3678 fn evaluate_210(&self, _ctx: &EvaluationContext) -> ConditionResult {
3679 // TODO: implement
3680 ConditionResult::Unknown
3681 }
3682
3683 /// [212] Wenn im selben SG12 NAD DE3124 nicht vorhanden
3684 fn evaluate_212(&self, _ctx: &EvaluationContext) -> ConditionResult {
3685 // TODO: implement
3686 ConditionResult::Unknown
3687 }
3688
3689 /// [213] Wenn SG12 NAD+Z09 (Kunde des Lieferanten) vorhanden
3690 fn evaluate_213(&self, _ctx: &EvaluationContext) -> ConditionResult {
3691 // TODO: implement
3692 ConditionResult::Unknown
3693 }
3694
3695 /// [215] Wenn in derselben SG8 (Zähleinrichtungsdaten) SG10 CCI+++E13 CAV+MME (Zählertyp: mME) vorhanden
3696 fn evaluate_215(&self, _ctx: &EvaluationContext) -> ConditionResult {
3697 // TODO: implement
3698 ConditionResult::Unknown
3699 }
3700
3701 /// [216] Wenn CCI+++Z88 (Netznutzung) CAV+Z74:::Z08 (Netznutzungsvertrag: Direkter Vertrag zwischen Kunden und NB) vorhanden
3702 fn evaluate_216(&self, _ctx: &EvaluationContext) -> ConditionResult {
3703 // TODO: implement
3704 ConditionResult::Unknown
3705 }
3706
3707 /// [217] Wenn SG6 RFF+Z49 (Verwendungszeitraum der Daten: \"Gültige Daten\") vorhanden
3708 fn evaluate_217(&self, _ctx: &EvaluationContext) -> ConditionResult {
3709 // TODO: implement
3710 ConditionResult::Unknown
3711 }
3712
3713 /// [219] Wenn SG12 NAD+Z65 (Informativer Kunde des Lieferanten) vorhanden
3714 fn evaluate_219(&self, _ctx: &EvaluationContext) -> ConditionResult {
3715 // TODO: implement
3716 ConditionResult::Unknown
3717 }
3718
3719 /// [220] Wenn SG8 SEQ+Z01/ Z98 (Daten der Marktlokation) SG10 CCI+Z30++Z06 (Lieferrichtung: Erzeugung) in dieser SG8 vorhanden
3720 fn evaluate_220(&self, _ctx: &EvaluationContext) -> ConditionResult {
3721 // TODO: implement
3722 ConditionResult::Unknown
3723 }
3724
3725 /// [221] Wenn kein SG8 SEQ+Z15 (Daten der Tranche) auf die gleiche Marktlokation-ID mit dem RFF+Z18 (Marktlokation) referenziert wie dieses SG8 SEQ+Z01 (Daten der Marktlokation)
3726 fn evaluate_221(&self, _ctx: &EvaluationContext) -> ConditionResult {
3727 // TODO: implement
3728 ConditionResult::Unknown
3729 }
3730
3731 /// [223] Wenn das RFF+Z18 (Marktlokation) aus dieser SG8 auf das gleiche SG5 LOC+Z16 (Marktlokation), wie ein RFF+Z18 (Marktlokation) aus einer SG8 SEQ+Z01 (Daten der Marktlokation) verweist, und dort das S...
3732 fn evaluate_223(&self, _ctx: &EvaluationContext) -> ConditionResult {
3733 // TODO: implement
3734 ConditionResult::Unknown
3735 }
3736
3737 /// [224] Wenn kein SG8 SEQ+ZE7 (Informative Daten der Tranche) auf die gleiche Marktlokation-ID mit dem RFF+Z18 (Marktlokation) referenziert wie dieses SG8 SEQ+Z98 (Informative Daten der Marktlokation)
3738 fn evaluate_224(&self, _ctx: &EvaluationContext) -> ConditionResult {
3739 // TODO: implement
3740 ConditionResult::Unknown
3741 }
3742
3743 /// [227] Wenn im SG8 SEQ+Z98 (Daten der Marktlokation) das SG10 CCI+++ZA6 (Prognosegrundlage der Marktlokation: Prognose auf Basis von Profilen) CAV+E14 (TLP/TEP) vorhanden
3744 fn evaluate_227(&self, _ctx: &EvaluationContext) -> ConditionResult {
3745 // TODO: implement
3746 ConditionResult::Unknown
3747 }
3748
3749 /// [229] Wenn der Objektcode im RFF+Z33 (Referenz auf den Objektcode in der Lokationsbündelstruktur) im DE1154 derselben SG8 SEQ+Z58/ ZC9/ ZD0/ ZD6 (Zuordnung Lokation zum Objektcode des Lokationsbündels)...
3750 // REVIEW: Detects if the same (SEQ-qualifier, Zeitraum-ID, RFF+Z33-Objektcode) triple appears in two different SG8 instances — which is what the condition guards against. Uses collect_group_values to correlate SEQ and RFF data by SG8 instance index. Limitation: collect_group_values may only return the first RFF per SG8 instance, so Z33 may be missed if it is not the first RFF in the group. (medium confidence)
3751 fn evaluate_229(&self, ctx: &EvaluationContext) -> ConditionResult {
3752 use std::collections::HashSet;
3753 let target_quals: HashSet<&str> = ["Z58", "ZC9", "ZD0", "ZD6"].iter().cloned().collect();
3754 // Collect per-SG8-instance: SEQ qualifier and Zeitraum-ID
3755 let seq_quals = ctx.collect_group_values("SEQ", 0, 0, &["SG4", "SG8"]);
3756 let seq_zeitraums = ctx.collect_group_values("SEQ", 1, 0, &["SG4", "SG8"]);
3757 // Collect per-SG8-instance: RFF qualifier and DE1154 value
3758 let rff_quals = ctx.collect_group_values("RFF", 0, 0, &["SG4", "SG8"]);
3759 let rff_codes = ctx.collect_group_values("RFF", 0, 1, &["SG4", "SG8"]);
3760 // Detect duplicate (seq_qual, zeitraum_id, objektcode) combinations across SG8 instances
3761 let mut seen: HashSet<(String, String, String)> = HashSet::new();
3762 for (idx, seq_qual) in &seq_quals {
3763 if seq_qual.is_empty() || !target_quals.contains(seq_qual.as_str()) {
3764 continue;
3765 }
3766 let zeitraum_id = seq_zeitraums
3767 .iter()
3768 .find(|(i, _)| i == idx)
3769 .map(|(_, v)| v.as_str())
3770 .unwrap_or("");
3771 // Find RFF+Z33 in this SG8 instance (correlation by instance index)
3772 for (ridx, rff_qual) in rff_quals.iter() {
3773 if ridx != idx || rff_qual != "Z33" {
3774 continue;
3775 }
3776 if let Some((_, obj_code)) = rff_codes.iter().find(|(i, _)| i == ridx) {
3777 if obj_code.is_empty() {
3778 continue;
3779 }
3780 let key = (seq_qual.clone(), zeitraum_id.to_string(), obj_code.clone());
3781 if seen.contains(&key) {
3782 return ConditionResult::True;
3783 }
3784 seen.insert(key);
3785 }
3786 }
3787 }
3788 ConditionResult::False
3789 }
3790
3791 /// [232] Wenn SG10 CCI+++Z83 (Messtechnische Einordnung der Marktlokation) CAV+Z52 (iMS) vorhanden
3792 fn evaluate_232(&self, _ctx: &EvaluationContext) -> ConditionResult {
3793 // TODO: implement
3794 ConditionResult::Unknown
3795 }
3796
3797 /// [233] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle NB
3798 fn evaluate_233(&self, ctx: &EvaluationContext) -> ConditionResult {
3799 ctx.external.evaluate("recipient_role_check")
3800 }
3801
3802 /// [234] Wenn SG10 CCI+++Z83 (Messtechnische Einordnung der Marktlokation) CAV+Z53 (kME/ mME) vorhanden
3803 fn evaluate_234(&self, _ctx: &EvaluationContext) -> ConditionResult {
3804 // TODO: implement
3805 ConditionResult::Unknown
3806 }
3807
3808 /// [237] Wenn in derselben SG8 im DE7140 des PIA+Z02 (Gruppenartikel-ID / Artikel-ID) eine Gruppenartikel-ID / Artikel-ID mit 1-06 (entspricht Entgelte des Messstellenbetriebs bei kME) beginnt
3809 fn evaluate_237(&self, _ctx: &EvaluationContext) -> ConditionResult {
3810 // TODO: implement
3811 ConditionResult::Unknown
3812 }
3813
3814 /// [238] Wenn SG4 IDE+24 (Vorgang) nicht vorhanden
3815 fn evaluate_238(&self, _ctx: &EvaluationContext) -> ConditionResult {
3816 // TODO: implement
3817 ConditionResult::Unknown
3818 }
3819
3820 /// [239] Wenn in derselben SG10 das CCI+Z17 (Stromverbrauchsart) im CAV+Z65 (Wärme/Kälte) vorhanden
3821 fn evaluate_239(&self, _ctx: &EvaluationContext) -> ConditionResult {
3822 // TODO: implement
3823 ConditionResult::Unknown
3824 }
3825
3826 /// [240] Wenn SG8 SEQ+Z01 (Daten der Marktlokation) CCI+Z22++Z91 (Veräußerungsform der erzeugenden Marktlokation:: Marktprämie) vorhanden
3827 fn evaluate_240(&self, _ctx: &EvaluationContext) -> ConditionResult {
3828 // TODO: implement
3829 ConditionResult::Unknown
3830 }
3831
3832 /// [241] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle MSB
3833 fn evaluate_241(&self, ctx: &EvaluationContext) -> ConditionResult {
3834 ctx.external.evaluate("recipient_role_check")
3835 }
3836
3837 /// [243] Wenn SG10 CCI+6++ZA8 (Aggreg.verantw. NB) in dieser SG8 vorhanden
3838 fn evaluate_243(&self, _ctx: &EvaluationContext) -> ConditionResult {
3839 // TODO: implement
3840 ConditionResult::Unknown
3841 }
3842
3843 /// [244] Wenn SG10 CCI+6++ZA9 (Aggreg.verantw. ÜNB) in dieser SG8 vorhanden
3844 fn evaluate_244(&self, _ctx: &EvaluationContext) -> ConditionResult {
3845 // TODO: implement
3846 ConditionResult::Unknown
3847 }
3848
3849 /// [248] Wenn die Inbetriebnahme der verbrauchenden Marktlokation innerhalb der letzten drei Jahre war und die Energie der Marktlokation mit iMS ausgestatteten Messlokationen erfolgt
3850 fn evaluate_248(&self, _ctx: &EvaluationContext) -> ConditionResult {
3851 // TODO: implement
3852 ConditionResult::Unknown
3853 }
3854
3855 /// [249] Innerhalb eines SG4 IDE müssen alle DE1131 der SG4 STS+E01 (Status der Antwort) den identischen Wert enthalten
3856 fn evaluate_249(&self, _ctx: &EvaluationContext) -> ConditionResult {
3857 // TODO: implement
3858 ConditionResult::Unknown
3859 }
3860
3861 /// [251] Wenn MP-ID in SG2 NAD+MS (Nachrichtensender) in der Rolle BIKO
3862 fn evaluate_251(&self, ctx: &EvaluationContext) -> ConditionResult {
3863 ctx.external.evaluate("sender_role_check")
3864 }
3865
3866 /// [252] Wenn DE0068 vorhanden
3867 fn evaluate_252(&self, _ctx: &EvaluationContext) -> ConditionResult {
3868 // TODO: implement
3869 ConditionResult::Unknown
3870 }
3871
3872 /// [254] Es ist der Code \"AUA\" einzutragen
3873 fn evaluate_254(&self, _ctx: &EvaluationContext) -> ConditionResult {
3874 // TODO: implement
3875 ConditionResult::Unknown
3876 }
3877
3878 /// [255] Wenn Marktlokation am Redispatch 2.0 teilnimmt
3879 fn evaluate_255(&self, _ctx: &EvaluationContext) -> ConditionResult {
3880 // TODO: implement
3881 ConditionResult::Unknown
3882 }
3883
3884 /// [256] Wenn in derselben SG8 SEQ (OBIS-Daten der Zähleinrichtung / Smartmeter-Gateway) das PIA+5+1-b?:1.8.e / 1-b?:2.8.e vorhanden
3885 fn evaluate_256(&self, _ctx: &EvaluationContext) -> ConditionResult {
3886 // TODO: implement
3887 ConditionResult::Unknown
3888 }
3889
3890 /// [257] Wenn in derselben SG8 SEQ (OBIS-Daten der Marktlokation) das PIA+5+1-b?:1.9.e vorhanden
3891 fn evaluate_257(&self, _ctx: &EvaluationContext) -> ConditionResult {
3892 // TODO: implement
3893 ConditionResult::Unknown
3894 }
3895
3896 /// [259] Wenn in diesem PIA der Code im DE7140 mit 1-01, 1-03, 1-05 enthalten ist
3897 fn evaluate_259(&self, _ctx: &EvaluationContext) -> ConditionResult {
3898 // TODO: implement
3899 ConditionResult::Unknown
3900 }
3901
3902 /// [261] Wenn in diesem PIA der Code im DE7140 mit 1-07-1/2, 1-10-1/2/4/5/6/7/8/9, 1-11-1 beginnt
3903 fn evaluate_261(&self, _ctx: &EvaluationContext) -> ConditionResult {
3904 // TODO: implement
3905 ConditionResult::Unknown
3906 }
3907
3908 /// [262] Wenn Produkt an der Marktlokation vorhanden ist
3909 fn evaluate_262(&self, _ctx: &EvaluationContext) -> ConditionResult {
3910 // TODO: implement
3911 ConditionResult::Unknown
3912 }
3913
3914 /// [265] Wenn im SG8 SEQ+Z01/ Z98 (Daten der Marktlokation) das SG10 CCI+++ZA6 (Prognosegrundlage der Marktlokation: Prognose auf Basis von Profilen) CAV+Z36 (TEP m. Referenzmessung) vorhanden
3915 fn evaluate_265(&self, _ctx: &EvaluationContext) -> ConditionResult {
3916 // TODO: implement
3917 ConditionResult::Unknown
3918 }
3919
3920 /// [266] Wenn im SG8 SEQ+Z01 (Daten der Marktlokation) mit identischer Zeitraum-ID im SG8 SEQ+Z01 DE1050 wie in dieser SG8 SEQ, das SG10 CCI+++ZA6 (Prognosegrundlage der Marktlokation: Prognose auf Basis vo...
3921 // REVIEW: Navigates all SG8 instances and their SG10 children, checking for CCI with elements[2][0]=ZA6 (Prognosegrundlage) co-occurring with CAV with elements[0][0]=Z36 (TEP m. Referenzmessung) in the same SG10 instance. The parent SG8 SEQ+Z01 filter and Zeitraum-ID cross-matching are not verified due to lack of direct SG8-level segment access; relies on CCI+ZA6/CAV+Z36 being specific enough to Marktlokation groups. (medium confidence)
3922 fn evaluate_266(&self, ctx: &EvaluationContext) -> ConditionResult {
3923 let nav = match ctx.navigator {
3924 Some(n) => n,
3925 None => {
3926 // Fallback: check any SG8+SEQ+Z01 child SG10 has CAV+Z36
3927 return ctx.filtered_parent_child_has_qualifier(
3928 &["SG4", "SG8"],
3929 "SEQ",
3930 0,
3931 "Z01",
3932 "SG10",
3933 "CAV",
3934 0,
3935 "Z36",
3936 );
3937 }
3938 };
3939 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
3940 for i in 0..sg8_count {
3941 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
3942 for j in 0..sg10_count {
3943 // CCI+++ZA6 means elements[2][0] == "ZA6"
3944 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
3945 let has_cci_za6 = ccis.iter().any(|s| {
3946 s.elements
3947 .get(2)
3948 .and_then(|e: &Vec<String>| e.first())
3949 .is_some_and(|v: &String| v == "ZA6")
3950 });
3951 if has_cci_za6 {
3952 let cavs =
3953 nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
3954 if cavs.iter().any(|s| {
3955 s.elements
3956 .first()
3957 .and_then(|e: &Vec<String>| e.first())
3958 .is_some_and(|v: &String| v == "Z36")
3959 }) {
3960 return ConditionResult::True;
3961 }
3962 }
3963 }
3964 }
3965 ConditionResult::False
3966 }
3967
3968 /// [267] Wenn SG8 SEQ+Z38 (Referenzprofildaten) nicht vorhanden
3969 fn evaluate_267(&self, _ctx: &EvaluationContext) -> ConditionResult {
3970 // TODO: implement
3971 ConditionResult::Unknown
3972 }
3973
3974 /// [268] Wenn der Code im DE3207 in der \"EDI@Energy Codeliste der europäischen Ländercodes\" in der Spalte \"PLZ vorhanden\" ein \"X\" aufgeführt ist
3975 fn evaluate_268(&self, _ctx: &EvaluationContext) -> ConditionResult {
3976 // TODO: implement
3977 ConditionResult::Unknown
3978 }
3979
3980 /// [269] Es sind alle OBIS-Kennzahlen gem. EDI@Energy Codeliste der OBIS-Kennzahlen und Medien für den deutschen Energiemarkt Kap.3 anzugeben welche an der Tranche erforderlich sind
3981 fn evaluate_269(&self, _ctx: &EvaluationContext) -> ConditionResult {
3982 // TODO: implement
3983 ConditionResult::Unknown
3984 }
3985
3986 /// [270] Wenn in diesem PIA der Code im DE7140 mit 1-02, 1-04, 1-06, 1-09 beginnt
3987 fn evaluate_270(&self, _ctx: &EvaluationContext) -> ConditionResult {
3988 // TODO: implement
3989 ConditionResult::Unknown
3990 }
3991
3992 /// [273] Wenn in derselben SG8 SEQ+Z20 (OBIS-Daten der Zähleinrichtung / Smartmeter-Gateway) das PIA+5+1-b?:1.8.e / 1-b?:2.8.e / 1-b?:3.8.e / 1-b?:4.8.e / 1-b?:5.8.e / 1-b?:6.8.e / 1-b?:7.8.e / 1-b?:8.8.e ...
3993 fn evaluate_273(&self, _ctx: &EvaluationContext) -> ConditionResult {
3994 // TODO: implement
3995 ConditionResult::Unknown
3996 }
3997
3998 /// [279] Wenn STS+7++xxx+ZW4 / ZAP (Transaktionsgrundergänzung verbrauchende Marktlokation / ruhende Marktlokation) vorhanden
3999 fn evaluate_279(&self, _ctx: &EvaluationContext) -> ConditionResult {
4000 // TODO: implement
4001 ConditionResult::Unknown
4002 }
4003
4004 /// [280] Nur MP-ID aus Sparte Strom
4005 fn evaluate_280(&self, _ctx: &EvaluationContext) -> ConditionResult {
4006 // TODO: implement
4007 ConditionResult::Unknown
4008 }
4009
4010 /// [282] Wenn in diesem PIA der Code im DE7140 1-01-6-005, 1-01-9-001/002, 1-07-3-001, 1- 08-1-001, 1-08-3-001, 1-08-4-001/002/003/004, 1-10-3-001 enthalten ist
4011 fn evaluate_282(&self, _ctx: &EvaluationContext) -> ConditionResult {
4012 // TODO: implement
4013 ConditionResult::Unknown
4014 }
4015
4016 /// [284] Erlaubte Codes aus der Codeliste der Gruppenartikel- und Artikel-ID sind in der Spalte UTILMD/Codeverwendung mit X gekennzeichnet
4017 fn evaluate_284(&self, _ctx: &EvaluationContext) -> ConditionResult {
4018 // TODO: implement
4019 ConditionResult::Unknown
4020 }
4021
4022 /// [285] Wenn in diesem PIA der Code im DE7140 mit 1-08-3-AGS angegeben ist
4023 fn evaluate_285(&self, _ctx: &EvaluationContext) -> ConditionResult {
4024 // TODO: implement
4025 ConditionResult::Unknown
4026 }
4027
4028 /// [286] Wenn in diesem PIA der Code im DE7140 mit 1-08-1/2/4/5-AGS-KG
4029 fn evaluate_286(&self, _ctx: &EvaluationContext) -> ConditionResult {
4030 // TODO: implement
4031 ConditionResult::Unknown
4032 }
4033
4034 /// [287] Erlaubte Codes aus der PRICAT BGM+ Z70 (Preisblatt Netznutzung) des verantwortlichen NB
4035 fn evaluate_287(&self, _ctx: &EvaluationContext) -> ConditionResult {
4036 // TODO: implement
4037 ConditionResult::Unknown
4038 }
4039
4040 /// [288] Wenn in derselben SG8 (OBIS-Daten der Marktlokation) das PIA+5+1-b?:2.9.e vorhanden
4041 fn evaluate_288(&self, _ctx: &EvaluationContext) -> ConditionResult {
4042 // TODO: implement
4043 ConditionResult::Unknown
4044 }
4045
4046 /// [291] Wenn in derselben SG8 (Zuordnung Lokation zum Objektcode des Lokationsbündels) das RFF+Z37 vorhanden
4047 fn evaluate_291(&self, _ctx: &EvaluationContext) -> ConditionResult {
4048 // TODO: implement
4049 ConditionResult::Unknown
4050 }
4051
4052 /// [292] Es sind nur die Produkt-Codes erlaubt, die in der Codeliste der Konfigurationen im Kapitel 6.1 \"Anmeldung einer Zuordnung des LFN (UTILMD)\" in der Spalte \"Anmeldung einer Zuordnung des LFN (UTIL...
4053 fn evaluate_292(&self, ctx: &EvaluationContext) -> ConditionResult {
4054 ctx.external.evaluate("code_list_membership_check")
4055 }
4056
4057 /// [293] Wenn SG5 LOC+Z22 (ruhende Marktlokation) vorhanden
4058 fn evaluate_293(&self, _ctx: &EvaluationContext) -> ConditionResult {
4059 // TODO: implement
4060 ConditionResult::Unknown
4061 }
4062
4063 /// [294] Wenn SG5 LOC+Z18 (Netzlokation) vorhanden
4064 fn evaluate_294(&self, _ctx: &EvaluationContext) -> ConditionResult {
4065 // TODO: implement
4066 ConditionResult::Unknown
4067 }
4068
4069 /// [295] Wenn SG5 LOC+Z15 (MaBiS-Zählpunkt) nicht vorhanden
4070 fn evaluate_295(&self, _ctx: &EvaluationContext) -> ConditionResult {
4071 // TODO: implement
4072 ConditionResult::Unknown
4073 }
4074
4075 /// [296] Wenn SG5 LOC+Z20 (Technische Ressource) vorhanden
4076 fn evaluate_296(&self, _ctx: &EvaluationContext) -> ConditionResult {
4077 // TODO: implement
4078 ConditionResult::Unknown
4079 }
4080
4081 /// [297] #kv# Wenn SG5 LOC+Z18 (Netzlokation) nicht vorhanden
4082 fn evaluate_297(&self, _ctx: &EvaluationContext) -> ConditionResult {
4083 // TODO: implement
4084 ConditionResult::Unknown
4085 }
4086
4087 /// [298] Wenn SG5 LOC+Z20 (Technische Ressource) nicht vorhanden
4088 fn evaluate_298(&self, _ctx: &EvaluationContext) -> ConditionResult {
4089 // TODO: implement
4090 ConditionResult::Unknown
4091 }
4092
4093 /// [299] #kv# Wenn SG5 LOC+Z19 (Steuerbare Ressource) nicht vorhanden
4094 fn evaluate_299(&self, _ctx: &EvaluationContext) -> ConditionResult {
4095 // TODO: implement
4096 ConditionResult::Unknown
4097 }
4098
4099 /// [300] Wenn SG8 SEQ+Z15/ ZE7 (Daten der Tranche) nicht vorhanden
4100 fn evaluate_300(&self, _ctx: &EvaluationContext) -> ConditionResult {
4101 // TODO: implement
4102 ConditionResult::Unknown
4103 }
4104
4105 /// [301] Wenn BGM+E03 (Änderungsmeldung) vorhanden
4106 fn evaluate_301(&self, _ctx: &EvaluationContext) -> ConditionResult {
4107 // TODO: implement
4108 ConditionResult::Unknown
4109 }
4110
4111 /// [302] Wenn SG8 SEQ+Z08 (Profilschardaten) nicht vorhanden
4112 fn evaluate_302(&self, _ctx: &EvaluationContext) -> ConditionResult {
4113 // TODO: implement
4114 ConditionResult::Unknown
4115 }
4116
4117 /// [303] Wenn SG8 SEQ+Z21 (Profildaten) nicht vorhanden
4118 fn evaluate_303(&self, _ctx: &EvaluationContext) -> ConditionResult {
4119 // TODO: implement
4120 ConditionResult::Unknown
4121 }
4122
4123 /// [304] Wenn SG8 SEQ+Z22 (Daten der Summenzeitreihe) vorhanden
4124 fn evaluate_304(&self, _ctx: &EvaluationContext) -> ConditionResult {
4125 // TODO: implement
4126 ConditionResult::Unknown
4127 }
4128
4129 /// [305] Wenn SG8 SEQ+Z24 (Daten der Überführungszeitreihe) vorhanden
4130 fn evaluate_305(&self, _ctx: &EvaluationContext) -> ConditionResult {
4131 // TODO: implement
4132 ConditionResult::Unknown
4133 }
4134
4135 /// [306] Wenn SG5 LOC+Z22 (ruhende Marktlokation) mit derselben Zeitraum-ID im DE3224 vorhanden wie in dieser SG8 im DE1050 (Referenz auf Zeitraum-ID) des SEQ+Z58
4136 fn evaluate_306(&self, ctx: &EvaluationContext) -> ConditionResult {
4137 use std::collections::HashSet;
4138 // Collect Zeitraum-IDs from SG5 LOC+Z22 (Ruhende Marktlokation) — DE3224 at elements[1][3]
4139 let loc_z22_ids: HashSet<String> = ctx
4140 .find_segments_with_qualifier("LOC", 0, "Z22")
4141 .into_iter()
4142 .filter_map(|s| s.elements.get(1)?.get(3).cloned())
4143 .filter(|v| !v.is_empty())
4144 .collect();
4145 if loc_z22_ids.is_empty() {
4146 return ConditionResult::False;
4147 }
4148 // Check if any SG8 SEQ+Z58 has DE1050 (elements[1][0]) matching a LOC+Z22 DE3224
4149 let has_match = ctx
4150 .find_segments_with_qualifier("SEQ", 0, "Z58")
4151 .iter()
4152 .any(|s| {
4153 s.elements
4154 .get(1)
4155 .and_then(|e: &Vec<String>| e.first())
4156 .is_some_and(|v: &String| !v.is_empty() && loc_z22_ids.contains(v.as_str()))
4157 });
4158 ConditionResult::from(has_match)
4159 }
4160
4161 /// [307] Wenn SG5 LOC+Z22 (ruhende Marktlokation) mit derselben Zeitraum-ID im DE3224 nicht vorhanden wie in dieser SG8 im DE1050 (Referenz auf Zeitraum-ID) des SEQ+Z58
4162 // REVIEW: Collects Zeitraum-IDs from SG5 LOC+Z22 segments (DE3224 = elements[1][3]) and SEQ+Z58 segments (DE1050 = elements[1][0]). Returns True when any SEQ+Z58 has a Zeitraum-ID with no matching LOC+Z22 entry. Message-wide fallback since group-level Zeitraum-ID isolation is not possible without navigator. (medium confidence)
4163 fn evaluate_307(&self, ctx: &EvaluationContext) -> ConditionResult {
4164 let seq_segs = ctx.find_segments_with_qualifier("SEQ", 0, "Z58");
4165 if seq_segs.is_empty() {
4166 return ConditionResult::Unknown;
4167 }
4168 let loc_segs = ctx.find_segments_with_qualifier("LOC", 0, "Z22");
4169 let loc_z22_zeitraum_ids: Vec<&str> = loc_segs
4170 .iter()
4171 .filter_map(|s| s.elements.get(1).and_then(|e| e.get(3)).map(|v| v.as_str()))
4172 .filter(|v| !v.is_empty())
4173 .collect();
4174 ConditionResult::from(seq_segs.iter().any(|seq| {
4175 let zid = seq
4176 .elements
4177 .get(1)
4178 .and_then(|e: &Vec<String>| e.first())
4179 .map(|v| v.as_str())
4180 .unwrap_or("");
4181 !zid.is_empty() && !loc_z22_zeitraum_ids.contains(&zid)
4182 }))
4183 }
4184
4185 /// [309] Wenn SG5 LOC+Z22 (ruhende Marktlokation) nicht vorhanden
4186 fn evaluate_309(&self, _ctx: &EvaluationContext) -> ConditionResult {
4187 // TODO: implement
4188 ConditionResult::Unknown
4189 }
4190
4191 /// [314] Es sind alle OBIS-Kennzahlen gem. Codeliste der OBIS-Kennzahlen und Medien Kapitel 3 anzugeben welche an der Marktlokation erforderlich sind. Der Mindestumfang der OBIS-Kennzahlen ergibt sich aus d...
4192 fn evaluate_314(&self, ctx: &EvaluationContext) -> ConditionResult {
4193 ctx.external.evaluate("code_list_membership_check")
4194 }
4195
4196 /// [315] Wenn BGM+Z88 (Datenclearing) vorhanden
4197 fn evaluate_315(&self, ctx: &EvaluationContext) -> ConditionResult {
4198 ctx.external.evaluate("data_clearing_required")
4199 }
4200
4201 /// [316] Wenn in derselben SG8 das RFF+Z14 (Smartmeter-Gateway) nicht vorhanden
4202 fn evaluate_316(&self, ctx: &EvaluationContext) -> ConditionResult {
4203 ctx.any_group_has_qualifier_without("SEQ", 0, "Z03", "RFF", 0, "Z14", &["SG4", "SG8"])
4204 }
4205
4206 /// [317] Es ist derselbe Wert wie im DE2380 von DTM+92 (Datum Vertragsbeginn) einzutragen
4207 fn evaluate_317(&self, _ctx: &EvaluationContext) -> ConditionResult {
4208 // TODO: implement
4209 ConditionResult::Unknown
4210 }
4211
4212 /// [318] Es ist derselbe Wert wie im DE2380 von DTM+93 (Datum Vertragende) einzutragen
4213 fn evaluate_318(&self, _ctx: &EvaluationContext) -> ConditionResult {
4214 // TODO: implement
4215 ConditionResult::Unknown
4216 }
4217
4218 /// [321] Wenn im DE3155 in demselben COM der Code EM vorhanden ist
4219 fn evaluate_321(&self, _ctx: &EvaluationContext) -> ConditionResult {
4220 // TODO: implement
4221 ConditionResult::Unknown
4222 }
4223
4224 /// [322] Wenn im DE3155 in demselben COM der Code TE / FX / AJ / AL vorhanden ist
4225 fn evaluate_322(&self, _ctx: &EvaluationContext) -> ConditionResult {
4226 // TODO: implement
4227 ConditionResult::Unknown
4228 }
4229
4230 /// [323] Es sind alle OBIS-Kennzahlen gem. EDI@Energy Codeliste der OBIS-Kennzahlen und Medien für den deutschen Energiemarkt Kap. 3. anzugeben, welche an der Zähleinrichtung genutzt werden. Der Mindestum...
4231 fn evaluate_323(&self, ctx: &EvaluationContext) -> ConditionResult {
4232 ctx.external.evaluate("code_list_membership_check")
4233 }
4234
4235 /// [327] Wenn die Zeitraum-ID im DE1050 dieser SG8 SEQ, welche mit der Zeitraum-ID einer SG6 RFF+Z47/Z48/Z49 (Verwendungszeitraum der Daten) identisch ist und in deren SG das SG6 DTM+Z25 (Verwendung der Dat...
4236 // REVIEW: Step 1: Collect all SEQ DE1050 Zeitraum-IDs. Step 2: Find RFF+Z47/Z48/Z49 (Verwendungszeitraum) whose DE1156 (elements[0][2]) matches. Step 3: Check co-located DTM+Z25 DE2380 (elements[0][1]) >= threshold after normalising EDIFACT escape '?+' to '+'. Falls back to message-wide DTM search which may give false positives if multiple SG6 groups are present, but is sufficient for typical single-transaction messages. (medium confidence)
4237 fn evaluate_327(&self, ctx: &EvaluationContext) -> ConditionResult {
4238 const THRESHOLD: &str = "202212312300+00";
4239 let seq_zeitraum_ids: Vec<String> = ctx
4240 .find_segments("SEQ")
4241 .iter()
4242 .filter_map(|s| {
4243 s.elements
4244 .get(1)
4245 .and_then(|e: &Vec<String>| e.first())
4246 .cloned()
4247 })
4248 .filter(|v| !v.is_empty())
4249 .collect();
4250 if seq_zeitraum_ids.is_empty() {
4251 return ConditionResult::Unknown;
4252 }
4253 let rff_segs = ctx.find_segments("RFF");
4254 let matching_rff = rff_segs.iter().any(|rff| {
4255 let qual = rff
4256 .elements
4257 .first()
4258 .and_then(|e: &Vec<String>| e.first())
4259 .map(|v| v.as_str())
4260 .unwrap_or("");
4261 if !["Z47", "Z48", "Z49"].contains(&qual) {
4262 return false;
4263 }
4264 let zid = rff
4265 .elements
4266 .first()
4267 .and_then(|e| e.get(2))
4268 .map(|v| v.as_str())
4269 .unwrap_or("");
4270 !zid.is_empty() && seq_zeitraum_ids.iter().any(|id| id.as_str() == zid)
4271 });
4272 if !matching_rff {
4273 return ConditionResult::False;
4274 }
4275 for dtm in ctx.find_segments_with_qualifier("DTM", 0, "Z25") {
4276 let val = dtm
4277 .elements
4278 .first()
4279 .and_then(|e| e.get(1))
4280 .map(|v| v.replace("?+", "+"))
4281 .unwrap_or_default();
4282 if !val.is_empty() && val.as_str() >= THRESHOLD {
4283 return ConditionResult::True;
4284 }
4285 }
4286 ConditionResult::False
4287 }
4288
4289 /// [329] Wenn in dieser SG4 IDE+24 das STS+E01++A03: E_0096 bzw. A04:E_0097 (Status der Antwort) nicht vorhanden
4290 fn evaluate_329(&self, _ctx: &EvaluationContext) -> ConditionResult {
4291 // TODO: implement
4292 ConditionResult::Unknown
4293 }
4294
4295 /// [331] Wenn im SG8 SEQ+Z98 (Daten der Marktlokation) das SG10 CCI+6++ZA9 (Aggreg. verantw. ÜNB) nicht vorhanden
4296 fn evaluate_331(&self, _ctx: &EvaluationContext) -> ConditionResult {
4297 // TODO: implement
4298 ConditionResult::Unknown
4299 }
4300
4301 /// [332] Wenn im SG8 SEQ+Z01 (Daten der Marktlokation) mit identischer Zeitraum-ID im DE1050 wie in dieser SG8, das SG10 CCI+6++ZA9 (Aggreg. verantw. ÜNB) nicht vorhanden
4302 // REVIEW: Checks whether any SG8 instance lacks CCI+6++ZA9 (Aggregationsverantwortung ÜNB, elements[0]='6' and elements[2][0]='ZA9') in its SG10 children. With navigator: iterates SG8 instances and their SG10 children. Without navigator: falls back to message-wide CCI+6 with ZA9 check. The Zeitraum-ID cross-reference between this SG8 and the Z01 SG8 cannot be fully verified without direct SG8-level segment access via navigator, so this is an approximation that may produce false positives in multi-SG4-group messages. (medium confidence)
4303 fn evaluate_332(&self, ctx: &EvaluationContext) -> ConditionResult {
4304 let nav = match ctx.navigator {
4305 Some(n) => n,
4306 None => {
4307 if ctx.find_segments_with_qualifier("SEQ", 0, "Z01").is_empty() {
4308 return ConditionResult::Unknown;
4309 }
4310 let has_cci_za9 = ctx
4311 .find_segments_with_qualifier("CCI", 0, "6")
4312 .iter()
4313 .any(|s| {
4314 s.elements
4315 .get(2)
4316 .and_then(|e: &Vec<String>| e.first())
4317 .map(|v| v.as_str())
4318 == Some("ZA9")
4319 });
4320 return ConditionResult::from(!has_cci_za9);
4321 }
4322 };
4323 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
4324 if sg8_count == 0 {
4325 return ConditionResult::Unknown;
4326 }
4327 for sg8_idx in 0..sg8_count {
4328 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], sg8_idx, "SG10");
4329 let mut has_cci_za9 = false;
4330 for sg10_idx in 0..sg10_count {
4331 let ccis = nav.find_segments_in_child_group(
4332 "CCI",
4333 &["SG4", "SG8"],
4334 sg8_idx,
4335 "SG10",
4336 sg10_idx,
4337 );
4338 if ccis.iter().any(|s| {
4339 s.elements
4340 .first()
4341 .and_then(|e: &Vec<String>| e.first())
4342 .map(|v| v.as_str())
4343 == Some("6")
4344 && s.elements
4345 .get(2)
4346 .and_then(|e: &Vec<String>| e.first())
4347 .map(|v| v.as_str())
4348 == Some("ZA9")
4349 }) {
4350 has_cci_za9 = true;
4351 break;
4352 }
4353 }
4354 if !has_cci_za9 {
4355 return ConditionResult::True;
4356 }
4357 }
4358 ConditionResult::False
4359 }
4360
4361 /// [333] Wenn in diesem RFF \"Referenz auf die Lokationsbündelstruktur\" im DE1153 der Code Z31 \"Lokationsbündelstruktur\" vorhanden ist
4362 fn evaluate_333(&self, _ctx: &EvaluationContext) -> ConditionResult {
4363 // TODO: implement
4364 ConditionResult::Unknown
4365 }
4366
4367 /// [334] Nur MP-ID aus Sparte Gas
4368 fn evaluate_334(&self, _ctx: &EvaluationContext) -> ConditionResult {
4369 // TODO: implement
4370 ConditionResult::Unknown
4371 }
4372
4373 /// [335] Wenn in dieser SG8 im SEQ+Z58 (Zuordnung Lokation zum Objektcode des Lokationsbündels) im DE1050 eine Zeitraum-ID angegeben wird, wie in einer SG8 SEQ+Z78 RFF+Z31 (Referenz auf die Lokationsbünde...
4374 // REVIEW: Collects Zeitraum-IDs from SEQ+Z58 DE1050 (elements[1][0]). Verifies an SG8 with SEQ+Z78 exists (entry for Lokationsbündelstruktur). Collects IDs from RFF+Z31 DE1154 (elements[0][1]) and checks if any SEQ+Z58 Zeitraum-ID matches. Co-location of RFF+Z31 with SEQ+Z78 in the same SG8 instance is approximated message-wide; exact co-location verification would require navigator SG8-level segment access. (medium confidence)
4375 fn evaluate_335(&self, ctx: &EvaluationContext) -> ConditionResult {
4376 let z58_ids: Vec<String> = ctx
4377 .find_segments_with_qualifier("SEQ", 0, "Z58")
4378 .iter()
4379 .filter_map(|s| {
4380 s.elements
4381 .get(1)
4382 .and_then(|e: &Vec<String>| e.first())
4383 .cloned()
4384 })
4385 .filter(|v| !v.is_empty())
4386 .collect();
4387 if z58_ids.is_empty() {
4388 return ConditionResult::Unknown;
4389 }
4390 if ctx.find_segments_with_qualifier("SEQ", 0, "Z78").is_empty() {
4391 return ConditionResult::False;
4392 }
4393 let rff_z31_ids: Vec<String> = ctx
4394 .find_segments("RFF")
4395 .iter()
4396 .filter(|rff| {
4397 rff.elements
4398 .first()
4399 .and_then(|e: &Vec<String>| e.first())
4400 .map(|v| v.as_str())
4401 == Some("Z31")
4402 })
4403 .filter_map(|rff| rff.elements.first().and_then(|e| e.get(1)).cloned())
4404 .filter(|v| !v.is_empty())
4405 .collect();
4406 ConditionResult::from(z58_ids.iter().any(|id| rff_z31_ids.contains(id)))
4407 }
4408
4409 /// [336] Wenn in Änderungsmeldung gefüllt
4410 fn evaluate_336(&self, _ctx: &EvaluationContext) -> ConditionResult {
4411 // TODO: implement
4412 ConditionResult::Unknown
4413 }
4414
4415 /// [337] Wenn SG10 CCI+++ZB4 (Bezeichnung der Summenzeitreihe) CAV+Z95/ Z96 vorhanden
4416 fn evaluate_337(&self, _ctx: &EvaluationContext) -> ConditionResult {
4417 // TODO: implement
4418 ConditionResult::Unknown
4419 }
4420
4421 /// [338] Wenn CCI+++ZB4 (Bezeichnung der Summenzeitreihe) CAV+Z95/ Z96/ Z97/ Z99/ ZA1/ ZA3/ ZA4/ZG7 vorhanden
4422 fn evaluate_338(&self, _ctx: &EvaluationContext) -> ConditionResult {
4423 // TODO: implement
4424 ConditionResult::Unknown
4425 }
4426
4427 /// [339] Wenn CCI+++ZB4 (Bezeichnung der Summenzeitreihe) CAV+Z97/ Z98/ Z99/ ZA0/ ZA1/ ZA2/ ZA3/ ZA6/ ZG7 vorhanden
4428 fn evaluate_339(&self, _ctx: &EvaluationContext) -> ConditionResult {
4429 // TODO: implement
4430 ConditionResult::Unknown
4431 }
4432
4433 /// [340] Wenn CCI+++ZB4 (Bezeichnung der Summenzeitreihe) CAV+Z95/ Z97/ Z98/ Z99/ ZA1/ ZA2/ ZA3/ ZA4/ ZA5/ ZA6 vorhanden
4434 fn evaluate_340(&self, _ctx: &EvaluationContext) -> ConditionResult {
4435 // TODO: implement
4436 ConditionResult::Unknown
4437 }
4438
4439 /// [341] Wenn CCI+++ZB4 (Bezeichnung der Summenzeitreihe) CAV+Z96/ ZA0/ ZG7 vorhanden
4440 fn evaluate_341(&self, _ctx: &EvaluationContext) -> ConditionResult {
4441 // TODO: implement
4442 ConditionResult::Unknown
4443 }
4444
4445 /// [342] Wenn aktiver MaBiS-ZP für den Betrachtungszeitraum vorhanden
4446 fn evaluate_342(&self, _ctx: &EvaluationContext) -> ConditionResult {
4447 // TODO: implement
4448 ConditionResult::Unknown
4449 }
4450
4451 /// [344] Wenn in dieser SG8 das SG10 CCI+++ZB4 (Bezeichnung der Summenzeitreihe) CAV+ZF1 (Netzgangzeitreihe (NGZ)) vorhanden
4452 fn evaluate_344(&self, _ctx: &EvaluationContext) -> ConditionResult {
4453 // TODO: implement
4454 ConditionResult::Unknown
4455 }
4456
4457 /// [345] Wenn SG5 LOC+Z17 (Messlokation) vorhanden
4458 fn evaluate_345(&self, _ctx: &EvaluationContext) -> ConditionResult {
4459 // TODO: implement
4460 ConditionResult::Unknown
4461 }
4462
4463 /// [346] Wenn SG10 CCI+++E13 (Zählertyp) CAV+MME (mME) vorhanden
4464 fn evaluate_346(&self, _ctx: &EvaluationContext) -> ConditionResult {
4465 // TODO: implement
4466 ConditionResult::Unknown
4467 }
4468
4469 /// [347] Wenn SG5 LOC+Z16 (Marktlokation) nicht vorhanden
4470 fn evaluate_347(&self, _ctx: &EvaluationContext) -> ConditionResult {
4471 // TODO: implement
4472 ConditionResult::Unknown
4473 }
4474
4475 /// [348] Wenn SG5 LOC+Z21 (Tranche) nicht vorhanden
4476 fn evaluate_348(&self, _ctx: &EvaluationContext) -> ConditionResult {
4477 // TODO: implement
4478 ConditionResult::Unknown
4479 }
4480
4481 /// [349] Wenn SG5 LOC+Z17 (Messlokation) nicht vorhanden
4482 fn evaluate_349(&self, _ctx: &EvaluationContext) -> ConditionResult {
4483 // TODO: implement
4484 ConditionResult::Unknown
4485 }
4486
4487 /// [350] Wenn SG8 SEQ+Z78/ZD5 RFF+Z31 (Referenz auf die Lokationsbündelstruktur) vorhanden
4488 fn evaluate_350(&self, _ctx: &EvaluationContext) -> ConditionResult {
4489 // TODO: implement
4490 ConditionResult::Unknown
4491 }
4492
4493 /// [351] Wenn SG4 STS+E01++A04/ A05 /A13 /A14 (Status der Antwort) vorhanden
4494 fn evaluate_351(&self, _ctx: &EvaluationContext) -> ConditionResult {
4495 // TODO: implement
4496 ConditionResult::Unknown
4497 }
4498
4499 /// [352] Wenn SG4 STS++A05/ A06/ A14 /A15 (Status der Antwort) vorhanden
4500 fn evaluate_352(&self, _ctx: &EvaluationContext) -> ConditionResult {
4501 // TODO: implement
4502 ConditionResult::Unknown
4503 }
4504
4505 /// [355] Wenn SG4 STS+E01++A45 (Status der Antwort) vorhanden
4506 fn evaluate_355(&self, _ctx: &EvaluationContext) -> ConditionResult {
4507 // TODO: implement
4508 ConditionResult::Unknown
4509 }
4510
4511 /// [356] Wenn SG4 STS+E01++A50 (Status der Antwort) vorhanden
4512 fn evaluate_356(&self, _ctx: &EvaluationContext) -> ConditionResult {
4513 // TODO: implement
4514 ConditionResult::Unknown
4515 }
4516
4517 /// [357] Wenn SG4 STS+E01++A03/ A09/ A12/ A17 (Status der Antwort) vorhanden
4518 fn evaluate_357(&self, _ctx: &EvaluationContext) -> ConditionResult {
4519 // TODO: implement
4520 ConditionResult::Unknown
4521 }
4522
4523 /// [358] Wenn SG4 STS+E01++A06 (Status der Antwort) vorhanden
4524 fn evaluate_358(&self, _ctx: &EvaluationContext) -> ConditionResult {
4525 // TODO: implement
4526 ConditionResult::Unknown
4527 }
4528
4529 /// [359] Es sind nur Antwortcodes aus dem Cluster Ablehnung erlaubt
4530 fn evaluate_359(&self, _ctx: &EvaluationContext) -> ConditionResult {
4531 // TODO: implement
4532 ConditionResult::Unknown
4533 }
4534
4535 /// [360] Es sind nur Antwortcodes aus dem Cluster Zustimmung erlaubt
4536 fn evaluate_360(&self, _ctx: &EvaluationContext) -> ConditionResult {
4537 // TODO: implement
4538 ConditionResult::Unknown
4539 }
4540
4541 /// [363] Wenn SG4 STS+E01++A50 (Status der Antwort) vorhanden
4542 fn evaluate_363(&self, _ctx: &EvaluationContext) -> ConditionResult {
4543 // TODO: implement
4544 ConditionResult::Unknown
4545 }
4546
4547 /// [365] Wenn in dieser SG4 IDE+24 das STS+E01++A04:E_0047/E_0014 bzw. A03:E_0049/E_0004 (Status der Antwort) nicht vorhanden
4548 fn evaluate_365(&self, _ctx: &EvaluationContext) -> ConditionResult {
4549 // TODO: implement
4550 ConditionResult::Unknown
4551 }
4552
4553 /// [366] Bis auf den Code A30 sind alle Codes aus EBD E_0624 im Cluster Ablehnung erlaubt
4554 fn evaluate_366(&self, _ctx: &EvaluationContext) -> ConditionResult {
4555 // TODO: implement
4556 ConditionResult::Unknown
4557 }
4558
4559 /// [367] Wenn SG4 STS+E01++A05/ A14 (Status der Antwort) vorhanden
4560 fn evaluate_367(&self, _ctx: &EvaluationContext) -> ConditionResult {
4561 // TODO: implement
4562 ConditionResult::Unknown
4563 }
4564
4565 /// [368] Bis auf den Code A41 sind alle Codes aus EBD E_0624 im Cluster Ablehnung erlaubt
4566 fn evaluate_368(&self, _ctx: &EvaluationContext) -> ConditionResult {
4567 // TODO: implement
4568 ConditionResult::Unknown
4569 }
4570
4571 /// [370] Wenn SG10 CAV+TLS/TES/BIT/GET/GAT/SOT/WNT/WFT/WAT
4572 fn evaluate_370(&self, _ctx: &EvaluationContext) -> ConditionResult {
4573 // TODO: implement
4574 ConditionResult::Unknown
4575 }
4576
4577 /// [371] Wenn SG8 SEQ+Z38 (Referenzprofildaten) nicht vorhanden
4578 fn evaluate_371(&self, _ctx: &EvaluationContext) -> ConditionResult {
4579 // TODO: implement
4580 ConditionResult::Unknown
4581 }
4582
4583 /// [372] Wenn SG10 CAV+TES/BIT/GET/GAT/SOT/WNT/WFT/WAT vorhanden
4584 fn evaluate_372(&self, _ctx: &EvaluationContext) -> ConditionResult {
4585 // TODO: implement
4586 ConditionResult::Unknown
4587 }
4588
4589 /// [373] Wenn ein Referenzprofil an der Marktlokation vorhanden ist
4590 fn evaluate_373(&self, _ctx: &EvaluationContext) -> ConditionResult {
4591 // TODO: implement
4592 ConditionResult::Unknown
4593 }
4594
4595 /// [375] Für die ID im SG5 LOC+Z15 (MaBiS-Zählpunkt) DE3225, wenn SG8+Z24 (Daten der Überführungszeitreihe) nicht vorhanden
4596 fn evaluate_375(&self, _ctx: &EvaluationContext) -> ConditionResult {
4597 // TODO: implement
4598 ConditionResult::Unknown
4599 }
4600
4601 /// [376] Für die ID im SG5 LOC+Z15 (MaBiS-Zählpunkt) DE3225, wenn SG8+Z22 (Daten der Summenzeitreihe) nicht vorhanden
4602 fn evaluate_376(&self, _ctx: &EvaluationContext) -> ConditionResult {
4603 // TODO: implement
4604 ConditionResult::Unknown
4605 }
4606
4607 /// [377] Wenn SG10 CCI+15++Z21 (Überführungszeitreihentyp) CAV+AUS vorhanden
4608 // REVIEW: Checks if any SG8 has a child SG10 with CCI[0]='15' and CCI[2]='Z21' (Überführungszeitreihentyp) followed by CAV with value 'AUS'. Follows the navigator pattern from example 10 exactly. (medium confidence)
4609 fn evaluate_377(&self, ctx: &EvaluationContext) -> ConditionResult {
4610 let nav = match ctx.navigator {
4611 Some(n) => n,
4612 None => return ctx.has_qualified_value("CAV", 0, "AUS", 0, 0, &["AUS"]),
4613 };
4614 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
4615 for i in 0..sg8_count {
4616 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
4617 for j in 0..sg10_count {
4618 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
4619 let has_cci = ccis.iter().any(|s| {
4620 s.elements
4621 .first()
4622 .and_then(|e: &Vec<String>| e.first())
4623 .is_some_and(|v: &String| v == "15")
4624 && s.elements
4625 .get(2)
4626 .and_then(|e: &Vec<String>| e.first())
4627 .is_some_and(|v: &String| v == "Z21")
4628 });
4629 if has_cci {
4630 let cavs =
4631 nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
4632 if cavs.iter().any(|s| {
4633 s.elements
4634 .first()
4635 .and_then(|e: &Vec<String>| e.first())
4636 .is_some_and(|v: &String| v == "AUS")
4637 }) {
4638 return ConditionResult::True;
4639 }
4640 }
4641 }
4642 }
4643 ConditionResult::False
4644 }
4645
4646 /// [378] Wenn SG10 CCI+15++Z21 (Überführungszeitreihentyp) CAV+AUS nicht vorhanden
4647 // REVIEW: Logical negation of condition 377: True when CCI+15++Z21 CAV+AUS is NOT present in any SG8's SG10 child. Iterates all instances and returns True only if the combination is never found. (medium confidence)
4648 fn evaluate_378(&self, ctx: &EvaluationContext) -> ConditionResult {
4649 let nav = match ctx.navigator {
4650 Some(n) => n,
4651 None => {
4652 let r = ctx.has_qualified_value("CAV", 0, "AUS", 0, 0, &["AUS"]);
4653 return match r {
4654 ConditionResult::True => ConditionResult::False,
4655 ConditionResult::False => ConditionResult::True,
4656 ConditionResult::Unknown => ConditionResult::Unknown,
4657 };
4658 }
4659 };
4660 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
4661 for i in 0..sg8_count {
4662 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
4663 for j in 0..sg10_count {
4664 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
4665 let has_cci = ccis.iter().any(|s| {
4666 s.elements
4667 .first()
4668 .and_then(|e: &Vec<String>| e.first())
4669 .is_some_and(|v: &String| v == "15")
4670 && s.elements
4671 .get(2)
4672 .and_then(|e: &Vec<String>| e.first())
4673 .is_some_and(|v: &String| v == "Z21")
4674 });
4675 if has_cci {
4676 let cavs =
4677 nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
4678 if cavs.iter().any(|s| {
4679 s.elements
4680 .first()
4681 .and_then(|e: &Vec<String>| e.first())
4682 .is_some_and(|v: &String| v == "AUS")
4683 }) {
4684 return ConditionResult::False;
4685 }
4686 }
4687 }
4688 }
4689 ConditionResult::True
4690 }
4691
4692 /// [379] Wenn SG10 CCI+15++Z21 (Überführungszeitreihentyp) CAV+ Code für EEG-Überführungszeitreihen (ausgenommen AU1) vorhanden
4693 fn evaluate_379(&self, _ctx: &EvaluationContext) -> ConditionResult {
4694 // TODO: implement
4695 ConditionResult::Unknown
4696 }
4697
4698 /// [380] Wenn SG10 CCI+15++Z21 (Überführungszeitreihentyp) CAV+AUS/AU1 vorhanden
4699 // REVIEW: Variant of condition 377 that accepts either 'AUS' or 'AU1' as the CAV value for the Überführungszeitreihentyp. Same SG8→SG10 parent-child navigation, broadened CAV value check. (medium confidence)
4700 fn evaluate_380(&self, ctx: &EvaluationContext) -> ConditionResult {
4701 let nav = match ctx.navigator {
4702 Some(n) => n,
4703 None => {
4704 return ctx.any_group_has_any_qualifier("CAV", 0, &["AUS", "AU1"], &["SG4", "SG8"])
4705 }
4706 };
4707 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
4708 for i in 0..sg8_count {
4709 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
4710 for j in 0..sg10_count {
4711 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
4712 let has_cci = ccis.iter().any(|s| {
4713 s.elements
4714 .first()
4715 .and_then(|e: &Vec<String>| e.first())
4716 .is_some_and(|v: &String| v == "15")
4717 && s.elements
4718 .get(2)
4719 .and_then(|e: &Vec<String>| e.first())
4720 .is_some_and(|v: &String| v == "Z21")
4721 });
4722 if has_cci {
4723 let cavs =
4724 nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
4725 if cavs.iter().any(|s| {
4726 s.elements
4727 .first()
4728 .and_then(|e: &Vec<String>| e.first())
4729 .is_some_and(|v: &String| v == "AUS" || v == "AU1")
4730 }) {
4731 return ConditionResult::True;
4732 }
4733 }
4734 }
4735 }
4736 ConditionResult::False
4737 }
4738
4739 /// [384] Wenn in derselben SG8 SG10 CCI+Z37++ZD1 (Basis zur Bildung der Tranchengröße) (Prozentual) vorhanden
4740 fn evaluate_384(&self, _ctx: &EvaluationContext) -> ConditionResult {
4741 // TODO: implement
4742 ConditionResult::Unknown
4743 }
4744
4745 /// [386] Wenn mehr als eine SG8 SEQ+Z02/ ZE3 (OBIS-Daten der Marktlokation) mit einer OBIS-Kennzahl für Energiemenge im PIA+5 vorhanden
4746 fn evaluate_386(&self, _ctx: &EvaluationContext) -> ConditionResult {
4747 // TODO: implement
4748 ConditionResult::Unknown
4749 }
4750
4751 /// [387] Wenn in derselben SG8 (OBIS Daten der Marktlokation) eine OBIS-Kennzahl für Energiemenge im PIA+5 vorhanden und es sich lt. Codeliste OBIS um eine OBIS mit zugeordneter Zählzeit handelt (Tarif: e...
4752 fn evaluate_387(&self, _ctx: &EvaluationContext) -> ConditionResult {
4753 // TODO: implement
4754 ConditionResult::Unknown
4755 }
4756
4757 /// [388] Segmentgruppe ist mindesten einmal für jede Zeitraum-ID aus dem DE1156 der SG6 RFF+Z49 (Verwendungszeitraum der Daten: \"Gültige Daten\") anzugeben, wenn in diesem Zeitraum Blindarbeit bzw. -leis...
4758 fn evaluate_388(&self, _ctx: &EvaluationContext) -> ConditionResult {
4759 // TODO: implement
4760 ConditionResult::Unknown
4761 }
4762
4763 /// [391] Wenn in derselben SG8 SEQ+Z20 (OBIS Daten der Zähleinrichtung / Smartmeter-Gateway) eine OBIS-Kennzahl für Zählerstand im PIA+5 vorhanden und es sich lt. Codeliste OBIS um eine OBIS mit zugeordn...
4764 fn evaluate_391(&self, _ctx: &EvaluationContext) -> ConditionResult {
4765 // TODO: implement
4766 ConditionResult::Unknown
4767 }
4768
4769 /// [392] Wenn in diesem PIA der Code im Format n1-n2-n1 angegeben ist
4770 fn evaluate_392(&self, _ctx: &EvaluationContext) -> ConditionResult {
4771 // TODO: implement
4772 ConditionResult::Unknown
4773 }
4774
4775 /// [393] Wenn in diesem PIA der Code im Format n1-n2-n1-n3 angegeben ist
4776 fn evaluate_393(&self, _ctx: &EvaluationContext) -> ConditionResult {
4777 // TODO: implement
4778 ConditionResult::Unknown
4779 }
4780
4781 /// [394] Wenn in diesem PIA der Code im Format n1-n2-n1-n8-n2 angegeben ist
4782 fn evaluate_394(&self, _ctx: &EvaluationContext) -> ConditionResult {
4783 // TODO: implement
4784 ConditionResult::Unknown
4785 }
4786
4787 /// [395] Wenn in diesem PIA der Code im Format n1-n2-n1-n8 angegeben ist
4788 fn evaluate_395(&self, _ctx: &EvaluationContext) -> ConditionResult {
4789 // TODO: implement
4790 ConditionResult::Unknown
4791 }
4792
4793 /// [396] Wenn in derselben SG8 SEQ+Z02/ ZA1/ ZA2 (OBIS-Daten der Marktlokation) eine OBIS-Kennzahl für Wirkarbeit und 1/4 Stunde im PIA+5 vorhanden
4794 fn evaluate_396(&self, _ctx: &EvaluationContext) -> ConditionResult {
4795 // TODO: implement
4796 ConditionResult::Unknown
4797 }
4798
4799 /// [397] Wenn in diesem PIA der Code im DE7140 mit 1-08-1/1-08-4 beginnt
4800 fn evaluate_397(&self, _ctx: &EvaluationContext) -> ConditionResult {
4801 // TODO: implement
4802 ConditionResult::Unknown
4803 }
4804
4805 /// [398] Wenn in diesem PIA der Code im DE7140 mit 1-08-2/1-08-5 beginnt
4806 fn evaluate_398(&self, _ctx: &EvaluationContext) -> ConditionResult {
4807 // TODO: implement
4808 ConditionResult::Unknown
4809 }
4810
4811 /// [399] Wenn im SG8 SEQ+Z78 mit identischer Zeitraum-ID im DE1050 wie im DE3224 dieses Segments, das RFF+Z31 (Lokationsbündelstruktur) im DE1153 der Code Z31 (Lokationsbündelstruktur) vorhanden, und im D...
4812 // REVIEW: Condition is True when an SG8 SEQ+Z78 exists whose Zeitraum-ID (DE1050) matches DE3224 of the current LOC segment (accessed via SG5 group navigator as LOC.C517.DE3224 = elements[1][3]), AND that Z78 SG8 has RFF+Z31 with a DE1154 value that is NOT the pauschal code 9992000000018. This identifies bundle structures that reference a non-pauschal Lokationsbündelstruktur. (medium confidence)
4813 fn evaluate_399(&self, ctx: &EvaluationContext) -> ConditionResult {
4814 let nav = match ctx.navigator() {
4815 Some(n) => n,
4816 None => return ConditionResult::Unknown,
4817 };
4818 // Collect DE3224 values from LOC segments in SG5 — LOC.C517.DE3224 = elements[1][3]
4819 // These serve as the Zeitraum-IDs referenced by the condition's "dieses Segments"
4820 let sg5_count = nav.group_instance_count(&["SG4", "SG5"]);
4821 let mut loc_zeitraum_ids: Vec<String> = Vec::new();
4822 for i in 0..sg5_count {
4823 let locs = nav.find_segments_in_group("LOC", &["SG4", "SG5"], i);
4824 for loc in &locs {
4825 if let Some(zid) = loc.elements.get(1).and_then(|e| e.get(3)) {
4826 if !zid.is_empty() {
4827 loc_zeitraum_ids.push(zid.clone());
4828 }
4829 }
4830 }
4831 }
4832 if loc_zeitraum_ids.is_empty() {
4833 return ConditionResult::Unknown;
4834 }
4835 let pauschal_id = "9992000000018";
4836 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
4837 // Find any Z78 SG8 whose Zeitraum-ID (SEQ.C286.DE1050) matches a LOC DE3224
4838 // and that has RFF+Z31 with DE1154 != pauschal_id
4839 for i in 0..sg8_count {
4840 let seqs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
4841 for seq in &seqs {
4842 if !seq
4843 .elements
4844 .first()
4845 .and_then(|e| e.first())
4846 .is_some_and(|v| v == "Z78")
4847 {
4848 continue;
4849 }
4850 let zid = seq
4851 .elements
4852 .get(1)
4853 .and_then(|e| e.first())
4854 .map(|s| s.as_str())
4855 .unwrap_or("");
4856 if !loc_zeitraum_ids.iter().any(|z| z == zid) {
4857 continue;
4858 }
4859 // Matching Z78 SG8 found — check RFF+Z31 DE1154
4860 let rffs = nav.find_segments_in_group("RFF", &["SG4", "SG8"], i);
4861 for rff in &rffs {
4862 let qual = rff
4863 .elements
4864 .first()
4865 .and_then(|e| e.first())
4866 .map(|v| v.as_str())
4867 .unwrap_or("");
4868 if qual == "Z31" {
4869 let id = rff
4870 .elements
4871 .first()
4872 .and_then(|e| e.get(1))
4873 .map(|v| v.as_str())
4874 .unwrap_or("");
4875 let normalized = id.replace(' ', "");
4876 if !normalized.is_empty() && normalized != pauschal_id {
4877 return ConditionResult::True;
4878 }
4879 }
4880 }
4881 }
4882 }
4883 ConditionResult::False
4884 }
4885
4886 /// [401] Wenn dieses DTM+Z25 (Verwendung der Daten ab) nicht im SG6 RFF+Z49/ Z53 (Verwendungszeitraum der Daten: Gültige Daten/ Keine Daten) mit der Zeitraum ID \"1\" im DE1156 ist, muss das Datum dem DTM+...
4887 fn evaluate_401(&self, _ctx: &EvaluationContext) -> ConditionResult {
4888 // TODO: implement
4889 ConditionResult::Unknown
4890 }
4891
4892 /// [402] Wenn in derselben SG8 (OBIS-Daten der Zähleinrichtung / Smartmeter-Gateway) eine OBIS-Kennzahl der Werteart \"Zählerstand\" im PIA+5 vorhanden
4893 fn evaluate_402(&self, _ctx: &EvaluationContext) -> ConditionResult {
4894 // TODO: implement
4895 ConditionResult::Unknown
4896 }
4897
4898 /// [403] Wenn nicht dieselbe MP-ID in SG2 NAD+MS (Nachrichtensender) und im SG8 SEQ+Z01 (Daten der Marktlokation) SG10 CCI+++ZB3 (Zugeordnete Marktpartner) CAV+Z91 (Messtellenbetreiber) vorhanden
4899 // REVIEW: Gets NAD+MS MP-ID from SG2 (elements[1][0]), then navigates all SG8→SG10 instances looking for CCI with elements[2][0]='ZB3' (Zugeordnete Marktpartner) and CAV with elements[0][0]='Z91' (Messstellenbetreiber). Compares the CAV+Z91 MP-ID (elements[0][1]) with the sender MP-ID. Returns True when they differ (not the same). Note: SEQ+Z01 filter on the parent SG8 is omitted because `find_segments_in_child_group` only accesses child groups, not the parent SG8 segments; the Z91 MSB identity is message-consistent regardless. (medium confidence)
4900 fn evaluate_403(&self, ctx: &EvaluationContext) -> ConditionResult {
4901 let sender_mp_id: String = match ctx.find_segments_with_qualifier("NAD", 0, "MS").first() {
4902 Some(nad) => match nad.elements.get(1).and_then(|e: &Vec<String>| e.first()) {
4903 Some(id) if !id.is_empty() => id.clone(),
4904 _ => return ConditionResult::Unknown,
4905 },
4906 None => return ConditionResult::Unknown,
4907 };
4908 let nav = match ctx.navigator {
4909 Some(n) => n,
4910 None => return ConditionResult::Unknown,
4911 };
4912 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
4913 for i in 0..sg8_count {
4914 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
4915 for j in 0..sg10_count {
4916 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
4917 let has_cci_zb3 = ccis.iter().any(|s| {
4918 s.elements
4919 .get(2)
4920 .and_then(|e: &Vec<String>| e.first())
4921 .is_some_and(|v: &String| v == "ZB3")
4922 });
4923 if !has_cci_zb3 {
4924 continue;
4925 }
4926 let cavs = nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
4927 for cav in &cavs {
4928 if cav
4929 .elements
4930 .first()
4931 .and_then(|e: &Vec<String>| e.first())
4932 .is_some_and(|v: &String| v == "Z91")
4933 {
4934 if let Some(msb_id) = cav.elements.first().and_then(|e| e.get(1)) {
4935 if !msb_id.is_empty() {
4936 return ConditionResult::from(
4937 sender_mp_id.as_str() != msb_id.as_str(),
4938 );
4939 }
4940 }
4941 }
4942 }
4943 }
4944 }
4945 ConditionResult::Unknown
4946 }
4947
4948 /// [404] Wenn nicht dieselbe MP-ID in SG2 NAD+MR (Nachrichtenempfänger) und im SG8 SEQ+Z01/ Z98 (Daten der Marktlokation) SG10 CCI+++ZB3 (Zugeordnete Marktpartner) CAV+Z91 (Messtellenbetreiber) vorhanden
4949 // REVIEW: Reads NAD+MR MP-ID from elements[1][0], then iterates all SG8 SG10 children looking for CCI with elements[2][0]==ZB3 and CAV with elements[0][0]==Z91 where the MP-ID (elements[0][1]) matches. Returns False if same MP-ID found (condition 'not same' fails), True otherwise. Approximation: cannot filter SG8 instances by SEQ+Z01/Z98 without find_segments_in_group; checks all SG8 SG10 children. This is acceptable since CCI+ZB3 CAV+Z91 patterns in other SG8 types would still represent valid MSB assignments to compare against. (medium confidence)
4950 fn evaluate_404(&self, ctx: &EvaluationContext) -> ConditionResult {
4951 let mr_nads = ctx.find_segments_with_qualifier("NAD", 0, "MR");
4952 let mr_mp_id = match mr_nads.first() {
4953 Some(nad) => nad
4954 .elements
4955 .get(1)
4956 .and_then(|e: &Vec<String>| e.first())
4957 .cloned()
4958 .unwrap_or_default(),
4959 None => return ConditionResult::Unknown,
4960 };
4961 if mr_mp_id.is_empty() {
4962 return ConditionResult::Unknown;
4963 }
4964
4965 let nav = match ctx.navigator {
4966 Some(n) => n,
4967 None => {
4968 let cavs = ctx.find_segments("CAV");
4969 let same_id_exists = cavs.iter().any(|s| {
4970 s.elements
4971 .first()
4972 .and_then(|e: &Vec<String>| e.first())
4973 .is_some_and(|v: &String| v == "Z91")
4974 && s.elements
4975 .first()
4976 .and_then(|e| e.get(1))
4977 .is_some_and(|v: &String| v == &mr_mp_id)
4978 });
4979 return ConditionResult::from(!same_id_exists);
4980 }
4981 };
4982
4983 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
4984 for i in 0..sg8_count {
4985 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
4986 for j in 0..sg10_count {
4987 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
4988 let has_cci_zb3 = ccis.iter().any(|s| {
4989 s.elements
4990 .get(2)
4991 .and_then(|e: &Vec<String>| e.first())
4992 .is_some_and(|v: &String| v == "ZB3")
4993 });
4994 if !has_cci_zb3 {
4995 continue;
4996 }
4997 let cavs = nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
4998 for cav in &cavs {
4999 if cav
5000 .elements
5001 .first()
5002 .and_then(|e: &Vec<String>| e.first())
5003 .is_some_and(|v: &String| v == "Z91")
5004 {
5005 let cav_mp_id = cav
5006 .elements
5007 .first()
5008 .and_then(|e| e.get(1))
5009 .map(|s| s.as_str())
5010 .unwrap_or("");
5011 if cav_mp_id == mr_mp_id.as_str() {
5012 return ConditionResult::False;
5013 }
5014 }
5015 }
5016 }
5017 }
5018
5019 ConditionResult::True
5020 }
5021
5022 /// [405] Wenn in derselben SG8 SEQ+Z02/ZA1/ZA2 (OBIS-Daten der Marktlokation) eine OBIS-Kennzahl für Wirkarbeit und kumuliert im PIA+5 vorhanden
5023 fn evaluate_405(&self, _ctx: &EvaluationContext) -> ConditionResult {
5024 // TODO: implement
5025 ConditionResult::Unknown
5026 }
5027
5028 /// [406] Wenn in derselben SG8 SEQ+Z02/ZA1/ZA2 (OBIS-Daten der Marktlokation) eine OBIS-Kennzahl für Wirkarbeit und höchste 1/4 Stunde im Monat im PIA+5 vorhanden
5029 fn evaluate_406(&self, _ctx: &EvaluationContext) -> ConditionResult {
5030 // TODO: implement
5031 ConditionResult::Unknown
5032 }
5033
5034 /// [407] Wenn in derselben SG8 SEQ+Z02/ZA1/ZA2 (OBIS-Daten der Marktlokation) eine OBIS-Kennzahl für Blindarbeit im PIA+5 vorhanden
5035 fn evaluate_407(&self, _ctx: &EvaluationContext) -> ConditionResult {
5036 // TODO: implement
5037 ConditionResult::Unknown
5038 }
5039
5040 /// [408] Wenn eine SG8 SEQ+Z02 (OBIS-Daten der Marktlokation), mit dem RFF+Z18 (Referenz auf die ID der Marktlokation) auf die gleiche ID einer Marktlokation referenziert wie das RFF+Z18 (Referenz auf die I...
5041 fn evaluate_408(&self, _ctx: &EvaluationContext) -> ConditionResult {
5042 // TODO: implement
5043 ConditionResult::Unknown
5044 }
5045
5046 /// [409] Wenn keine SG8 SEQ+Z02 (OBIS-Daten der Marktlokation), mit dem RFF+Z18 (Referenz auf die ID der Marktlokation) auf die gleiche ID einer Marktlokation referenziert wie das RFF+Z18 (Referenz auf die ...
5047 fn evaluate_409(&self, _ctx: &EvaluationContext) -> ConditionResult {
5048 // TODO: implement
5049 ConditionResult::Unknown
5050 }
5051
5052 /// [410] Wenn eine SG8 SEQ+Z02 (OBIS-Daten der Marktlokation), mit dem RFF+Z18 (Referenz auf die ID der Marktlokation) auf die gleiche ID einer Marktlokation referenziert wie das RFF+Z18 (Referenz auf die I...
5053 fn evaluate_410(&self, _ctx: &EvaluationContext) -> ConditionResult {
5054 // TODO: implement
5055 ConditionResult::Unknown
5056 }
5057
5058 /// [411] Wenn keine SG8 SEQ+Z02 (OBIS-Daten der Marktlokation), mit dem RFF+Z18 (Referenz auf die ID der Marktlokation) auf die gleiche ID einer Marktlokation referenziert wie das RFF+Z18 (Referenz auf die ...
5059 fn evaluate_411(&self, _ctx: &EvaluationContext) -> ConditionResult {
5060 // TODO: implement
5061 ConditionResult::Unknown
5062 }
5063
5064 /// [412] Es sind ausschließlich Konfigurationsprodukt-Codes der \"EDI@Energy Codeliste der Konfigurationen\" aus Kapitel 4.2 Konfigurationsprodukte Leistungskurvendefinition erlaubt
5065 fn evaluate_412(&self, ctx: &EvaluationContext) -> ConditionResult {
5066 ctx.external.evaluate("code_list_membership_check")
5067 }
5068
5069 /// [413] Wenn eine SG8 SEQ+Z02/ZA1/ZA2 (OBIS-Daten der Marktlokation) mit einer OBIS-Kennzahl für Wirkarbeit und kumuliert im PIA+5 vorhanden
5070 fn evaluate_413(&self, _ctx: &EvaluationContext) -> ConditionResult {
5071 // TODO: implement
5072 ConditionResult::Unknown
5073 }
5074
5075 /// [414] Wenn keine SG8 SEQ+Z02/ZA1/ZA2 (OBIS-Daten der Marktlokation) mit einer OBIS-Kennzahl für Wirkarbeit und kumuliert im PIA+5 vorhanden
5076 fn evaluate_414(&self, _ctx: &EvaluationContext) -> ConditionResult {
5077 // TODO: implement
5078 ConditionResult::Unknown
5079 }
5080
5081 /// [415] Wenn eine weitere SG8 SEQ+Z02/ZA1/ZA2 (OBIS-Daten der Marktlokation) mit einer OBIS-Kennzahl für Wirkarbeit und 1/4 Stunde im PIA+5 vorhanden
5082 fn evaluate_415(&self, _ctx: &EvaluationContext) -> ConditionResult {
5083 // TODO: implement
5084 ConditionResult::Unknown
5085 }
5086
5087 /// [416] Wenn keine SG8 SEQ+Z02/ZA1/ZA2 (OBIS-Daten der Marktlokation) mit einer OBIS-Kennzahl für Wirkarbeit und 1/4 Stunde im PIA+5 vorhanden
5088 fn evaluate_416(&self, _ctx: &EvaluationContext) -> ConditionResult {
5089 // TODO: implement
5090 ConditionResult::Unknown
5091 }
5092
5093 /// [417] Wenn für den erforderlichen Wert keine Zählzeit benötigt wird
5094 fn evaluate_417(&self, _ctx: &EvaluationContext) -> ConditionResult {
5095 // TODO: implement
5096 ConditionResult::Unknown
5097 }
5098
5099 /// [419] Wenn in diesem Datenelement kein anderes Paket in dieser SG10 in derselben SG8 SEQ zur Möglichkeit der Angabe von mindestens einem anderen Code führt
5100 fn evaluate_419(&self, _ctx: &EvaluationContext) -> ConditionResult {
5101 // TODO: implement
5102 ConditionResult::Unknown
5103 }
5104
5105 /// [420] Wenn in dieser SG8 das RFF+Z14 (Smartmeter-Gateway) vorhanden ist
5106 fn evaluate_420(&self, _ctx: &EvaluationContext) -> ConditionResult {
5107 // TODO: implement
5108 ConditionResult::Unknown
5109 }
5110
5111 /// [421] Wenn in dieser SG8 das SG10 CCI+Z39 (Zugeordnete Zählzeitdefinition) vorhanden ist
5112 fn evaluate_421(&self, _ctx: &EvaluationContext) -> ConditionResult {
5113 // TODO: implement
5114 ConditionResult::Unknown
5115 }
5116
5117 /// [425] Messprodukt-Code aus den Kapitel 2.1 \"Standard-Messprodukte der Marktlokation\" der Codeliste der Konfigurationen
5118 fn evaluate_425(&self, ctx: &EvaluationContext) -> ConditionResult {
5119 ctx.external.evaluate("code_list_membership_check")
5120 }
5121
5122 /// [426] Messprodukt-Code aus den Kapitel 2.2 \"Standard-Messprodukte der Tranche\" der Codeliste der Konfigurationen
5123 fn evaluate_426(&self, ctx: &EvaluationContext) -> ConditionResult {
5124 ctx.external.evaluate("code_list_membership_check")
5125 }
5126
5127 /// [427] Messprodukt-Code aus den Kapitel 2.3 \"Standard-Messprodukte der Messlokation\" der Codeliste der Konfigurationen
5128 fn evaluate_427(&self, ctx: &EvaluationContext) -> ConditionResult {
5129 ctx.external.evaluate("code_list_membership_check")
5130 }
5131
5132 /// [428] Wenn in derselben SG8 SEQ+Z27/ ZE2 (Erforderliches Messprodukt der Marktlokation) das PIA+5 DE7140 mit einem Messprodukt aus Codeliste der Konfigurationen Kapitel 2.1.1 Standard-Messprodukt der Mar...
5133 fn evaluate_428(&self, ctx: &EvaluationContext) -> ConditionResult {
5134 ctx.external.evaluate("code_list_membership_check")
5135 }
5136
5137 /// [429] Wenn in derselben SG8 SEQ+Z19/ ZF4 (Erforderliches Messprodukt der Messlokation) das PIA+5 DE7140 mit einem Messprodukt aus Codeliste der Konfigurationen Kapitel 2.3.1 Standard-Messprodukt der Mess...
5138 fn evaluate_429(&self, ctx: &EvaluationContext) -> ConditionResult {
5139 ctx.external.evaluate("code_list_membership_check")
5140 }
5141
5142 /// [430] Wenn eine andere SG8 SEQ+Z27 (Erforderliches Messprodukt der Marktlokation), mit dem RFF+Z18 (Referenz auf die ID der Marktlokation) auf die gleiche ID einer Marktlokation referenziert, mit PIA+5+9...
5143 fn evaluate_430(&self, _ctx: &EvaluationContext) -> ConditionResult {
5144 // TODO: implement
5145 ConditionResult::Unknown
5146 }
5147
5148 /// [431] Wenn keine andere SG8 SEQ+Z27 (Erforderliches Messprodukt der Marktlokation), mit dem RFF+Z18 (Referenz auf die ID der Marktlokation) auf die gleiche ID einer Marktlokation referenziert, mit PIA+5+...
5149 fn evaluate_431(&self, _ctx: &EvaluationContext) -> ConditionResult {
5150 // TODO: implement
5151 ConditionResult::Unknown
5152 }
5153
5154 /// [432] Wenn in derselben SG8 SEQ+Z27 (Erforderliches Messprodukt der Marktlokation), das PIA+5+9991000000078:Z11 (Wirkarbeit Lastgang 1/4 stündlich) vorhanden ist
5155 fn evaluate_432(&self, _ctx: &EvaluationContext) -> ConditionResult {
5156 // TODO: implement
5157 ConditionResult::Unknown
5158 }
5159
5160 /// [433] Wenn keine andere SG8 SEQ+Z27 (Erforderliches Messprodukt der Marktlokation), mit dem RFF+Z18 (Referenz auf die ID der Marktlokation) auf die gleiche ID einer Marktlokation referenziert, mit PIA+5 ...
5161 fn evaluate_433(&self, ctx: &EvaluationContext) -> ConditionResult {
5162 ctx.external.evaluate("code_list_membership_check")
5163 }
5164
5165 /// [435] Wenn eine andere SG8 SEQ+Z27 (Erforderliches Messprodukt der Marktlokation), mit dem RFF+Z18 (Referenz auf die ID der Marktlokation) auf die gleiche ID einer Marktlokation referenziert, mit PIA+5 D...
5166 fn evaluate_435(&self, ctx: &EvaluationContext) -> ConditionResult {
5167 ctx.external.evaluate("code_list_membership_check")
5168 }
5169
5170 /// [436] Wenn in derselben SG8 SEQ+Z27 (Erforderliches Messprodukt der Marktlokation), das PIA+5+9991000000086:Z11 (Wirkarbeit höchste 1/4 Stunde im Monat) vorhanden ist
5171 fn evaluate_436(&self, _ctx: &EvaluationContext) -> ConditionResult {
5172 // TODO: implement
5173 ConditionResult::Unknown
5174 }
5175
5176 /// [437] Wenn in dieser SG4 das STS+E01++A04 / A23 (Status der Antwort) vorhanden
5177 fn evaluate_437(&self, _ctx: &EvaluationContext) -> ConditionResult {
5178 // TODO: implement
5179 ConditionResult::Unknown
5180 }
5181
5182 /// [438] Wenn im selben CCI im DE7059 der Code Z39 (Code der Zählzeit) vorhanden ist
5183 fn evaluate_438(&self, _ctx: &EvaluationContext) -> ConditionResult {
5184 // TODO: implement
5185 ConditionResult::Unknown
5186 }
5187
5188 /// [440] Wenn in demselben RFF der Code Z35 (vorgelagerte Netzlokation) im DE1153 vorhanden
5189 fn evaluate_440(&self, _ctx: &EvaluationContext) -> ConditionResult {
5190 // TODO: implement
5191 ConditionResult::Unknown
5192 }
5193
5194 /// [441] Wenn im SG8+SEQ+Z03/ ZF5 (Zähleinrichtungsdaten) für die in diesem RFF DE1154 genannte Gerätenummer eines Zählers das RFF+Z14 (Referenz auf das Smartmeter-Gateway) nicht vorhanden ist
5195 fn evaluate_441(&self, _ctx: &EvaluationContext) -> ConditionResult {
5196 // TODO: implement
5197 ConditionResult::Unknown
5198 }
5199
5200 /// [442] Wenn in demselben RFF der Code Z34 (vorgelagerte Messlokation) im DE1153 vorhanden
5201 fn evaluate_442(&self, _ctx: &EvaluationContext) -> ConditionResult {
5202 // TODO: implement
5203 ConditionResult::Unknown
5204 }
5205
5206 /// [444] Wenn in derselben SG8 (Produkt-Daten der Netzlokation) das PIA+5 (Produkt-Daten der Netzlokation) nicht vorhanden
5207 // REVIEW: Checks whether any SG8 instance carrying a 'Produkt-Daten der Netzlokation' SEQ qualifier (Z60, ZE0, ZG8, ZG9) lacks PIA+5. Iterates each qualifier separately using any_group_has_qualifier_without which checks: SEQ+code present AND PIA+5 absent in same SG8. Returns True on first match. Correctly handles the multi-qualifier case via OR iteration. (medium confidence)
5208 fn evaluate_444(&self, ctx: &EvaluationContext) -> ConditionResult {
5209 for code in ["Z60", "ZE0", "ZG8", "ZG9"] {
5210 if matches!(
5211 ctx.any_group_has_qualifier_without("SEQ", 0, code, "PIA", 0, "5", &["SG4", "SG8"]),
5212 ConditionResult::True
5213 ) {
5214 return ConditionResult::True;
5215 }
5216 }
5217 ConditionResult::False
5218 }
5219
5220 /// [445] Wenn in derselben SG8 (Produkt-Daten der Netzlokation) das SG10 CCI+11 (Details zum Produkt der Netzlokation) nicht vorhanden
5221 // REVIEW: Iterates all SG8 instances and checks whether any SG10 child group contains CCI with elements[0][0]=="11" (Details zum Produkt der Netzlokation). Returns True when an SG8 is found that lacks such a CCI+11 in its SG10 children. Navigator fallback uses filtered_parent_child_has_qualifier negated per qualifier. Approximation: the navigator path does not filter SG8 instances by Produkt-Daten-Netzlokation SEQ qualifier due to absence of find_segments_in_group; checks all SG8 instances instead. (medium confidence)
5222 fn evaluate_445(&self, ctx: &EvaluationContext) -> ConditionResult {
5223 let nav = match ctx.navigator {
5224 Some(n) => n,
5225 None => {
5226 let has_cci11 = ["Z60", "ZE0", "ZG8", "ZG9"].iter().any(|code| {
5227 matches!(
5228 ctx.filtered_parent_child_has_qualifier(
5229 &["SG4", "SG8"],
5230 "SEQ",
5231 0,
5232 code,
5233 "SG10",
5234 "CCI",
5235 0,
5236 "11",
5237 ),
5238 ConditionResult::True
5239 )
5240 });
5241 return ConditionResult::from(!has_cci11);
5242 }
5243 };
5244
5245 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
5246 for i in 0..sg8_count {
5247 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
5248 let has_cci11 = (0..sg10_count).any(|j| {
5249 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
5250 ccis.iter().any(|s| {
5251 s.elements
5252 .first()
5253 .and_then(|e: &Vec<String>| e.first())
5254 .is_some_and(|v: &String| v == "11")
5255 })
5256 });
5257 if !has_cci11 {
5258 return ConditionResult::True;
5259 }
5260 }
5261 ConditionResult::False
5262 }
5263
5264 /// [446] Wenn in derselben SG8 das CCI+Z17 (Stromverbrauchsart) vorhanden
5265 fn evaluate_446(&self, _ctx: &EvaluationContext) -> ConditionResult {
5266 // TODO: implement
5267 ConditionResult::Unknown
5268 }
5269
5270 /// [447] Wenn in derselben SG8 das CCI+Z50 (Stromerzeugungsart) vorhanden
5271 fn evaluate_447(&self, _ctx: &EvaluationContext) -> ConditionResult {
5272 // TODO: implement
5273 ConditionResult::Unknown
5274 }
5275
5276 /// [448] Wenn in derselben SG8 das CCI+Z56 (Speicher) vorhanden
5277 fn evaluate_448(&self, _ctx: &EvaluationContext) -> ConditionResult {
5278 // TODO: implement
5279 ConditionResult::Unknown
5280 }
5281
5282 /// [449] Wenn in derselben SG8 das SG10 CCI+6++ZA9 CAV=ZG3 (Aggreg.verantw. ÜNB und Lokation im Regelbetrieb) vorhanden
5283 fn evaluate_449(&self, _ctx: &EvaluationContext) -> ConditionResult {
5284 // TODO: implement
5285 ConditionResult::Unknown
5286 }
5287
5288 /// [450] Wenn in demselben RFF der Code Z32 (Netzlokation) im DE1153 vorhanden
5289 fn evaluate_450(&self, _ctx: &EvaluationContext) -> ConditionResult {
5290 // TODO: implement
5291 ConditionResult::Unknown
5292 }
5293
5294 /// [451] Wenn in demselben RFF der Code Z18 (Marktlokation) im DE1153 vorhanden
5295 fn evaluate_451(&self, _ctx: &EvaluationContext) -> ConditionResult {
5296 // TODO: implement
5297 ConditionResult::Unknown
5298 }
5299
5300 /// [452] Wenn in demselben RFF der Code Z19 (Messlokation) im DE1153 vorhanden
5301 fn evaluate_452(&self, _ctx: &EvaluationContext) -> ConditionResult {
5302 // TODO: implement
5303 ConditionResult::Unknown
5304 }
5305
5306 /// [453] Wenn bei der Bestellung ein Messprodukt der Codeliste der Konfigurationen aus dem Kapitel 4.4 mit dem Auslöser „Bei Schwellwertunter-/ -überschreitung“ mit selbständiger Änderungsmöglichke...
5307 fn evaluate_453(&self, ctx: &EvaluationContext) -> ConditionResult {
5308 ctx.external.evaluate("code_list_membership_check")
5309 }
5310
5311 /// [454] Das Bilanzierungsbeginn Datum muss kleiner sein als das Bilanzierungsende Datum in der SG8 „Datenstand des ÜNB“, SG 9 Energiemenge DZÜ Anteil
5312 fn evaluate_454(&self, _ctx: &EvaluationContext) -> ConditionResult {
5313 // TODO: implement
5314 ConditionResult::Unknown
5315 }
5316
5317 /// [455] Das Bilanzierungsende-Datum muss größer sein, als das Bilanzierungsbeginn Datum in der SG8 „Datenstand des ÜNB“ , SG 9 Energiemenge DZÜ Anteil
5318 fn evaluate_455(&self, _ctx: &EvaluationContext) -> ConditionResult {
5319 // TODO: implement
5320 ConditionResult::Unknown
5321 }
5322
5323 /// [456] Wenn in demselben RFF der Code Z37 (Technische Ressource) im DE1153 vorhanden
5324 fn evaluate_456(&self, _ctx: &EvaluationContext) -> ConditionResult {
5325 // TODO: implement
5326 ConditionResult::Unknown
5327 }
5328
5329 /// [457] Wenn bei der Bestellung das Messprodukten 9991000001498 bestellt wurde
5330 fn evaluate_457(&self, _ctx: &EvaluationContext) -> ConditionResult {
5331 // TODO: implement
5332 ConditionResult::Unknown
5333 }
5334
5335 /// [458] Wenn bei der Bestellung das Konfigurationsprodukte 9991000000739 bestellt wurde
5336 fn evaluate_458(&self, _ctx: &EvaluationContext) -> ConditionResult {
5337 // TODO: implement
5338 ConditionResult::Unknown
5339 }
5340
5341 /// [459] Wenn bei der Bestellung ein Messprodukt der Codeliste der Konfigurationen aus dem Kapitel 4.4 mit dem Übertragungsweg \"CLS-Direkt aus dem SMGW\" bestellt wurde
5342 fn evaluate_459(&self, ctx: &EvaluationContext) -> ConditionResult {
5343 ctx.external.evaluate("code_list_membership_check")
5344 }
5345
5346 /// [460] Wenn bei der Bestellung ein Messprodukt der Codeliste der Konfigurationen aus dem Kapitel 4.4 mit dem Übertragungsweg \"aus dem SMGW\" bestellt wurde
5347 fn evaluate_460(&self, ctx: &EvaluationContext) -> ConditionResult {
5348 ctx.external.evaluate("code_list_membership_check")
5349 }
5350
5351 /// [461] Wenn in derselben SG10 das CCI+Z17 (Stromverbrauchsart) im CAV+ZG8 (Technischen Ressource fällt unter § 14a EnWG) vorhanden
5352 fn evaluate_461(&self, _ctx: &EvaluationContext) -> ConditionResult {
5353 // TODO: implement
5354 ConditionResult::Unknown
5355 }
5356
5357 /// [462] Wenn in derselben SG10 das CCI+Z17 (Stromverbrauchsart) im CAV+ZH1 (Inbetriebsetzung der TR vor 2024) vorhanden
5358 fn evaluate_462(&self, _ctx: &EvaluationContext) -> ConditionResult {
5359 // TODO: implement
5360 ConditionResult::Unknown
5361 }
5362
5363 /// [463] Wenn in derselben SG10 das CCI+Z61++ZF9 (Kunde erfüllt die Voraussetzung nach EnFG) vorhanden
5364 fn evaluate_463(&self, _ctx: &EvaluationContext) -> ConditionResult {
5365 // TODO: implement
5366 ConditionResult::Unknown
5367 }
5368
5369 /// [465] Wenn in derselben SG8 (Daten der Technischen Ressource) das RFF+Z38 (Referenz auf die der Technischen Ressource zugeordnete Steuerbare Ressource) vorhanden ist
5370 fn evaluate_465(&self, _ctx: &EvaluationContext) -> ConditionResult {
5371 // TODO: implement
5372 ConditionResult::Unknown
5373 }
5374
5375 /// [466] Wenn in derselben SG8 (Daten der Technischen Ressource) das RFF+Z32 (Referenz auf die der Technischen Ressource zugeordneten Netzlokation) vorhanden ist
5376 fn evaluate_466(&self, _ctx: &EvaluationContext) -> ConditionResult {
5377 // TODO: implement
5378 ConditionResult::Unknown
5379 }
5380
5381 /// [467] Wenn in derselben SG8 (Daten der Technischen Ressource) das CAV+ZG8 (Technischen Ressource fällt unter § 14a EnWG) vorhanden ist
5382 fn evaluate_467(&self, _ctx: &EvaluationContext) -> ConditionResult {
5383 // TODO: implement
5384 ConditionResult::Unknown
5385 }
5386
5387 /// [468] Wenn in derselben SG8 (Daten der Technischen Ressource) das SG10 CAV+ZH0 (Inbetriebsetzung der TR nach 2023) vorhanden ist
5388 fn evaluate_468(&self, _ctx: &EvaluationContext) -> ConditionResult {
5389 // TODO: implement
5390 ConditionResult::Unknown
5391 }
5392
5393 /// [469] Wenn in derselben SG8 (Daten der Technischen Ressource) das SG10 CAV+ZH1 (Inbetriebsetzung der TR vor 2024) vorhanden ist
5394 fn evaluate_469(&self, _ctx: &EvaluationContext) -> ConditionResult {
5395 // TODO: implement
5396 ConditionResult::Unknown
5397 }
5398
5399 /// [470] Wenn in derselben SG8 (Daten der Technischen Ressource) das CAV+ZH5 (Wechsel in das in das § 14a EnWG-Modell gem. Festlegung BK6-22-300 wurde durchgeführt) vorhanden ist
5400 fn evaluate_470(&self, _ctx: &EvaluationContext) -> ConditionResult {
5401 // TODO: implement
5402 ConditionResult::Unknown
5403 }
5404
5405 /// [471] Wenn im selben SG6 RFF+Z49/ Z53 (Verwendungszeitraum der Daten: Gültige Daten/ Keine Daten) im DE1156 (Zeitraum-ID) eine Zeitraum ID genannt ist, die kleiner ist als in einem anderen SG6 RFF+Z49/ ...
5406 fn evaluate_471(&self, _ctx: &EvaluationContext) -> ConditionResult {
5407 // TODO: implement
5408 ConditionResult::Unknown
5409 }
5410
5411 /// [472] Wenn im selben SG6 RFF+Z48/ Z55 (Verwendungszeitraum der Daten: Erwartete Daten/ Keine Daten erwartet) im DE1156 (Zeitraum-ID) eine Zeitraum ID genannt ist, die kleiner ist als in einem anderen SG6...
5412 fn evaluate_472(&self, _ctx: &EvaluationContext) -> ConditionResult {
5413 // TODO: implement
5414 ConditionResult::Unknown
5415 }
5416
5417 /// [473] Wenn im selben SG6 RFF+Z47/ Z54 (Verwendungszeitraum der Daten: Im System vorhandene Daten/ Im System keine Daten vorhanden) im DE1156 (Zeitraum-ID) eine Zeitraum ID genannt ist, die kleiner ist al...
5418 fn evaluate_473(&self, _ctx: &EvaluationContext) -> ConditionResult {
5419 // TODO: implement
5420 ConditionResult::Unknown
5421 }
5422
5423 /// [474] Wenn SG4 STS+7++ZC8 (Transaktionsgrund \"Beendigung der Zuordnung\") vorhanden
5424 fn evaluate_474(&self, _ctx: &EvaluationContext) -> ConditionResult {
5425 // TODO: implement
5426 ConditionResult::Unknown
5427 }
5428
5429 /// [475] Wenn SG4 STS+7++ZH1 (Transaktionsgrund \"Aufhebung einer zukünftigen Zuordnung wegen Stilllegung\") vorhanden
5430 fn evaluate_475(&self, _ctx: &EvaluationContext) -> ConditionResult {
5431 // TODO: implement
5432 ConditionResult::Unknown
5433 }
5434
5435 /// [476] Wenn SG4 STS+7++xxx+ZW0 (Transaktionsgrundergänzung Geschäftsvorfall 1) vorhanden
5436 fn evaluate_476(&self, _ctx: &EvaluationContext) -> ConditionResult {
5437 // TODO: implement
5438 ConditionResult::Unknown
5439 }
5440
5441 /// [477] Wenn SG4 STS+7++xxx+ZW1 (Transaktionsgrundergänzung Geschäftsvorfall 2) vorhanden
5442 fn evaluate_477(&self, _ctx: &EvaluationContext) -> ConditionResult {
5443 // TODO: implement
5444 ConditionResult::Unknown
5445 }
5446
5447 /// [478] Wenn SG4 STS+7++xxx+ZW2 (Transaktionsgrundergänzung Geschäftsvorfall 3) vorhanden
5448 fn evaluate_478(&self, _ctx: &EvaluationContext) -> ConditionResult {
5449 // TODO: implement
5450 ConditionResult::Unknown
5451 }
5452
5453 /// [479] Wenn SG4 STS+7++xxx+ZW3 (Transaktionsgrundergänzung Erzeugende Marktlokation) vorhanden
5454 fn evaluate_479(&self, _ctx: &EvaluationContext) -> ConditionResult {
5455 // TODO: implement
5456 ConditionResult::Unknown
5457 }
5458
5459 /// [480] Wenn SG4 STS+7++xxx+ZW4 (Transaktionsgrundergänzung Verbrauchende Marktlokation) vorhanden
5460 fn evaluate_480(&self, _ctx: &EvaluationContext) -> ConditionResult {
5461 // TODO: implement
5462 ConditionResult::Unknown
5463 }
5464
5465 /// [481] Wenn SG4 STS+7++xxx+ZW5 (Transaktionsgrundergänzung Tranche) vorhanden
5466 fn evaluate_481(&self, _ctx: &EvaluationContext) -> ConditionResult {
5467 // TODO: implement
5468 ConditionResult::Unknown
5469 }
5470
5471 /// [483] Wenn SG4 STS+7++xxx+ZW7 (Transaktionsgrundergänzung Gemessene Marktlokation) vorhanden
5472 fn evaluate_483(&self, _ctx: &EvaluationContext) -> ConditionResult {
5473 // TODO: implement
5474 ConditionResult::Unknown
5475 }
5476
5477 /// [484] Wenn SG4 STS+7++xxx+ZW8 (Transaktionsgrundergänzung Fall1) vorhanden
5478 fn evaluate_484(&self, _ctx: &EvaluationContext) -> ConditionResult {
5479 // TODO: implement
5480 ConditionResult::Unknown
5481 }
5482
5483 /// [487] Wenn SG4 STS+7++xxx+ZX1 (Transaktionsgrundergänzung Fall4) vorhanden
5484 fn evaluate_487(&self, _ctx: &EvaluationContext) -> ConditionResult {
5485 // TODO: implement
5486 ConditionResult::Unknown
5487 }
5488
5489 /// [489] Nur bei dem ältesten Zeitraum welcher mit SG6 RFF+Z49 (Verwendungszeitraum der Daten: Gültige Daten) beschrieben ist
5490 fn evaluate_489(&self, _ctx: &EvaluationContext) -> ConditionResult {
5491 // TODO: implement
5492 ConditionResult::Unknown
5493 }
5494
5495 /// [490] Wenn Wert in diesem DE, an der Stelle CCYYMMDD ein Datum aus dem angegeben Zeitraum der Tabelle Kapitel 3.5 „Prozesszeitpunkt bei MESZ mit UTC“ ist
5496 fn evaluate_490(&self, _ctx: &EvaluationContext) -> ConditionResult {
5497 // TODO: implement
5498 ConditionResult::Unknown
5499 }
5500
5501 /// [491] Wenn Wert in diesem DE, an der Stelle CCYYMMDD ein Datum aus dem angegeben Zeitraum der Tabelle Kapitel 3.6 „Prozesszeitpunkt bei MEZ mit UTC““ ist
5502 fn evaluate_491(&self, _ctx: &EvaluationContext) -> ConditionResult {
5503 // TODO: implement
5504 ConditionResult::Unknown
5505 }
5506
5507 /// [494] Das hier genannte Datum muss der Zeitpunkt sein, zu dem das Dokument erstellt wurde, oder ein Zeitpunkt, der davor liegt
5508 fn evaluate_494(&self, _ctx: &EvaluationContext) -> ConditionResult {
5509 // TODO: implement
5510 ConditionResult::Unknown
5511 }
5512
5513 /// [500] Hinweis: Code ist gemäß der Kategorie der zu stornierenden Meldung zu wählen
5514 fn evaluate_500(&self, _ctx: &EvaluationContext) -> ConditionResult {
5515 // TODO: implement
5516 ConditionResult::Unknown
5517 }
5518
5519 /// [501] Hinweis: Es sind zur Unterstützung die Daten des LFA anzugeben
5520 fn evaluate_501(&self, _ctx: &EvaluationContext) -> ConditionResult {
5521 // TODO: implement
5522 ConditionResult::Unknown
5523 }
5524
5525 /// [502] Hinweis: Es wird der Betrachtungsmonat der DZR bzw. BAS angegeben
5526 fn evaluate_502(&self, _ctx: &EvaluationContext) -> ConditionResult {
5527 // TODO: implement
5528 ConditionResult::Unknown
5529 }
5530
5531 /// [503] Hinweis: Angabe des BGM DE1004 aus der ORDERS
5532 fn evaluate_503(&self, _ctx: &EvaluationContext) -> ConditionResult {
5533 // TODO: implement
5534 ConditionResult::Unknown
5535 }
5536
5537 /// [504] Hinweis: Je Profil (ggf. inkl. Profilschar) ein Vorgang erforderlich
5538 fn evaluate_504(&self, _ctx: &EvaluationContext) -> ConditionResult {
5539 // TODO: implement
5540 ConditionResult::Unknown
5541 }
5542
5543 /// [505] Hinweis: Je zugeordneter ID und je EEG-Überführungszeitreihe ein Vorgang erforderlich
5544 fn evaluate_505(&self, _ctx: &EvaluationContext) -> ConditionResult {
5545 // TODO: implement
5546 ConditionResult::Unknown
5547 }
5548
5549 /// [506] Hinweis: Für jeden Code im LOC+Z16 (Marktlokation) sollen die entsprechenden Kundendaten des LF angegeben werden, falls bekannt
5550 fn evaluate_506(&self, _ctx: &EvaluationContext) -> ConditionResult {
5551 // TODO: implement
5552 ConditionResult::Unknown
5553 }
5554
5555 /// [507] Hinweis: Ursprünglich vom NB bestätigtes Beginndatum
5556 fn evaluate_507(&self, _ctx: &EvaluationContext) -> ConditionResult {
5557 // TODO: implement
5558 ConditionResult::Unknown
5559 }
5560
5561 /// [508] Hinweis: Ausschließlich kME sind über die NNE abrechenbar
5562 fn evaluate_508(&self, _ctx: &EvaluationContext) -> ConditionResult {
5563 // TODO: implement
5564 ConditionResult::Unknown
5565 }
5566
5567 /// [509] Hinweis: Handelt sich um ein mME oder iMS ist das RFF 1154 immer mit NEIN anzugeben
5568 fn evaluate_509(&self, _ctx: &EvaluationContext) -> ConditionResult {
5569 // TODO: implement
5570 ConditionResult::Unknown
5571 }
5572
5573 /// [510] Hinweis: Zu verwenden bei der Abmeldung der ESV
5574 fn evaluate_510(&self, _ctx: &EvaluationContext) -> ConditionResult {
5575 // TODO: implement
5576 ConditionResult::Unknown
5577 }
5578
5579 /// [511] Hinweis: Es sind alle Bilanzierungsgebiete anzugeben in denen das Profil verwendet wird
5580 fn evaluate_511(&self, _ctx: &EvaluationContext) -> ConditionResult {
5581 // TODO: implement
5582 ConditionResult::Unknown
5583 }
5584
5585 /// [512] Hinweis: Es ist informativ die bisherige Veräußerungsform des LFA an der erzeugenden Marktlokation anzugeben
5586 fn evaluate_512(&self, _ctx: &EvaluationContext) -> ConditionResult {
5587 // TODO: implement
5588 ConditionResult::Unknown
5589 }
5590
5591 /// [513] Hinweis: Es ist das nächstmögliche Datum ab dem DTM+471 aus der entsprechenden Anfrage zu ermitteln
5592 fn evaluate_513(&self, _ctx: &EvaluationContext) -> ConditionResult {
5593 // TODO: implement
5594 ConditionResult::Unknown
5595 }
5596
5597 /// [514] Hinweis: Es darf nur eine Information im DE3148 übermittelt werden
5598 fn evaluate_514(&self, _ctx: &EvaluationContext) -> ConditionResult {
5599 // TODO: implement
5600 ConditionResult::Unknown
5601 }
5602
5603 /// [515] Hinweis: Für den ZP der LieferantensummenZR anzugeben
5604 fn evaluate_515(&self, _ctx: &EvaluationContext) -> ConditionResult {
5605 // TODO: implement
5606 ConditionResult::Unknown
5607 }
5608
5609 /// [516] Hinweis: Es ist der Änderungszeitpunkt anzugeben an dem das Zuordnungsende des NBA und der Zuordnungsbeginn des NBN zu einer Marktlokation fallen
5610 fn evaluate_516(&self, _ctx: &EvaluationContext) -> ConditionResult {
5611 // TODO: implement
5612 ConditionResult::Unknown
5613 }
5614
5615 /// [517] Hinweis: Anzuwenden wenn einer Marktlokation eine Paket-ID zugeordnet wurde und diese wieder gelöscht werden soll, da sie nicht unter den genannten NB-Wechsel fällt
5616 fn evaluate_517(&self, _ctx: &EvaluationContext) -> ConditionResult {
5617 // TODO: implement
5618 ConditionResult::Unknown
5619 }
5620
5621 /// [518] Hinweis: Es sind alle Altlieferanten anzugeben, an die eine Abmeldeanfrage gesendet wird
5622 fn evaluate_518(&self, _ctx: &EvaluationContext) -> ConditionResult {
5623 // TODO: implement
5624 ConditionResult::Unknown
5625 }
5626
5627 /// [519] Hinweis: Wenn in der Anmeldung der Code ZAP vorhanden war, so ist dieser auch in der Antwort zu verwenden
5628 fn evaluate_519(&self, _ctx: &EvaluationContext) -> ConditionResult {
5629 // TODO: implement
5630 ConditionResult::Unknown
5631 }
5632
5633 /// [520] Hinweis: Bei der Verwendung des Codes ZAP handelt es sich immer um eine gemessene Marktlokation
5634 fn evaluate_520(&self, _ctx: &EvaluationContext) -> ConditionResult {
5635 // TODO: implement
5636 ConditionResult::Unknown
5637 }
5638
5639 /// [521] Hinweis: Wenn im zweiten DE 9013 des STS+7 (Transaktionsgrund) der Code ZAP vorhanden ist, so ist das hier angegebene Datum als Zuordnungsbeginn bei der Bildung der \"Ruhenden MaLo zu verstehen. Be...
5640 fn evaluate_521(&self, _ctx: &EvaluationContext) -> ConditionResult {
5641 // TODO: implement
5642 ConditionResult::Unknown
5643 }
5644
5645 /// [522] Hinweis: Es ist der NBN anzugeben
5646 fn evaluate_522(&self, _ctx: &EvaluationContext) -> ConditionResult {
5647 // TODO: implement
5648 ConditionResult::Unknown
5649 }
5650
5651 /// [523] Hinweis: Mindestens einmal für jede Marktlokation bzw. Tranche, die in der DZÜ / BG-CL / LF-SZR berücksichtigt wurde
5652 fn evaluate_523(&self, _ctx: &EvaluationContext) -> ConditionResult {
5653 // TODO: implement
5654 ConditionResult::Unknown
5655 }
5656
5657 /// [524] Hinweis: Mindestens einmal für jede Marktlokation bzw. Tranche, für die der LF nicht die gemeldete Ansicht des NB teilt
5658 fn evaluate_524(&self, _ctx: &EvaluationContext) -> ConditionResult {
5659 // TODO: implement
5660 ConditionResult::Unknown
5661 }
5662
5663 /// [525] Hinweis: Es sind nur die OBIS-Kennzahlen erlaubt, die im vorherigen Stammdatenaustausch zu dieser Marktlokation vom MSB zu diesem Zeitpunkt übermittelt wurden
5664 fn evaluate_525(&self, _ctx: &EvaluationContext) -> ConditionResult {
5665 // TODO: implement
5666 ConditionResult::Unknown
5667 }
5668
5669 /// [526] Hinweis: Wenn der Marktlokation keine Technische Ressource in der Lokationsbündelstruktur zugeordnet wurde
5670 fn evaluate_526(&self, _ctx: &EvaluationContext) -> ConditionResult {
5671 // TODO: implement
5672 ConditionResult::Unknown
5673 }
5674
5675 /// [527] Hinweis: Es sind alle Identifikatoren der Messlokationen anzugeben
5676 fn evaluate_527(&self, _ctx: &EvaluationContext) -> ConditionResult {
5677 // TODO: implement
5678 ConditionResult::Unknown
5679 }
5680
5681 /// [528] Hinweis: Es ist das Datum/ Daten aus der Anfrage zu verwenden
5682 fn evaluate_528(&self, _ctx: &EvaluationContext) -> ConditionResult {
5683 // TODO: implement
5684 ConditionResult::Unknown
5685 }
5686
5687 /// [529] Hinweis: Für zusätzliche nicht im Markt standardisierte Identifikatoren wie z.B. eine Netzbetreiber-Projektnummer
5688 fn evaluate_529(&self, _ctx: &EvaluationContext) -> ConditionResult {
5689 // TODO: implement
5690 ConditionResult::Unknown
5691 }
5692
5693 /// [530] Hinweis: Es sind alle an der Lokation vorhandenen Daten, die mit dieser Segmentgruppe übermittelt werden und zum Datum „Änderung zum“ Gültigkeit haben, anzugeben. Dies kann zur Folge haben, ...
5694 fn evaluate_530(&self, _ctx: &EvaluationContext) -> ConditionResult {
5695 // TODO: implement
5696 ConditionResult::Unknown
5697 }
5698
5699 /// [531] Hinweis: Es ist das Jahr anzugeben in dem die nächste Netznutzungsabrechnung erfolgt
5700 fn evaluate_531(&self, _ctx: &EvaluationContext) -> ConditionResult {
5701 // TODO: implement
5702 ConditionResult::Unknown
5703 }
5704
5705 /// [532] Hinweis: Kritische Daten (gemäß GPKE)
5706 fn evaluate_532(&self, _ctx: &EvaluationContext) -> ConditionResult {
5707 // TODO: implement
5708 ConditionResult::Unknown
5709 }
5710
5711 /// [533] Hinweis: Es ist die MP-ID des Lieferanten anzugeben
5712 fn evaluate_533(&self, _ctx: &EvaluationContext) -> ConditionResult {
5713 // TODO: implement
5714 ConditionResult::Unknown
5715 }
5716
5717 /// [555] Die Anwendungsfälle für die Durchführung der BDEW-Anwendungshilfe „Marktprozesse Netzbetreiberwechsel Sparte Strom“ sind ab dem 01.08.2025 für Netzbetreiberwechsel ab dem 01.01.2026 zu verw...
5718 fn evaluate_555(&self, _ctx: &EvaluationContext) -> ConditionResult {
5719 // TODO: implement
5720 ConditionResult::Unknown
5721 }
5722
5723 /// [556] Hinweis: Wenn keine Korrespondenzanschrift des Endverbrauchers/ Kunden vorliegt, ist die Anschrift der Marktlokation zu übermitteln
5724 fn evaluate_556(&self, _ctx: &EvaluationContext) -> ConditionResult {
5725 // TODO: implement
5726 ConditionResult::Unknown
5727 }
5728
5729 /// [558] Hinweis: Diese Information kann freiwillig ausgetauscht werden
5730 fn evaluate_558(&self, _ctx: &EvaluationContext) -> ConditionResult {
5731 // TODO: implement
5732 ConditionResult::Unknown
5733 }
5734
5735 /// [559] Hinweis: Die Korrespondenzanschrift des Endverbrauchers/Kunden wird nicht zur Identifikation genutzt
5736 fn evaluate_559(&self, _ctx: &EvaluationContext) -> ConditionResult {
5737 // TODO: implement
5738 ConditionResult::Unknown
5739 }
5740
5741 /// [563] Hinweis: Für die ID der LieferantensummenZR
5742 fn evaluate_563(&self, _ctx: &EvaluationContext) -> ConditionResult {
5743 // TODO: implement
5744 ConditionResult::Unknown
5745 }
5746
5747 /// [566] Hinweis: Altlieferant
5748 fn evaluate_566(&self, _ctx: &EvaluationContext) -> ConditionResult {
5749 // TODO: implement
5750 ConditionResult::Unknown
5751 }
5752
5753 /// [567] Hinweis: Neulieferant
5754 fn evaluate_567(&self, _ctx: &EvaluationContext) -> ConditionResult {
5755 // TODO: implement
5756 ConditionResult::Unknown
5757 }
5758
5759 /// [568] Hinweis: Lieferant der LieferantensummenZR
5760 fn evaluate_568(&self, _ctx: &EvaluationContext) -> ConditionResult {
5761 // TODO: implement
5762 ConditionResult::Unknown
5763 }
5764
5765 /// [569] Hinweis: Dritter Nutzer
5766 fn evaluate_569(&self, _ctx: &EvaluationContext) -> ConditionResult {
5767 // TODO: implement
5768 ConditionResult::Unknown
5769 }
5770
5771 /// [570] Hinweis: Netzbetreiber Alt
5772 fn evaluate_570(&self, _ctx: &EvaluationContext) -> ConditionResult {
5773 // TODO: implement
5774 ConditionResult::Unknown
5775 }
5776
5777 /// [572] Hinweis: Kundenname aus Anmeldung Lieferant neu
5778 fn evaluate_572(&self, _ctx: &EvaluationContext) -> ConditionResult {
5779 // TODO: implement
5780 ConditionResult::Unknown
5781 }
5782
5783 /// [576] Hinweis: Stammdaten des bisherigen Messstellenbetreibers
5784 fn evaluate_576(&self, _ctx: &EvaluationContext) -> ConditionResult {
5785 // TODO: implement
5786 ConditionResult::Unknown
5787 }
5788
5789 /// [577] Hinweis: Wird mit dem ursprünglich vom NB bestätigten Beginnzeitpunkt gefüllt
5790 fn evaluate_577(&self, _ctx: &EvaluationContext) -> ConditionResult {
5791 // TODO: implement
5792 ConditionResult::Unknown
5793 }
5794
5795 /// [579] Hinweis: Auslösender Marktpartner (LFN bei STS+7++ZH0/ZG9, NB bei STS+7++ZH1)
5796 fn evaluate_579(&self, _ctx: &EvaluationContext) -> ConditionResult {
5797 // TODO: implement
5798 ConditionResult::Unknown
5799 }
5800
5801 /// [580] Hinweis: Ersatzbelieferung gibt es nur bei - Marktlokationen in der Niederspannung, die kein Haushaltskunde gem. EnWG sind und die nicht mehr der gesetzlichen Ersatzversorgung (drei Monate) unte...
5802 fn evaluate_580(&self, _ctx: &EvaluationContext) -> ConditionResult {
5803 // TODO: implement
5804 ConditionResult::Unknown
5805 }
5806
5807 /// [581] Hinweis: Es ist der Zeitpunkt anzugeben, zu welchem der Vertrag am Tag des Versandes der Antwort noch kündbar ist.
5808 fn evaluate_581(&self, _ctx: &EvaluationContext) -> ConditionResult {
5809 // TODO: implement
5810 ConditionResult::Unknown
5811 }
5812
5813 /// [586] Hinweis: Die Messlokationsadresse ist der Messlokation zugeordnet, welche in SG8 SEQ+Z18/ ZF3 (Daten der Messlokation) mit CCI+Z01++Z82 (Verwendungsumfang: ID der prozessual behandelten Messlokatio...
5814 fn evaluate_586(&self, _ctx: &EvaluationContext) -> ConditionResult {
5815 // TODO: implement
5816 ConditionResult::Unknown
5817 }
5818
5819 /// [590] Hinweis: Für den Empfang des Steuerbefehls
5820 fn evaluate_590(&self, _ctx: &EvaluationContext) -> ConditionResult {
5821 // TODO: implement
5822 ConditionResult::Unknown
5823 }
5824
5825 /// [594] Hinweis: Es ist der ZPB des ZP der NGZ und die ZPB der NZR anzugeben
5826 fn evaluate_594(&self, _ctx: &EvaluationContext) -> ConditionResult {
5827 // TODO: implement
5828 ConditionResult::Unknown
5829 }
5830
5831 /// [599] Hinweis: Es ist der Name und die Adresse des Ablesekartenempfängers für die Messlokation anzugeben, welche in SG8 SEQ+Z18 (Daten der Messlokation) mit CCI+Z01++Z82 (Verwendungsumfang: ID der proz...
5832 fn evaluate_599(&self, _ctx: &EvaluationContext) -> ConditionResult {
5833 // TODO: implement
5834 ConditionResult::Unknown
5835 }
5836
5837 /// [601] Hinweis: Es ist die ID der Marktlokation und alle Identifikatoren der Messlokationen anzugeben. Sowie wenn vorhanden die Tranche/n der Marklokation
5838 fn evaluate_601(&self, _ctx: &EvaluationContext) -> ConditionResult {
5839 // TODO: implement
5840 ConditionResult::Unknown
5841 }
5842
5843 /// [606] Hinweis: In diesem Segment bzw. SG sind die Daten aus der Sicht des NB anzugeben
5844 fn evaluate_606(&self, _ctx: &EvaluationContext) -> ConditionResult {
5845 // TODO: implement
5846 ConditionResult::Unknown
5847 }
5848
5849 /// [609] Hinweis: In diesem Segment bzw. SG sind die zwischen NB, LF und ÜNB im Rahmen der Marktkommunikation ausgetauschten Daten aus der Sicht des ÜNB anzugeben
5850 fn evaluate_609(&self, _ctx: &EvaluationContext) -> ConditionResult {
5851 // TODO: implement
5852 ConditionResult::Unknown
5853 }
5854
5855 /// [611] Hinweis: Wenn das Unternehmen NB die Aufgaben der Marktrolle LF wahrnimmt, ist die MP-ID des Unternehmens NB in der Marktrolle LF anzugeben
5856 fn evaluate_611(&self, _ctx: &EvaluationContext) -> ConditionResult {
5857 // TODO: implement
5858 ConditionResult::Unknown
5859 }
5860
5861 /// [614] Hinweis: Es werden nur die OBIS Kennzahlen übermittelt die für die Bilanzierung relevant sind
5862 fn evaluate_614(&self, _ctx: &EvaluationContext) -> ConditionResult {
5863 // TODO: implement
5864 ConditionResult::Unknown
5865 }
5866
5867 /// [617] Hinweis: Mehrere Vorgänge für eine Marktlokation bei Wechsel bilanzierungsrelevanter Stammdaten innerhalb des Bilanzierungsmonats
5868 fn evaluate_617(&self, _ctx: &EvaluationContext) -> ConditionResult {
5869 // TODO: implement
5870 ConditionResult::Unknown
5871 }
5872
5873 /// [618] Hinweis: Bisheriges Datum des MSBA. Sollte der MSBN ein abweichendes Datum verwenden wollen, so teilt er das neue Datum mit einer Stammdatenänderung mit
5874 fn evaluate_618(&self, _ctx: &EvaluationContext) -> ConditionResult {
5875 // TODO: implement
5876 ConditionResult::Unknown
5877 }
5878
5879 /// [619] Hinweis: Für die selbständige Änderungsmöglichkeit der Schwellwertunter- / -über-schreitung
5880 fn evaluate_619(&self, _ctx: &EvaluationContext) -> ConditionResult {
5881 // TODO: implement
5882 ConditionResult::Unknown
5883 }
5884
5885 /// [621] Hinweis: Es ist der MSB anzugeben, welcher ab dem Zeitpunkt der Lokation zugeordnet ist, der in DTM+76 (Datum zum geplanten Leistungsbeginn) genannt ist.
5886 fn evaluate_621(&self, _ctx: &EvaluationContext) -> ConditionResult {
5887 // TODO: implement
5888 ConditionResult::Unknown
5889 }
5890
5891 /// [622] Hinweis: Falls die OBIS-Kennzahl für mehrere Marktrollen relevant ist, so muss die Segmentgruppe pro Marktrolle wiederholt werden
5892 fn evaluate_622(&self, _ctx: &EvaluationContext) -> ConditionResult {
5893 // TODO: implement
5894 ConditionResult::Unknown
5895 }
5896
5897 /// [623] Hinweis: Es sind alle Identifikatoren der Messlokationen anzugeben, die zur Ermittlung der Energiemenge der im Vorgang genannten Marktlokation benötigt werden
5898 fn evaluate_623(&self, _ctx: &EvaluationContext) -> ConditionResult {
5899 // TODO: implement
5900 ConditionResult::Unknown
5901 }
5902
5903 /// [630] Hinweis: Wenn die Liste abgelehnt wird, ist kein Vorgang enthalten
5904 fn evaluate_630(&self, _ctx: &EvaluationContext) -> ConditionResult {
5905 // TODO: implement
5906 ConditionResult::Unknown
5907 }
5908
5909 /// [631] Hinweis: Es ist die Listennummer aus der Lieferanten- bzw. Bilanzierungsgebietsclearingliste zu verwenden
5910 fn evaluate_631(&self, _ctx: &EvaluationContext) -> ConditionResult {
5911 // TODO: implement
5912 ConditionResult::Unknown
5913 }
5914
5915 /// [632] Hinweis: Es ist die Listennummer aus der Lieferanten-ausfallarbeits-clearingliste zu verwenden
5916 fn evaluate_632(&self, _ctx: &EvaluationContext) -> ConditionResult {
5917 // TODO: implement
5918 ConditionResult::Unknown
5919 }
5920
5921 /// [637] Hinweis: Bei Verpflichtungsanfrage
5922 fn evaluate_637(&self, _ctx: &EvaluationContext) -> ConditionResult {
5923 // TODO: implement
5924 ConditionResult::Unknown
5925 }
5926
5927 /// [638] Hinweis: Bei Aufforderung zur Übernahme der einzelnen Messlokation durch den gMSB
5928 fn evaluate_638(&self, _ctx: &EvaluationContext) -> ConditionResult {
5929 // TODO: implement
5930 ConditionResult::Unknown
5931 }
5932
5933 /// [639] Hinweis: Wenn Antwort auf Deaktivierung
5934 fn evaluate_639(&self, _ctx: &EvaluationContext) -> ConditionResult {
5935 // TODO: implement
5936 ConditionResult::Unknown
5937 }
5938
5939 /// [640] Hinweis: Wenn Antwort auf Aktivierung
5940 fn evaluate_640(&self, _ctx: &EvaluationContext) -> ConditionResult {
5941 // TODO: implement
5942 ConditionResult::Unknown
5943 }
5944
5945 /// [641] Hinweis: Wenn Einzelanforderung vorliegt
5946 fn evaluate_641(&self, _ctx: &EvaluationContext) -> ConditionResult {
5947 // TODO: implement
5948 ConditionResult::Unknown
5949 }
5950
5951 /// [642] Hinweis: Wenn Abo vorliegt
5952 fn evaluate_642(&self, _ctx: &EvaluationContext) -> ConditionResult {
5953 // TODO: implement
5954 ConditionResult::Unknown
5955 }
5956
5957 /// [643] Hinweis: Nachfolgender Netzbetreiber
5958 fn evaluate_643(&self, _ctx: &EvaluationContext) -> ConditionResult {
5959 // TODO: implement
5960 ConditionResult::Unknown
5961 }
5962
5963 /// [645] Hinweis: Es ist der Bilanzkreis des LF anzugeben
5964 fn evaluate_645(&self, _ctx: &EvaluationContext) -> ConditionResult {
5965 // TODO: implement
5966 ConditionResult::Unknown
5967 }
5968
5969 /// [646] Hinweis: Es ist der RD-Bilanzkreis des ANB anzugeben
5970 fn evaluate_646(&self, _ctx: &EvaluationContext) -> ConditionResult {
5971 // TODO: implement
5972 ConditionResult::Unknown
5973 }
5974
5975 /// [647] Hinweis: Es ist der RD-Bilanzkreis des anfNB anzugeben
5976 fn evaluate_647(&self, _ctx: &EvaluationContext) -> ConditionResult {
5977 // TODO: implement
5978 ConditionResult::Unknown
5979 }
5980
5981 /// [648] Hinweis: Soll ein Produkt ab dem Datum \"Änderung zum\" nicht mehr vorhanden sein, wird dies durch nicht angeben des PIA+5 ausgedrückt
5982 fn evaluate_648(&self, _ctx: &EvaluationContext) -> ConditionResult {
5983 // TODO: implement
5984 ConditionResult::Unknown
5985 }
5986
5987 /// [651] Hinweis: Es sind die Marktlokationen anzugeben, zu welchen die hier genannte OBIS benötigt wird
5988 fn evaluate_651(&self, _ctx: &EvaluationContext) -> ConditionResult {
5989 // TODO: implement
5990 ConditionResult::Unknown
5991 }
5992
5993 /// [653] Hinweis: Es sind alle Netzlokationen, Marktlokationen, Tranchen und Messlokationen zu nennen, die durch die Bestätigung der Abmeldung der prozessual behandelten Messlokation nicht mehr dem MSB zug...
5994 fn evaluate_653(&self, _ctx: &EvaluationContext) -> ConditionResult {
5995 // TODO: implement
5996 ConditionResult::Unknown
5997 }
5998
5999 /// [655] Hinweis: Es ist die Listennummer aus der DZÜ Liste zu verwenden
6000 fn evaluate_655(&self, _ctx: &EvaluationContext) -> ConditionResult {
6001 // TODO: implement
6002 ConditionResult::Unknown
6003 }
6004
6005 /// [659] Hinweis: Bei Tranchen ist nur der Meldepunkt der Tranche anzugeben
6006 fn evaluate_659(&self, _ctx: &EvaluationContext) -> ConditionResult {
6007 // TODO: implement
6008 ConditionResult::Unknown
6009 }
6010
6011 /// [660] Hinweis: Es ist die ID der BK-Summenzeitreihe Aggregationsebene BG anzugeben
6012 fn evaluate_660(&self, _ctx: &EvaluationContext) -> ConditionResult {
6013 // TODO: implement
6014 ConditionResult::Unknown
6015 }
6016
6017 /// [662] Hinweis: Es sind die Daten NGZ und die Daten der NZR anzugeben
6018 fn evaluate_662(&self, _ctx: &EvaluationContext) -> ConditionResult {
6019 // TODO: implement
6020 ConditionResult::Unknown
6021 }
6022
6023 /// [663] Hinweis: Es ist die ID der Marktlokation und die ZPB des ZP der NGZ anzugeben
6024 fn evaluate_663(&self, _ctx: &EvaluationContext) -> ConditionResult {
6025 // TODO: implement
6026 ConditionResult::Unknown
6027 }
6028
6029 /// [664] Hinweis: Es ist das BG des NB (LPB) anzugeben
6030 fn evaluate_664(&self, _ctx: &EvaluationContext) -> ConditionResult {
6031 // TODO: implement
6032 ConditionResult::Unknown
6033 }
6034
6035 /// [665] Hinweis: Wenn ein Zähler mit einem SMGW parametriert ist werden an dem Zähler keine OBIS-Kennzahlen angegeben Hier gibt es nur OBIS Kennzahlen vom SMGW
6036 fn evaluate_665(&self, _ctx: &EvaluationContext) -> ConditionResult {
6037 // TODO: implement
6038 ConditionResult::Unknown
6039 }
6040
6041 /// [667] Hinweis: Für Zeiten die bilanziert wurden, aber inzwischen keine Aggregationsverantwortung beim ÜNB vorliegt, ist eine SG8 mit SG8 - SG10 CCI+6=ZA8 oder SG 10 CCI+6 = ZA9 CAV=ZG4 und SG8 - SG9 QT...
6042 fn evaluate_667(&self, _ctx: &EvaluationContext) -> ConditionResult {
6043 // TODO: implement
6044 ConditionResult::Unknown
6045 }
6046
6047 /// [668] Hinweis: Dieses Segment wird nach Abschluss der Einführung der Lokationsbündelstruktur zum 01.10.2025 aus der UTILMD entfernt
6048 fn evaluate_668(&self, _ctx: &EvaluationContext) -> ConditionResult {
6049 // TODO: implement
6050 ConditionResult::Unknown
6051 }
6052
6053 /// [670] Hinweis: Es sind alle Netzlokationen, zu nennen, die dem gleichen Lokationsbündel angehören
6054 fn evaluate_670(&self, _ctx: &EvaluationContext) -> ConditionResult {
6055 // TODO: implement
6056 ConditionResult::Unknown
6057 }
6058
6059 /// [671] Hinweis: Es sind alle Marktlokationen, zu nennen, die dem gleichen Lokationsbündel angehören
6060 fn evaluate_671(&self, _ctx: &EvaluationContext) -> ConditionResult {
6061 // TODO: implement
6062 ConditionResult::Unknown
6063 }
6064
6065 /// [672] Hinweis: Es sind alle Technischen Ressourcen, zu nennen, die dem gleichen Lokationsbündel angehören
6066 fn evaluate_672(&self, _ctx: &EvaluationContext) -> ConditionResult {
6067 // TODO: implement
6068 ConditionResult::Unknown
6069 }
6070
6071 /// [673] Hinweis: Es sind alle Steuerbaren Ressourcen, zu nennen, die dem gleichen Lokationsbündel angehören
6072 fn evaluate_673(&self, _ctx: &EvaluationContext) -> ConditionResult {
6073 // TODO: implement
6074 ConditionResult::Unknown
6075 }
6076
6077 /// [674] Hinweis: Es sind alle Tranchen, zu nennen, die dem gleichen Lokationsbündel angehören
6078 fn evaluate_674(&self, _ctx: &EvaluationContext) -> ConditionResult {
6079 // TODO: implement
6080 ConditionResult::Unknown
6081 }
6082
6083 /// [675] Hinweis: Es sind alle Messlokationen, zu nennen, die Lokationsbündel angehören
6084 fn evaluate_675(&self, _ctx: &EvaluationContext) -> ConditionResult {
6085 // TODO: implement
6086 ConditionResult::Unknown
6087 }
6088
6089 /// [677] Hinweis: Es sind alle Netzlokationen, zu nennen, die aktuell und / oder zukünftig dem gleichen Lokationsbündel angehören
6090 fn evaluate_677(&self, _ctx: &EvaluationContext) -> ConditionResult {
6091 // TODO: implement
6092 ConditionResult::Unknown
6093 }
6094
6095 /// [678] Hinweis: Es sind alle Marktlokationen, zu nennen, die aktuell und / oder zukünftig dem gleichen Lokationsbündel angehören
6096 fn evaluate_678(&self, _ctx: &EvaluationContext) -> ConditionResult {
6097 // TODO: implement
6098 ConditionResult::Unknown
6099 }
6100
6101 /// [679] Hinweis: Es sind alle Technischen Ressourcen, zu nennen, die aktuell und / oder zukünftig dem gleichen Lokationsbündel angehören
6102 fn evaluate_679(&self, _ctx: &EvaluationContext) -> ConditionResult {
6103 // TODO: implement
6104 ConditionResult::Unknown
6105 }
6106
6107 /// [680] Hinweis: Es sind alle Steuerbaren Ressourcen, zu nennen, die aktuell und / oder zukünftig dem gleichen Lokationsbündel angehören
6108 fn evaluate_680(&self, _ctx: &EvaluationContext) -> ConditionResult {
6109 // TODO: implement
6110 ConditionResult::Unknown
6111 }
6112
6113 /// [682] Hinweis: Es sind alle Messlokationen, zu nennen, die aktuell und / oder zukünftig dem gleichen Lokationsbündel angehören
6114 fn evaluate_682(&self, _ctx: &EvaluationContext) -> ConditionResult {
6115 // TODO: implement
6116 ConditionResult::Unknown
6117 }
6118
6119 /// [683] Hinweis: Es sind alle ID der Netzlokationen, welche der im SG5 LOC+Z16 angegebenen Marktlokation aktuell und / oder zukünftig vorgelagert sind, anzugeben
6120 fn evaluate_683(&self, _ctx: &EvaluationContext) -> ConditionResult {
6121 // TODO: implement
6122 ConditionResult::Unknown
6123 }
6124
6125 /// [684] Hinweis: Es sind alle ID der Technischen Ressourcen, welche der im LOC+Z16/ Z22 angegebenen Marktlokation aktuell und / oder zukünftig zugehören, anzugeben
6126 fn evaluate_684(&self, _ctx: &EvaluationContext) -> ConditionResult {
6127 // TODO: implement
6128 ConditionResult::Unknown
6129 }
6130
6131 /// [685] Hinweis: Es sind alle ID der Steuerbaren Ressourcen, welche der im LOC+Z20 angegebenen Technischen Ressourcen aktuell und / oder zukünftig zugeordnet sind, anzugeben.
6132 fn evaluate_685(&self, _ctx: &EvaluationContext) -> ConditionResult {
6133 // TODO: implement
6134 ConditionResult::Unknown
6135 }
6136
6137 /// [687] Hinweis: Es sind alle Messlokationen zu nennen, die für die Energiemengenermittlung aktuell und / oder zukünftig der im LOC+Z16/ Z22 angegebenen Marktlokation notwendig sind
6138 fn evaluate_687(&self, _ctx: &EvaluationContext) -> ConditionResult {
6139 // TODO: implement
6140 ConditionResult::Unknown
6141 }
6142
6143 /// [688] Hinweis: Es sind alle ID der Netzlokationen, welche der im LOC+Z16 angegebenen Marktlokation vorgelagert sind, anzugeben
6144 fn evaluate_688(&self, _ctx: &EvaluationContext) -> ConditionResult {
6145 // TODO: implement
6146 ConditionResult::Unknown
6147 }
6148
6149 /// [689] Hinweis: Es sind alle ID der Technischen Ressourcen, welche der im LOC+Z16 angegebenen Marktlokation zugehören, anzugeben
6150 fn evaluate_689(&self, _ctx: &EvaluationContext) -> ConditionResult {
6151 // TODO: implement
6152 ConditionResult::Unknown
6153 }
6154
6155 /// [690] Hinweis: Es sind alle ID der Steuerbaren Ressourcen, welche der im LOC+Z20 angegebenen Technischen Ressourcen zugeordnet sind, anzugeben
6156 fn evaluate_690(&self, _ctx: &EvaluationContext) -> ConditionResult {
6157 // TODO: implement
6158 ConditionResult::Unknown
6159 }
6160
6161 /// [693] Hinweis: Es sind die Daten NGZ anzugeben
6162 fn evaluate_693(&self, _ctx: &EvaluationContext) -> ConditionResult {
6163 // TODO: implement
6164 ConditionResult::Unknown
6165 }
6166
6167 /// [694] Hinweis: Wenn in einer Marktlokation eine ID für eine Technischen Ressource vergeben wird, müssen für alle ggf. weitere Technische Ressourcen in der Marktlokation ID vergeben werden. Hintergrund...
6168 fn evaluate_694(&self, _ctx: &EvaluationContext) -> ConditionResult {
6169 // TODO: implement
6170 ConditionResult::Unknown
6171 }
6172
6173 /// [695] Hinweis: Verwendung, wenn Rolle LF einem Unternehmen NB zugeordnet ist
6174 fn evaluate_695(&self, _ctx: &EvaluationContext) -> ConditionResult {
6175 // TODO: implement
6176 ConditionResult::Unknown
6177 }
6178
6179 /// [696] Hinweis: Verwendung, nur wenn die Rolle LF nicht einem Unternehmen NB zugeordnet ist
6180 fn evaluate_696(&self, _ctx: &EvaluationContext) -> ConditionResult {
6181 // TODO: implement
6182 ConditionResult::Unknown
6183 }
6184
6185 /// [698] Hinweis: Für eine erzeugende Marktlokation muss für jede Technische Ressource eine ID der Technischen Ressourcen vergeben werden. Dies ist notwendig um die Nennleistung der Technische Ressource b...
6186 fn evaluate_698(&self, _ctx: &EvaluationContext) -> ConditionResult {
6187 // TODO: implement
6188 ConditionResult::Unknown
6189 }
6190
6191 /// [699] Hinweis: Es ist die ID der Steuerbare Ressource zu nennen über die die Technische Ressource gesteuert wird
6192 fn evaluate_699(&self, _ctx: &EvaluationContext) -> ConditionResult {
6193 // TODO: implement
6194 ConditionResult::Unknown
6195 }
6196
6197 /// [700] Hinweis: Es ist die ID der Netzlokation zu nennen über die die Technische Ressource gesteuert wird
6198 fn evaluate_700(&self, _ctx: &EvaluationContext) -> ConditionResult {
6199 // TODO: implement
6200 ConditionResult::Unknown
6201 }
6202
6203 /// [704] Hinweis: Segment ist zu verwenden, wenn es in Anfrage vorhanden war
6204 fn evaluate_704(&self, _ctx: &EvaluationContext) -> ConditionResult {
6205 // TODO: implement
6206 ConditionResult::Unknown
6207 }
6208
6209 /// [705] Hinweis: Wenn die Aktion eines Sequenzdiagramms \"Rückmeldung auf Änderung\" durchgeführt wird
6210 fn evaluate_705(&self, _ctx: &EvaluationContext) -> ConditionResult {
6211 // TODO: implement
6212 ConditionResult::Unknown
6213 }
6214
6215 /// [706] Hinweis: Wenn die Aktion eines Sequenzdiagramms \"Bestellung einer Änderung von Stammdaten...\" durchgeführt wird, mit dem Ziel ein Datenclearing durchzuführen
6216 fn evaluate_706(&self, ctx: &EvaluationContext) -> ConditionResult {
6217 ctx.external.evaluate("data_clearing_required")
6218 }
6219
6220 /// [707] Hinweis: für weitere Details siehe Kapitel \"SG6 Verwendungszeitraum der Daten\"
6221 fn evaluate_707(&self, _ctx: &EvaluationContext) -> ConditionResult {
6222 // TODO: implement
6223 ConditionResult::Unknown
6224 }
6225
6226 /// [708] Hinweis: Wenn die Aktion \"Ankündigung der Zuordnung des E/G zur Marktlokation\" durchgeführt wird
6227 fn evaluate_708(&self, _ctx: &EvaluationContext) -> ConditionResult {
6228 // TODO: implement
6229 ConditionResult::Unknown
6230 }
6231
6232 /// [709] Hinweis: Wenn die Aktion \"Zuordnung des E/G zur Marktlokation aufgrund fehlender Antwort\" durchgeführt wird
6233 fn evaluate_709(&self, _ctx: &EvaluationContext) -> ConditionResult {
6234 // TODO: implement
6235 ConditionResult::Unknown
6236 }
6237
6238 /// [710] Hinweis: Wenn die Aktion \"Ankündigung der Zuordnung des LFN zur Marktlokation bzw. Tranche\" durchgeführt wird
6239 fn evaluate_710(&self, _ctx: &EvaluationContext) -> ConditionResult {
6240 // TODO: implement
6241 ConditionResult::Unknown
6242 }
6243
6244 /// [711] Hinweis: Wenn die Aktion \"Zuordnung des LFN zur Marktlokation bzw. Tranche aufgrund fehlender Antwort\" durchgeführt wird
6245 fn evaluate_711(&self, _ctx: &EvaluationContext) -> ConditionResult {
6246 // TODO: implement
6247 ConditionResult::Unknown
6248 }
6249
6250 /// [712] Hinweis: Wenn die Aktion \"Ankündigung der Beendigung der Zuordnung des LF zur Marktlokation bzw. Tranche\" durchgeführt wird
6251 fn evaluate_712(&self, _ctx: &EvaluationContext) -> ConditionResult {
6252 // TODO: implement
6253 ConditionResult::Unknown
6254 }
6255
6256 /// [713] Hinweis: Wenn die Aktion \"Beendigung der Zuordnung des LF zur Marktlokation bzw. Tranche aufgrund fehlender Antwort\" durchgeführt wird
6257 fn evaluate_713(&self, _ctx: &EvaluationContext) -> ConditionResult {
6258 // TODO: implement
6259 ConditionResult::Unknown
6260 }
6261
6262 /// [714] Hinweis: Es ist bei einer unterjährigen Gebietsübernahme möglich hier den bisherigen NB zu nennen um aufzuzeigen, dass die im PIA+5 dieser SG8 genannten Gruppenartikel-ID bzw. Artikel-ID auf die...
6263 fn evaluate_714(&self, _ctx: &EvaluationContext) -> ConditionResult {
6264 // TODO: implement
6265 ConditionResult::Unknown
6266 }
6267
6268 /// [715] Hinweis: Dieser Transaktionsgrund darf für die betroffene Lokation nur angewendet werden wenn zuvor vom LF eine Anfrage Abr.-Daten BK-Abr. in die Vergangenheit erfolgte oder eine Korrektur zuvor m...
6269 fn evaluate_715(&self, _ctx: &EvaluationContext) -> ConditionResult {
6270 // TODO: implement
6271 ConditionResult::Unknown
6272 }
6273
6274 /// [716] Hinweis: Wenn die Aktion eines Sequenzdiagramms \"Rückmeldung auf Abrechnungsdaten\" durchgeführt wird
6275 fn evaluate_716(&self, _ctx: &EvaluationContext) -> ConditionResult {
6276 // TODO: implement
6277 ConditionResult::Unknown
6278 }
6279
6280 /// [717] Hinweis: Wenn die Aktion des Sequenzdiagramms \"Bestellung einer Änderung von Abrechnungsdaten\" durchgeführt wird, mit dem Ziel ein Datenclearing durchzuführen
6281 fn evaluate_717(&self, ctx: &EvaluationContext) -> ConditionResult {
6282 ctx.external.evaluate("data_clearing_required")
6283 }
6284
6285 /// [718] Hinweis: Es sind alle Tranchen der im SG5 LOC+Z16 (Marktlokation) genannten Marktlokation anzugeben, die für die im SG6 (Verwendungszeitraum der Daten) genannten Zeiträume vorhanden sind
6286 fn evaluate_718(&self, _ctx: &EvaluationContext) -> ConditionResult {
6287 // TODO: implement
6288 ConditionResult::Unknown
6289 }
6290
6291 /// [719] Hinweis: Dieser Transaktionsgrund darf für die betroffene Lokation nur angewendet werden wenn der LF auf eine Anfrage mit diesem Transaktionsgrund antwortet oder eine Anfrage Abr.-Daten BK-Abr. in...
6292 fn evaluate_719(&self, _ctx: &EvaluationContext) -> ConditionResult {
6293 // TODO: implement
6294 ConditionResult::Unknown
6295 }
6296
6297 /// [902] Format: Möglicher Wert: ≥ 0
6298 fn evaluate_902(&self, _ctx: &EvaluationContext) -> ConditionResult {
6299 // TODO: implement
6300 ConditionResult::Unknown
6301 }
6302
6303 /// [910] Format: Möglicher Wert: < 0 oder ≥ 0
6304 fn evaluate_910(&self, _ctx: &EvaluationContext) -> ConditionResult {
6305 // TODO: implement
6306 ConditionResult::Unknown
6307 }
6308
6309 /// [914] Format: Möglicher Wert: > 0
6310 fn evaluate_914(&self, _ctx: &EvaluationContext) -> ConditionResult {
6311 // TODO: implement
6312 ConditionResult::Unknown
6313 }
6314
6315 /// [922] Format: TR-ID
6316 fn evaluate_922(&self, _ctx: &EvaluationContext) -> ConditionResult {
6317 // TODO: implement
6318 ConditionResult::Unknown
6319 }
6320
6321 /// [926] Format: Möglicher Wert: 0
6322 fn evaluate_926(&self, _ctx: &EvaluationContext) -> ConditionResult {
6323 // TODO: implement
6324 ConditionResult::Unknown
6325 }
6326
6327 /// [930] Format: max. 2 Nachkommastellen
6328 fn evaluate_930(&self, _ctx: &EvaluationContext) -> ConditionResult {
6329 // TODO: implement
6330 ConditionResult::Unknown
6331 }
6332
6333 /// [931] Format: ZZZ = +00
6334 fn evaluate_931(&self, _ctx: &EvaluationContext) -> ConditionResult {
6335 // TODO: implement
6336 ConditionResult::Unknown
6337 }
6338
6339 /// [932] Format: HHMM = 2200
6340 fn evaluate_932(&self, _ctx: &EvaluationContext) -> ConditionResult {
6341 // TODO: implement
6342 ConditionResult::Unknown
6343 }
6344
6345 /// [933] Format: HHMM = 2300
6346 fn evaluate_933(&self, _ctx: &EvaluationContext) -> ConditionResult {
6347 // TODO: implement
6348 ConditionResult::Unknown
6349 }
6350
6351 /// [937] Format: keine Nachkommastelle
6352 fn evaluate_937(&self, _ctx: &EvaluationContext) -> ConditionResult {
6353 // TODO: implement
6354 ConditionResult::Unknown
6355 }
6356
6357 /// [938] Format: Möglicher Wert: <= 10
6358 fn evaluate_938(&self, _ctx: &EvaluationContext) -> ConditionResult {
6359 // TODO: implement
6360 ConditionResult::Unknown
6361 }
6362
6363 /// [939] Format: Die Zeichenkette muss die Zeichen @ und . enthalten
6364 fn evaluate_939(&self, _ctx: &EvaluationContext) -> ConditionResult {
6365 // TODO: implement
6366 ConditionResult::Unknown
6367 }
6368
6369 /// [940] Format: Die Zeichenkette muss mit dem Zeichen + beginnen und danach dürfen nur noch Ziffern folgen
6370 fn evaluate_940(&self, _ctx: &EvaluationContext) -> ConditionResult {
6371 // TODO: implement
6372 ConditionResult::Unknown
6373 }
6374
6375 /// [942] Format: n1-n2-n1-n3
6376 fn evaluate_942(&self, _ctx: &EvaluationContext) -> ConditionResult {
6377 // TODO: implement
6378 ConditionResult::Unknown
6379 }
6380
6381 /// [943] Format: n1-n2-n1
6382 fn evaluate_943(&self, _ctx: &EvaluationContext) -> ConditionResult {
6383 // TODO: implement
6384 ConditionResult::Unknown
6385 }
6386
6387 /// [946] Format: max. 11 Nachkommastellen
6388 fn evaluate_946(&self, _ctx: &EvaluationContext) -> ConditionResult {
6389 // TODO: implement
6390 ConditionResult::Unknown
6391 }
6392
6393 /// [948] Format: n1-n2-n1-n8-n2
6394 fn evaluate_948(&self, _ctx: &EvaluationContext) -> ConditionResult {
6395 // TODO: implement
6396 ConditionResult::Unknown
6397 }
6398
6399 /// [950] Format: Marktlokations-ID
6400 fn evaluate_950(&self, _ctx: &EvaluationContext) -> ConditionResult {
6401 // TODO: implement
6402 ConditionResult::Unknown
6403 }
6404
6405 /// [951] Format: Zählpunktbezeichnung
6406 fn evaluate_951(&self, _ctx: &EvaluationContext) -> ConditionResult {
6407 // TODO: implement
6408 ConditionResult::Unknown
6409 }
6410
6411 /// [952] Format: Gerätenummer nach DIN 43863-5
6412 fn evaluate_952(&self, _ctx: &EvaluationContext) -> ConditionResult {
6413 // TODO: implement
6414 ConditionResult::Unknown
6415 }
6416
6417 /// [955] Format: Möglicher Wert: < 100
6418 fn evaluate_955(&self, _ctx: &EvaluationContext) -> ConditionResult {
6419 // TODO: implement
6420 ConditionResult::Unknown
6421 }
6422
6423 /// [957] Format: n1-n2-n1-n8
6424 fn evaluate_957(&self, _ctx: &EvaluationContext) -> ConditionResult {
6425 // TODO: implement
6426 ConditionResult::Unknown
6427 }
6428
6429 /// [960] Format: Netzlokations-ID
6430 fn evaluate_960(&self, _ctx: &EvaluationContext) -> ConditionResult {
6431 // TODO: implement
6432 ConditionResult::Unknown
6433 }
6434
6435 /// [961] Format: SR-ID
6436 fn evaluate_961(&self, _ctx: &EvaluationContext) -> ConditionResult {
6437 // TODO: implement
6438 ConditionResult::Unknown
6439 }
6440
6441 /// [967] Format: Zertifikatskörper gemäß X509.1, BSI TR-03109-4
6442 fn evaluate_967(&self, _ctx: &EvaluationContext) -> ConditionResult {
6443 // TODO: implement
6444 ConditionResult::Unknown
6445 }
6446
6447 /// [2001] Segmentgruppe ist mindestens zweimal je SG4 IDE+24 (Vorgang) anzugeben
6448 fn evaluate_2001(&self, _ctx: &EvaluationContext) -> ConditionResult {
6449 // TODO: implement
6450 ConditionResult::Unknown
6451 }
6452
6453 /// [2002] Für jede Produktpaket-ID im SG8 SEQ+Z79 (Erforderliches Produkt) DE1050 genau einmal anzugeben
6454 fn evaluate_2002(&self, _ctx: &EvaluationContext) -> ConditionResult {
6455 // TODO: implement
6456 ConditionResult::Unknown
6457 }
6458
6459 /// [2003] Einmal für jede ruhende Marktlokation, die der Marktlokation \"Kundenanlage\" aus dem SG5 LOC+Z16 (Marktlokation) ab dem Zeitpunkt aus dem SG4 DTM+92 (Beginn zum) untergeordnet ist
6460 fn evaluate_2003(&self, _ctx: &EvaluationContext) -> ConditionResult {
6461 // TODO: implement
6462 ConditionResult::Unknown
6463 }
6464
6465 /// [2004] Segmentgruppe ist genau einmal für jede Zeitraum-ID aus dem DE1156 der SG6 RFF+Z49 (Verwendungszeitraum der Daten: "Gültige Daten") anzugeben
6466 // REVIEW: Collects Zeitraum-IDs from SG6 RFF+Z49 DE1156 (elements[0][2]) by correlating qualifier (elements[0][0]) and ID (elements[0][2]) vectors via shared SG6 instance index. Then collects all SEQ DE1050 (elements[1][0]) references from SG8 instances. For each Zeitraum-ID from SG6 RFF+Z49, counts matching SG8 SEQ references; returns False if any count != 1 (violates 'exactly once' cardinality). Returns Unknown if no RFF+Z49 Zeitraum-IDs exist. (medium confidence)
6467 fn evaluate_2004(&self, ctx: &EvaluationContext) -> ConditionResult {
6468 let rff_qualifiers = ctx.collect_group_values("RFF", 0, 0, &["SG4", "SG6"]);
6469 let rff_zeitraum_ids = ctx.collect_group_values("RFF", 0, 2, &["SG4", "SG6"]);
6470
6471 let zeitraum_ids: Vec<String> = rff_qualifiers
6472 .iter()
6473 .filter(|(_, qual)| qual.as_str() == "Z49")
6474 .filter_map(|(idx, _)| {
6475 rff_zeitraum_ids
6476 .iter()
6477 .find(|(i, v)| i == idx && !v.is_empty())
6478 .map(|(_, v)| v.clone())
6479 })
6480 .collect();
6481
6482 if zeitraum_ids.is_empty() {
6483 return ConditionResult::Unknown;
6484 }
6485
6486 let seq_refs = ctx.collect_group_values("SEQ", 1, 0, &["SG4", "SG8"]);
6487
6488 for zid in &zeitraum_ids {
6489 let count = seq_refs.iter().filter(|(_, v)| v == zid).count();
6490 if count != 1 {
6491 return ConditionResult::False;
6492 }
6493 }
6494
6495 ConditionResult::True
6496 }
6497
6498 /// [2005] Segmentgruppe ist mindesten einmal für jede Zeitraum-ID aus dem DE1156 der SG6 RFF+Z49 (Verwendungszeitraum der Daten: "Gültige Daten") anzugeben
6499 // REVIEW: Same logic as 2004 but enforces 'at least once' cardinality (count >= 1) instead of 'exactly once'. Collects Zeitraum-IDs from SG6 RFF+Z49 DE1156 and checks that each has at least one matching SG8 SEQ DE1050 reference. Returns False if any Zeitraum-ID has zero matching SG8 references. (medium confidence)
6500 fn evaluate_2005(&self, ctx: &EvaluationContext) -> ConditionResult {
6501 let rff_qualifiers = ctx.collect_group_values("RFF", 0, 0, &["SG4", "SG6"]);
6502 let rff_zeitraum_ids = ctx.collect_group_values("RFF", 0, 2, &["SG4", "SG6"]);
6503
6504 let zeitraum_ids: Vec<String> = rff_qualifiers
6505 .iter()
6506 .filter(|(_, qual)| qual.as_str() == "Z49")
6507 .filter_map(|(idx, _)| {
6508 rff_zeitraum_ids
6509 .iter()
6510 .find(|(i, v)| i == idx && !v.is_empty())
6511 .map(|(_, v)| v.clone())
6512 })
6513 .collect();
6514
6515 if zeitraum_ids.is_empty() {
6516 return ConditionResult::Unknown;
6517 }
6518
6519 let seq_refs = ctx.collect_group_values("SEQ", 1, 0, &["SG4", "SG8"]);
6520
6521 for zid in &zeitraum_ids {
6522 let count = seq_refs.iter().filter(|(_, v)| v == zid).count();
6523 if count == 0 {
6524 return ConditionResult::False;
6525 }
6526 }
6527
6528 ConditionResult::True
6529 }
6530
6531 /// [2010] Segmentgruppe ist genau einmal für jede SG8 SEQ+Z01 (Daten der Marktlokation) anzugeben, bei der die Bedingungen [266] ∧ [479] an der Segmentgruppe erfüllt ist. Dabei ist die selbe Zeitraum-ID ...
6532 fn evaluate_2010(&self, _ctx: &EvaluationContext) -> ConditionResult {
6533 // TODO: implement
6534 ConditionResult::Unknown
6535 }
6536
6537 /// [2011] Segmentgruppe ist genau einmal für jede Zeitraum-ID aus dem DE1156 der SG6 RFF+Z49 / Z53 (Verwendungszeitraum der Daten: "Gültige Daten" / "Keine Daten") aus der Anfragennachricht aus SG6 RFF+TN ...
6538 /// EXTERNAL: Requires context from outside the message.
6539 // REVIEW: Condition requires checking Zeitraum-IDs from DE1156 of SG6 RFF+Z49/Z53 ('Verwendungszeitraum der Daten: Gültige Daten / Keine Daten') that originated in the REQUEST message referenced by SG6 RFF+TN DE1154. The referenced request message is a separate EDIFACT interchange not present in the current message being validated. The cardinality constraint ('exactly once per Zeitraum-ID from the request') is therefore an external business context check that depends on data from a prior message in the business process. (medium confidence)
6540 fn evaluate_2011(&self, ctx: &EvaluationContext) -> ConditionResult {
6541 ctx.external
6542 .evaluate("request_message_zeitraum_ids_present")
6543 }
6544
6545 /// [2012] Segmentgruppe ist genau einmal für die Angabe der Informativen Daten der Marktlokation anzugeben
6546 fn evaluate_2012(&self, _ctx: &EvaluationContext) -> ConditionResult {
6547 // TODO: implement
6548 ConditionResult::Unknown
6549 }
6550
6551 /// [2013] Mindesten einmal anzugeben wenn kein SG6 RFF+Z54 (Verwendungszeitraum der Daten: Im System keine Daten vorhanden) vorhanden
6552 fn evaluate_2013(&self, _ctx: &EvaluationContext) -> ConditionResult {
6553 // TODO: implement
6554 ConditionResult::Unknown
6555 }
6556
6557 /// [2014] Mindesten einmal anzugeben wenn kein SG6 RFF+Z47 (Verwendungszeitraum der Daten: Im System vorhandene Daten) vorhanden
6558 fn evaluate_2014(&self, _ctx: &EvaluationContext) -> ConditionResult {
6559 // TODO: implement
6560 ConditionResult::Unknown
6561 }
6562
6563 /// [2015] Einmal für jede ruhende Marktlokation, die der Marktlokation \"Kundenanlage\" aus dem SG5 LOC+Z16 (Marktlokation) untergeordnet ist
6564 fn evaluate_2015(&self, _ctx: &EvaluationContext) -> ConditionResult {
6565 // TODO: implement
6566 ConditionResult::Unknown
6567 }
6568
6569 /// [2016] Je SG5 LOC+Z16 (Marktlokation) ist genau einmal die Segmentgruppe anzugeben
6570 fn evaluate_2016(&self, _ctx: &EvaluationContext) -> ConditionResult {
6571 // TODO: implement
6572 ConditionResult::Unknown
6573 }
6574
6575 /// [2017] Je SG5 LOC+Z17 (Messlokation) ist genau einmal die Segmentgruppe anzugeben
6576 fn evaluate_2017(&self, _ctx: &EvaluationContext) -> ConditionResult {
6577 // TODO: implement
6578 ConditionResult::Unknown
6579 }
6580
6581 /// [2018] Segmentgruppe ist genau einmal für jede SG8 SEQ+Z01 (Daten der Marktlokation) anzugeben, bei der die Bedingungen [266] an der Segmentgruppe erfüllt ist. Dabei ist die selbe Zeitraum-ID im nachfol...
6582 fn evaluate_2018(&self, _ctx: &EvaluationContext) -> ConditionResult {
6583 // TODO: implement
6584 ConditionResult::Unknown
6585 }
6586
6587 /// [2060] Wenn SG10 CAV+NZR ist die Segmentgruppe genau zwei Mal je IDE+24 anzugeben
6588 fn evaluate_2060(&self, _ctx: &EvaluationContext) -> ConditionResult {
6589 // TODO: implement
6590 ConditionResult::Unknown
6591 }
6592
6593 /// [2061] Segment bzw. Segmentgruppe ist genau einmal je SG4 IDE (Vorgang) anzugeben
6594 fn evaluate_2061(&self, _ctx: &EvaluationContext) -> ConditionResult {
6595 // TODO: implement
6596 ConditionResult::Unknown
6597 }
6598
6599 /// [2071] Für die ID der LieferantensummenZR einmal je SG4 IDE+24 (Vorgang)
6600 fn evaluate_2071(&self, _ctx: &EvaluationContext) -> ConditionResult {
6601 // TODO: implement
6602 ConditionResult::Unknown
6603 }
6604
6605 /// [2073] Für die ID der BilanzkreissummenZR einmal je SG4 IDE+24 (Vorgang)
6606 fn evaluate_2073(&self, _ctx: &EvaluationContext) -> ConditionResult {
6607 // TODO: implement
6608 ConditionResult::Unknown
6609 }
6610
6611 /// [2075] Für die ID der Zeitreihen (nicht bei EEG-EUZ und EUZ der AAÜZ) in der Clearingliste einmal je SG4 IDE+24 (Vorgang)
6612 fn evaluate_2075(&self, _ctx: &EvaluationContext) -> ConditionResult {
6613 // TODO: implement
6614 ConditionResult::Unknown
6615 }
6616
6617 /// [2080] Segmentgruppe ist max. zweimal je SG4 IDE+24 (Vorgang) anzugeben
6618 fn evaluate_2080(&self, _ctx: &EvaluationContext) -> ConditionResult {
6619 // TODO: implement
6620 ConditionResult::Unknown
6621 }
6622
6623 /// [2095] Je SG5 LOC+Z15 (MaBiS-Zählpunkt) ist genau einmal die Segmentgruppe anzugeben
6624 fn evaluate_2095(&self, _ctx: &EvaluationContext) -> ConditionResult {
6625 // TODO: implement
6626 ConditionResult::Unknown
6627 }
6628
6629 /// [2096] Segmentgruppe ist genau zweimal je SG4 IDE anzugeben
6630 fn evaluate_2096(&self, _ctx: &EvaluationContext) -> ConditionResult {
6631 // TODO: implement
6632 ConditionResult::Unknown
6633 }
6634
6635 /// [2119] Je SG8 SEQ+Z13/ ZG0 (Smartmeter-Gateway) ist genau einmal die Segmentgruppe anzugeben
6636 fn evaluate_2119(&self, _ctx: &EvaluationContext) -> ConditionResult {
6637 // TODO: implement
6638 ConditionResult::Unknown
6639 }
6640
6641 /// [2140] Für die ID der LieferantensummenZR einmal je SG4 IDE+Z01 (Liste)
6642 fn evaluate_2140(&self, _ctx: &EvaluationContext) -> ConditionResult {
6643 // TODO: implement
6644 ConditionResult::Unknown
6645 }
6646
6647 /// [2182] Segmentgruppe ist genau einmal je SG8 SEQ+Z01/ Z80/ Z81/ Z98 (Daten der Marktlokation/ Erwartete Daten der Marktlokation/ Im System vorhandene Daten der Marktlokation) anzugeben
6648 fn evaluate_2182(&self, _ctx: &EvaluationContext) -> ConditionResult {
6649 // TODO: implement
6650 ConditionResult::Unknown
6651 }
6652
6653 /// [2183] Segmentgruppe ist genau zweimal je SG8 SEQ+Z01/ Z80/ Z81/ Z98 (Daten der Marktlokation/ Erwartete Daten der Marktlokation/ Im System vorhandene Daten der Marktlokation) anzugeben
6654 fn evaluate_2183(&self, _ctx: &EvaluationContext) -> ConditionResult {
6655 // TODO: implement
6656 ConditionResult::Unknown
6657 }
6658
6659 /// [2207] Für die ID der Lieferanten-ausfall-arbeits-summen-zeitreihe einmal je SG4 IDE+Z01 (Liste)
6660 fn evaluate_2207(&self, _ctx: &EvaluationContext) -> ConditionResult {
6661 // TODO: implement
6662 ConditionResult::Unknown
6663 }
6664
6665 /// [2225] Einmal für jede Marktlokation bzw. Tranche für die der LF nicht die gemeldete Ansicht des NB teilt
6666 fn evaluate_2225(&self, _ctx: &EvaluationContext) -> ConditionResult {
6667 // TODO: implement
6668 ConditionResult::Unknown
6669 }
6670
6671 /// [2236] Code einmal je SG4 IDE+24 (Vorgang)
6672 fn evaluate_2236(&self, _ctx: &EvaluationContext) -> ConditionResult {
6673 // TODO: implement
6674 ConditionResult::Unknown
6675 }
6676
6677 /// [2252] Einmal für jede Marktlokation bzw. Tranche, die in der Lieferantenausfallarbeits-summenzeitreihe berücksichtigt wurde
6678 fn evaluate_2252(&self, _ctx: &EvaluationContext) -> ConditionResult {
6679 // TODO: implement
6680 ConditionResult::Unknown
6681 }
6682
6683 /// [2261] Für jede ID im SG5 LOC+Z21 (Tranche) DE3225, mindestens einmal anzugeben
6684 fn evaluate_2261(&self, _ctx: &EvaluationContext) -> ConditionResult {
6685 // TODO: implement
6686 ConditionResult::Unknown
6687 }
6688
6689 /// [2284] Für jede Messlokations-ID im SG5 LOC+Z17 (Messlokation) DE3225 genau einmal anzugeben
6690 fn evaluate_2284(&self, _ctx: &EvaluationContext) -> ConditionResult {
6691 // TODO: implement
6692 ConditionResult::Unknown
6693 }
6694
6695 /// [2286] Für jede SEQ+ZF3 (Daten der Messlokation) mindestens einmal anzugeben
6696 fn evaluate_2286(&self, _ctx: &EvaluationContext) -> ConditionResult {
6697 // TODO: implement
6698 ConditionResult::Unknown
6699 }
6700
6701 /// [2287] Für jede SEQ+Z03/ ZF5 (Zähleinrichtungsdaten) mindestens einmal anzugeben
6702 fn evaluate_2287(&self, _ctx: &EvaluationContext) -> ConditionResult {
6703 // TODO: implement
6704 ConditionResult::Unknown
6705 }
6706
6707 /// [2288] Einmal für jede Zeitreihe, die in der DZR berücksichtigt wurde
6708 fn evaluate_2288(&self, _ctx: &EvaluationContext) -> ConditionResult {
6709 // TODO: implement
6710 ConditionResult::Unknown
6711 }
6712
6713 /// [2307] Für jede ID im SG5 LOC+Z21 (Tranche) DE3225 genau einmal anzugeben
6714 fn evaluate_2307(&self, _ctx: &EvaluationContext) -> ConditionResult {
6715 // TODO: implement
6716 ConditionResult::Unknown
6717 }
6718
6719 /// [2308] Für jede ID im SG5 LOC+Z16 (Marktlokation) DE3225, mindestens einmal anzugeben
6720 fn evaluate_2308(&self, _ctx: &EvaluationContext) -> ConditionResult {
6721 // TODO: implement
6722 ConditionResult::Unknown
6723 }
6724
6725 /// [2309] Für jede ID im SG5 LOC+Z17 (Messlokation) DE3225 mindestens einmal anzugeben
6726 fn evaluate_2309(&self, _ctx: &EvaluationContext) -> ConditionResult {
6727 // TODO: implement
6728 ConditionResult::Unknown
6729 }
6730
6731 /// [2310] Für jede ID im SG5 LOC+Z16 (Marktlokation) DE3225 genau einmal anzugeben
6732 fn evaluate_2310(&self, _ctx: &EvaluationContext) -> ConditionResult {
6733 // TODO: implement
6734 ConditionResult::Unknown
6735 }
6736
6737 /// [2311] Für jede ID im SG5 LOC+Z21 (Tranche) DE3225, mindestens einmal anzugeben
6738 fn evaluate_2311(&self, _ctx: &EvaluationContext) -> ConditionResult {
6739 // TODO: implement
6740 ConditionResult::Unknown
6741 }
6742
6743 /// [2312] Wenn der Objektcode \"9992000001256\" (Netzlokation) im DE1154 des selben RFF+Z33 nicht vorhanden ist, ist das RFF+Z33 in derselben SG8 SEQ+Z58/ ZC9/ ZD0/ ZD6 (Zuordnung Lokation zum Objektcode des...
6744 fn evaluate_2312(&self, _ctx: &EvaluationContext) -> ConditionResult {
6745 // TODO: implement
6746 ConditionResult::Unknown
6747 }
6748
6749 /// [2313] Je SG8 SEQ+Z58/ ZC9/ ZD0/ ZD6 (Zuordnung Lokation zum Objektcode des Lokationsbündels) genau einmal anzugeben
6750 fn evaluate_2313(&self, _ctx: &EvaluationContext) -> ConditionResult {
6751 // TODO: implement
6752 ConditionResult::Unknown
6753 }
6754
6755 /// [2317] Wenn in derselben SG8 SEQ+Z04/ ZF7 (Wandlerdaten) das SG10 CCI+++Z25 (Wandler) CAV+MIW/MPW/MUW vorhanden, ist das Segment mindestens zweimal anzugeben
6756 fn evaluate_2317(&self, _ctx: &EvaluationContext) -> ConditionResult {
6757 // TODO: implement
6758 ConditionResult::Unknown
6759 }
6760
6761 /// [2318] Wenn in derselben SG8 SEQ+Z04/ ZF7 (Wandlerdaten) das SG10 CCI+++Z25 (Wandler) CAV+MBW (Blockstromwandler) vorhanden, ist das Segment genau einmal anzugeben
6762 fn evaluate_2318(&self, _ctx: &EvaluationContext) -> ConditionResult {
6763 // TODO: implement
6764 ConditionResult::Unknown
6765 }
6766
6767 /// [2344] Einmal für jede Marktlokation bzw. Tranche, die in der DZÜ / BG-CL / LF-SZR berücksichtigt wurde
6768 fn evaluate_2344(&self, _ctx: &EvaluationContext) -> ConditionResult {
6769 // TODO: implement
6770 ConditionResult::Unknown
6771 }
6772
6773 /// [2350] Für jedes SMGW das im SEQ+Z13/ ZG0 (Smartmeter-Gateway) SG10 CCI+++Z75 CAV+Z30 (Gerätenummer) genannt ist, mindestens einmal je SEQ+Z03/ ZF5 (Zähleinrichtungsdaten) das mit SG8 RFF+Z14 (Referenz...
6774 fn evaluate_2350(&self, _ctx: &EvaluationContext) -> ConditionResult {
6775 // TODO: implement
6776 ConditionResult::Unknown
6777 }
6778
6779 /// [2351] Einmal je ZP einer BK-SZR, in der die Marktlokation in die Berechnung der abgerechneten Summenzeitreihe aufgenommen wurde
6780 fn evaluate_2351(&self, _ctx: &EvaluationContext) -> ConditionResult {
6781 // TODO: implement
6782 ConditionResult::Unknown
6783 }
6784
6785 /// [2352] Einmal je ZP einer BG-SZR, in der die Marktlokation in die Berechnung der abgerechneten Summenzeitreihe aufge-nommen wurde
6786 fn evaluate_2352(&self, _ctx: &EvaluationContext) -> ConditionResult {
6787 // TODO: implement
6788 ConditionResult::Unknown
6789 }
6790
6791 /// [2356] Je SG5 LOC+Z18 (Netzlokation) ist genau einmal die Segmentgruppe anzugeben
6792 fn evaluate_2356(&self, _ctx: &EvaluationContext) -> ConditionResult {
6793 // TODO: implement
6794 ConditionResult::Unknown
6795 }
6796
6797 /// [2357] Je SG5 LOC+Z20 (Technische Ressource) ist genau einmal die Segmentgruppe anzugeben
6798 fn evaluate_2357(&self, _ctx: &EvaluationContext) -> ConditionResult {
6799 // TODO: implement
6800 ConditionResult::Unknown
6801 }
6802
6803 /// [2358] Je SG5 LOC+Z19 (Steuerbare Ressource) ist genau einmal die Segmentgruppe anzugeben
6804 fn evaluate_2358(&self, _ctx: &EvaluationContext) -> ConditionResult {
6805 // TODO: implement
6806 ConditionResult::Unknown
6807 }
6808
6809 /// [2359] Für jede ID im SG5 LOC+Z16 / Z17 / Z20 (Marktlokation / Messlokation / Technische Ressource) DE3225 mindestens einmal anzugeben
6810 fn evaluate_2359(&self, _ctx: &EvaluationContext) -> ConditionResult {
6811 // TODO: implement
6812 ConditionResult::Unknown
6813 }
6814
6815 /// [2360] Für jede ID im SG5 LOC+Z18 (Netzlokation) DE3225 mindestens einmal anzugeben
6816 fn evaluate_2360(&self, _ctx: &EvaluationContext) -> ConditionResult {
6817 // TODO: implement
6818 ConditionResult::Unknown
6819 }
6820
6821 /// [2361] Für jede ID im SG5 LOC+Z17 / Z20 / Z22 (Messlokation / Technische Ressource / ruhende Marktlokation) DE3225 mindestens einmal anzugeben
6822 fn evaluate_2361(&self, _ctx: &EvaluationContext) -> ConditionResult {
6823 // TODO: implement
6824 ConditionResult::Unknown
6825 }
6826}