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