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(14);
28 external_conditions.insert(31);
29 external_conditions.insert(33);
30 external_conditions.insert(36);
31 external_conditions.insert(38);
32 external_conditions.insert(39);
33 external_conditions.insert(40);
34 external_conditions.insert(75);
35 external_conditions.insert(98);
36 external_conditions.insert(99);
37 external_conditions.insert(151);
38 external_conditions.insert(233);
39 external_conditions.insert(241);
40 external_conditions.insert(251);
41 external_conditions.insert(292);
42 external_conditions.insert(314);
43 external_conditions.insert(315);
44 external_conditions.insert(323);
45 external_conditions.insert(326);
46 external_conditions.insert(328);
47 external_conditions.insert(412);
48 external_conditions.insert(425);
49 external_conditions.insert(426);
50 external_conditions.insert(427);
51 external_conditions.insert(428);
52 external_conditions.insert(429);
53 external_conditions.insert(433);
54 external_conditions.insert(435);
55 external_conditions.insert(453);
56 external_conditions.insert(459);
57 external_conditions.insert(460);
58 external_conditions.insert(706);
59 external_conditions.insert(717);
60 Self {
61 external_conditions,
62 }
63 }
64}
65
66impl ConditionEvaluator for UtilmdStromConditionEvaluatorFV2510 {
67 fn message_type(&self) -> &str {
68 "UTILMD_Strom"
69 }
70
71 fn format_version(&self) -> &str {
72 "FV2510"
73 }
74
75 fn evaluate(&self, condition: u32, ctx: &EvaluationContext) -> ConditionResult {
76 match condition {
77 1 => self.evaluate_1(ctx),
78 2 => self.evaluate_2(ctx),
79 3 => self.evaluate_3(ctx),
80 4 => self.evaluate_4(ctx),
81 5 => self.evaluate_5(ctx),
82 6 => self.evaluate_6(ctx),
83 7 => self.evaluate_7(ctx),
84 8 => self.evaluate_8(ctx),
85 9 => self.evaluate_9(ctx),
86 10 => self.evaluate_10(ctx),
87 11 => self.evaluate_11(ctx),
88 12 => self.evaluate_12(ctx),
89 13 => self.evaluate_13(ctx),
90 14 => self.evaluate_14(ctx),
91 15 => self.evaluate_15(ctx),
92 16 => self.evaluate_16(ctx),
93 17 => self.evaluate_17(ctx),
94 18 => self.evaluate_18(ctx),
95 19 => self.evaluate_19(ctx),
96 20 => self.evaluate_20(ctx),
97 21 => self.evaluate_21(ctx),
98 22 => self.evaluate_22(ctx),
99 23 => self.evaluate_23(ctx),
100 24 => self.evaluate_24(ctx),
101 25 => self.evaluate_25(ctx),
102 27 => self.evaluate_27(ctx),
103 28 => self.evaluate_28(ctx),
104 29 => self.evaluate_29(ctx),
105 30 => self.evaluate_30(ctx),
106 31 => self.evaluate_31(ctx),
107 32 => self.evaluate_32(ctx),
108 33 => self.evaluate_33(ctx),
109 34 => self.evaluate_34(ctx),
110 35 => self.evaluate_35(ctx),
111 36 => self.evaluate_36(ctx),
112 37 => self.evaluate_37(ctx),
113 38 => self.evaluate_38(ctx),
114 39 => self.evaluate_39(ctx),
115 40 => self.evaluate_40(ctx),
116 41 => self.evaluate_41(ctx),
117 42 => self.evaluate_42(ctx),
118 43 => self.evaluate_43(ctx),
119 44 => self.evaluate_44(ctx),
120 45 => self.evaluate_45(ctx),
121 46 => self.evaluate_46(ctx),
122 47 => self.evaluate_47(ctx),
123 48 => self.evaluate_48(ctx),
124 49 => self.evaluate_49(ctx),
125 50 => self.evaluate_50(ctx),
126 51 => self.evaluate_51(ctx),
127 52 => self.evaluate_52(ctx),
128 53 => self.evaluate_53(ctx),
129 54 => self.evaluate_54(ctx),
130 55 => self.evaluate_55(ctx),
131 56 => self.evaluate_56(ctx),
132 57 => self.evaluate_57(ctx),
133 58 => self.evaluate_58(ctx),
134 60 => self.evaluate_60(ctx),
135 61 => self.evaluate_61(ctx),
136 62 => self.evaluate_62(ctx),
137 63 => self.evaluate_63(ctx),
138 64 => self.evaluate_64(ctx),
139 65 => self.evaluate_65(ctx),
140 66 => self.evaluate_66(ctx),
141 67 => self.evaluate_67(ctx),
142 68 => self.evaluate_68(ctx),
143 69 => self.evaluate_69(ctx),
144 70 => self.evaluate_70(ctx),
145 71 => self.evaluate_71(ctx),
146 72 => self.evaluate_72(ctx),
147 73 => self.evaluate_73(ctx),
148 74 => self.evaluate_74(ctx),
149 75 => self.evaluate_75(ctx),
150 76 => self.evaluate_76(ctx),
151 77 => self.evaluate_77(ctx),
152 78 => self.evaluate_78(ctx),
153 79 => self.evaluate_79(ctx),
154 83 => self.evaluate_83(ctx),
155 84 => self.evaluate_84(ctx),
156 85 => self.evaluate_85(ctx),
157 86 => self.evaluate_86(ctx),
158 87 => self.evaluate_87(ctx),
159 88 => self.evaluate_88(ctx),
160 89 => self.evaluate_89(ctx),
161 90 => self.evaluate_90(ctx),
162 91 => self.evaluate_91(ctx),
163 92 => self.evaluate_92(ctx),
164 93 => self.evaluate_93(ctx),
165 94 => self.evaluate_94(ctx),
166 95 => self.evaluate_95(ctx),
167 96 => self.evaluate_96(ctx),
168 97 => self.evaluate_97(ctx),
169 98 => self.evaluate_98(ctx),
170 99 => self.evaluate_99(ctx),
171 100 => self.evaluate_100(ctx),
172 101 => self.evaluate_101(ctx),
173 102 => self.evaluate_102(ctx),
174 103 => self.evaluate_103(ctx),
175 104 => self.evaluate_104(ctx),
176 105 => self.evaluate_105(ctx),
177 106 => self.evaluate_106(ctx),
178 107 => self.evaluate_107(ctx),
179 108 => self.evaluate_108(ctx),
180 110 => self.evaluate_110(ctx),
181 111 => self.evaluate_111(ctx),
182 112 => self.evaluate_112(ctx),
183 113 => self.evaluate_113(ctx),
184 114 => self.evaluate_114(ctx),
185 115 => self.evaluate_115(ctx),
186 116 => self.evaluate_116(ctx),
187 117 => self.evaluate_117(ctx),
188 118 => self.evaluate_118(ctx),
189 119 => self.evaluate_119(ctx),
190 120 => self.evaluate_120(ctx),
191 121 => self.evaluate_121(ctx),
192 122 => self.evaluate_122(ctx),
193 123 => self.evaluate_123(ctx),
194 124 => self.evaluate_124(ctx),
195 125 => self.evaluate_125(ctx),
196 126 => self.evaluate_126(ctx),
197 127 => self.evaluate_127(ctx),
198 128 => self.evaluate_128(ctx),
199 129 => self.evaluate_129(ctx),
200 130 => self.evaluate_130(ctx),
201 131 => self.evaluate_131(ctx),
202 132 => self.evaluate_132(ctx),
203 133 => self.evaluate_133(ctx),
204 134 => self.evaluate_134(ctx),
205 135 => self.evaluate_135(ctx),
206 136 => self.evaluate_136(ctx),
207 137 => self.evaluate_137(ctx),
208 138 => self.evaluate_138(ctx),
209 139 => self.evaluate_139(ctx),
210 140 => self.evaluate_140(ctx),
211 141 => self.evaluate_141(ctx),
212 142 => self.evaluate_142(ctx),
213 143 => self.evaluate_143(ctx),
214 144 => self.evaluate_144(ctx),
215 145 => self.evaluate_145(ctx),
216 146 => self.evaluate_146(ctx),
217 147 => self.evaluate_147(ctx),
218 148 => self.evaluate_148(ctx),
219 149 => self.evaluate_149(ctx),
220 150 => self.evaluate_150(ctx),
221 151 => self.evaluate_151(ctx),
222 152 => self.evaluate_152(ctx),
223 153 => self.evaluate_153(ctx),
224 156 => self.evaluate_156(ctx),
225 157 => self.evaluate_157(ctx),
226 161 => self.evaluate_161(ctx),
227 162 => self.evaluate_162(ctx),
228 163 => self.evaluate_163(ctx),
229 164 => self.evaluate_164(ctx),
230 165 => self.evaluate_165(ctx),
231 166 => self.evaluate_166(ctx),
232 167 => self.evaluate_167(ctx),
233 168 => self.evaluate_168(ctx),
234 169 => self.evaluate_169(ctx),
235 170 => self.evaluate_170(ctx),
236 172 => self.evaluate_172(ctx),
237 173 => self.evaluate_173(ctx),
238 174 => self.evaluate_174(ctx),
239 175 => self.evaluate_175(ctx),
240 176 => self.evaluate_176(ctx),
241 177 => self.evaluate_177(ctx),
242 178 => self.evaluate_178(ctx),
243 179 => self.evaluate_179(ctx),
244 180 => self.evaluate_180(ctx),
245 184 => self.evaluate_184(ctx),
246 190 => self.evaluate_190(ctx),
247 191 => self.evaluate_191(ctx),
248 192 => self.evaluate_192(ctx),
249 193 => self.evaluate_193(ctx),
250 194 => self.evaluate_194(ctx),
251 195 => self.evaluate_195(ctx),
252 196 => self.evaluate_196(ctx),
253 197 => self.evaluate_197(ctx),
254 198 => self.evaluate_198(ctx),
255 199 => self.evaluate_199(ctx),
256 201 => self.evaluate_201(ctx),
257 202 => self.evaluate_202(ctx),
258 203 => self.evaluate_203(ctx),
259 204 => self.evaluate_204(ctx),
260 205 => self.evaluate_205(ctx),
261 206 => self.evaluate_206(ctx),
262 209 => self.evaluate_209(ctx),
263 210 => self.evaluate_210(ctx),
264 212 => self.evaluate_212(ctx),
265 213 => self.evaluate_213(ctx),
266 215 => self.evaluate_215(ctx),
267 216 => self.evaluate_216(ctx),
268 217 => self.evaluate_217(ctx),
269 219 => self.evaluate_219(ctx),
270 220 => self.evaluate_220(ctx),
271 221 => self.evaluate_221(ctx),
272 223 => self.evaluate_223(ctx),
273 224 => self.evaluate_224(ctx),
274 227 => self.evaluate_227(ctx),
275 229 => self.evaluate_229(ctx),
276 232 => self.evaluate_232(ctx),
277 233 => self.evaluate_233(ctx),
278 234 => self.evaluate_234(ctx),
279 237 => self.evaluate_237(ctx),
280 238 => self.evaluate_238(ctx),
281 239 => self.evaluate_239(ctx),
282 240 => self.evaluate_240(ctx),
283 241 => self.evaluate_241(ctx),
284 242 => self.evaluate_242(ctx),
285 243 => self.evaluate_243(ctx),
286 244 => self.evaluate_244(ctx),
287 248 => self.evaluate_248(ctx),
288 249 => self.evaluate_249(ctx),
289 251 => self.evaluate_251(ctx),
290 252 => self.evaluate_252(ctx),
291 253 => self.evaluate_253(ctx),
292 254 => self.evaluate_254(ctx),
293 255 => self.evaluate_255(ctx),
294 256 => self.evaluate_256(ctx),
295 257 => self.evaluate_257(ctx),
296 258 => self.evaluate_258(ctx),
297 259 => self.evaluate_259(ctx),
298 261 => self.evaluate_261(ctx),
299 262 => self.evaluate_262(ctx),
300 265 => self.evaluate_265(ctx),
301 266 => self.evaluate_266(ctx),
302 267 => self.evaluate_267(ctx),
303 268 => self.evaluate_268(ctx),
304 269 => self.evaluate_269(ctx),
305 270 => self.evaluate_270(ctx),
306 273 => self.evaluate_273(ctx),
307 279 => self.evaluate_279(ctx),
308 280 => self.evaluate_280(ctx),
309 282 => self.evaluate_282(ctx),
310 284 => self.evaluate_284(ctx),
311 285 => self.evaluate_285(ctx),
312 286 => self.evaluate_286(ctx),
313 287 => self.evaluate_287(ctx),
314 288 => self.evaluate_288(ctx),
315 291 => self.evaluate_291(ctx),
316 292 => self.evaluate_292(ctx),
317 293 => self.evaluate_293(ctx),
318 294 => self.evaluate_294(ctx),
319 295 => self.evaluate_295(ctx),
320 296 => self.evaluate_296(ctx),
321 297 => self.evaluate_297(ctx),
322 298 => self.evaluate_298(ctx),
323 300 => self.evaluate_300(ctx),
324 301 => self.evaluate_301(ctx),
325 302 => self.evaluate_302(ctx),
326 303 => self.evaluate_303(ctx),
327 304 => self.evaluate_304(ctx),
328 305 => self.evaluate_305(ctx),
329 306 => self.evaluate_306(ctx),
330 307 => self.evaluate_307(ctx),
331 309 => self.evaluate_309(ctx),
332 312 => self.evaluate_312(ctx),
333 313 => self.evaluate_313(ctx),
334 314 => self.evaluate_314(ctx),
335 315 => self.evaluate_315(ctx),
336 316 => self.evaluate_316(ctx),
337 317 => self.evaluate_317(ctx),
338 318 => self.evaluate_318(ctx),
339 321 => self.evaluate_321(ctx),
340 322 => self.evaluate_322(ctx),
341 323 => self.evaluate_323(ctx),
342 326 => self.evaluate_326(ctx),
343 327 => self.evaluate_327(ctx),
344 328 => self.evaluate_328(ctx),
345 329 => self.evaluate_329(ctx),
346 332 => self.evaluate_332(ctx),
347 333 => self.evaluate_333(ctx),
348 334 => self.evaluate_334(ctx),
349 335 => self.evaluate_335(ctx),
350 336 => self.evaluate_336(ctx),
351 337 => self.evaluate_337(ctx),
352 338 => self.evaluate_338(ctx),
353 339 => self.evaluate_339(ctx),
354 340 => self.evaluate_340(ctx),
355 341 => self.evaluate_341(ctx),
356 342 => self.evaluate_342(ctx),
357 344 => self.evaluate_344(ctx),
358 345 => self.evaluate_345(ctx),
359 346 => self.evaluate_346(ctx),
360 347 => self.evaluate_347(ctx),
361 348 => self.evaluate_348(ctx),
362 349 => self.evaluate_349(ctx),
363 350 => self.evaluate_350(ctx),
364 351 => self.evaluate_351(ctx),
365 352 => self.evaluate_352(ctx),
366 355 => self.evaluate_355(ctx),
367 356 => self.evaluate_356(ctx),
368 357 => self.evaluate_357(ctx),
369 358 => self.evaluate_358(ctx),
370 359 => self.evaluate_359(ctx),
371 360 => self.evaluate_360(ctx),
372 363 => self.evaluate_363(ctx),
373 365 => self.evaluate_365(ctx),
374 366 => self.evaluate_366(ctx),
375 367 => self.evaluate_367(ctx),
376 368 => self.evaluate_368(ctx),
377 370 => self.evaluate_370(ctx),
378 371 => self.evaluate_371(ctx),
379 372 => self.evaluate_372(ctx),
380 373 => self.evaluate_373(ctx),
381 375 => self.evaluate_375(ctx),
382 376 => self.evaluate_376(ctx),
383 377 => self.evaluate_377(ctx),
384 378 => self.evaluate_378(ctx),
385 379 => self.evaluate_379(ctx),
386 380 => self.evaluate_380(ctx),
387 384 => self.evaluate_384(ctx),
388 386 => self.evaluate_386(ctx),
389 387 => self.evaluate_387(ctx),
390 388 => self.evaluate_388(ctx),
391 391 => self.evaluate_391(ctx),
392 392 => self.evaluate_392(ctx),
393 393 => self.evaluate_393(ctx),
394 394 => self.evaluate_394(ctx),
395 395 => self.evaluate_395(ctx),
396 396 => self.evaluate_396(ctx),
397 397 => self.evaluate_397(ctx),
398 398 => self.evaluate_398(ctx),
399 399 => self.evaluate_399(ctx),
400 401 => self.evaluate_401(ctx),
401 402 => self.evaluate_402(ctx),
402 403 => self.evaluate_403(ctx),
403 404 => self.evaluate_404(ctx),
404 405 => self.evaluate_405(ctx),
405 406 => self.evaluate_406(ctx),
406 407 => self.evaluate_407(ctx),
407 408 => self.evaluate_408(ctx),
408 409 => self.evaluate_409(ctx),
409 410 => self.evaluate_410(ctx),
410 411 => self.evaluate_411(ctx),
411 412 => self.evaluate_412(ctx),
412 413 => self.evaluate_413(ctx),
413 414 => self.evaluate_414(ctx),
414 415 => self.evaluate_415(ctx),
415 416 => self.evaluate_416(ctx),
416 417 => self.evaluate_417(ctx),
417 419 => self.evaluate_419(ctx),
418 420 => self.evaluate_420(ctx),
419 421 => self.evaluate_421(ctx),
420 425 => self.evaluate_425(ctx),
421 426 => self.evaluate_426(ctx),
422 427 => self.evaluate_427(ctx),
423 428 => self.evaluate_428(ctx),
424 429 => self.evaluate_429(ctx),
425 430 => self.evaluate_430(ctx),
426 431 => self.evaluate_431(ctx),
427 432 => self.evaluate_432(ctx),
428 433 => self.evaluate_433(ctx),
429 435 => self.evaluate_435(ctx),
430 436 => self.evaluate_436(ctx),
431 437 => self.evaluate_437(ctx),
432 438 => self.evaluate_438(ctx),
433 440 => self.evaluate_440(ctx),
434 441 => self.evaluate_441(ctx),
435 442 => self.evaluate_442(ctx),
436 444 => self.evaluate_444(ctx),
437 445 => self.evaluate_445(ctx),
438 446 => self.evaluate_446(ctx),
439 447 => self.evaluate_447(ctx),
440 448 => self.evaluate_448(ctx),
441 449 => self.evaluate_449(ctx),
442 450 => self.evaluate_450(ctx),
443 451 => self.evaluate_451(ctx),
444 452 => self.evaluate_452(ctx),
445 453 => self.evaluate_453(ctx),
446 454 => self.evaluate_454(ctx),
447 455 => self.evaluate_455(ctx),
448 456 => self.evaluate_456(ctx),
449 457 => self.evaluate_457(ctx),
450 458 => self.evaluate_458(ctx),
451 459 => self.evaluate_459(ctx),
452 460 => self.evaluate_460(ctx),
453 461 => self.evaluate_461(ctx),
454 462 => self.evaluate_462(ctx),
455 463 => self.evaluate_463(ctx),
456 465 => self.evaluate_465(ctx),
457 466 => self.evaluate_466(ctx),
458 467 => self.evaluate_467(ctx),
459 468 => self.evaluate_468(ctx),
460 469 => self.evaluate_469(ctx),
461 470 => self.evaluate_470(ctx),
462 471 => self.evaluate_471(ctx),
463 472 => self.evaluate_472(ctx),
464 473 => self.evaluate_473(ctx),
465 474 => self.evaluate_474(ctx),
466 475 => self.evaluate_475(ctx),
467 476 => self.evaluate_476(ctx),
468 477 => self.evaluate_477(ctx),
469 478 => self.evaluate_478(ctx),
470 479 => self.evaluate_479(ctx),
471 480 => self.evaluate_480(ctx),
472 481 => self.evaluate_481(ctx),
473 483 => self.evaluate_483(ctx),
474 484 => self.evaluate_484(ctx),
475 487 => self.evaluate_487(ctx),
476 489 => self.evaluate_489(ctx),
477 490 => self.evaluate_490(ctx),
478 491 => self.evaluate_491(ctx),
479 494 => self.evaluate_494(ctx),
480 500 => self.evaluate_500(ctx),
481 501 => self.evaluate_501(ctx),
482 502 => self.evaluate_502(ctx),
483 503 => self.evaluate_503(ctx),
484 504 => self.evaluate_504(ctx),
485 505 => self.evaluate_505(ctx),
486 506 => self.evaluate_506(ctx),
487 507 => self.evaluate_507(ctx),
488 508 => self.evaluate_508(ctx),
489 509 => self.evaluate_509(ctx),
490 510 => self.evaluate_510(ctx),
491 511 => self.evaluate_511(ctx),
492 512 => self.evaluate_512(ctx),
493 513 => self.evaluate_513(ctx),
494 514 => self.evaluate_514(ctx),
495 515 => self.evaluate_515(ctx),
496 516 => self.evaluate_516(ctx),
497 517 => self.evaluate_517(ctx),
498 518 => self.evaluate_518(ctx),
499 519 => self.evaluate_519(ctx),
500 520 => self.evaluate_520(ctx),
501 521 => self.evaluate_521(ctx),
502 522 => self.evaluate_522(ctx),
503 523 => self.evaluate_523(ctx),
504 524 => self.evaluate_524(ctx),
505 525 => self.evaluate_525(ctx),
506 526 => self.evaluate_526(ctx),
507 527 => self.evaluate_527(ctx),
508 528 => self.evaluate_528(ctx),
509 529 => self.evaluate_529(ctx),
510 530 => self.evaluate_530(ctx),
511 531 => self.evaluate_531(ctx),
512 532 => self.evaluate_532(ctx),
513 533 => self.evaluate_533(ctx),
514 534 => self.evaluate_534(ctx),
515 555 => self.evaluate_555(ctx),
516 556 => self.evaluate_556(ctx),
517 557 => self.evaluate_557(ctx),
518 558 => self.evaluate_558(ctx),
519 559 => self.evaluate_559(ctx),
520 560 => self.evaluate_560(ctx),
521 561 => self.evaluate_561(ctx),
522 562 => self.evaluate_562(ctx),
523 563 => self.evaluate_563(ctx),
524 564 => self.evaluate_564(ctx),
525 565 => self.evaluate_565(ctx),
526 566 => self.evaluate_566(ctx),
527 567 => self.evaluate_567(ctx),
528 568 => self.evaluate_568(ctx),
529 569 => self.evaluate_569(ctx),
530 570 => self.evaluate_570(ctx),
531 572 => self.evaluate_572(ctx),
532 576 => self.evaluate_576(ctx),
533 577 => self.evaluate_577(ctx),
534 578 => self.evaluate_578(ctx),
535 579 => self.evaluate_579(ctx),
536 580 => self.evaluate_580(ctx),
537 581 => self.evaluate_581(ctx),
538 586 => self.evaluate_586(ctx),
539 590 => self.evaluate_590(ctx),
540 594 => self.evaluate_594(ctx),
541 599 => self.evaluate_599(ctx),
542 601 => self.evaluate_601(ctx),
543 606 => self.evaluate_606(ctx),
544 609 => self.evaluate_609(ctx),
545 611 => self.evaluate_611(ctx),
546 614 => self.evaluate_614(ctx),
547 617 => self.evaluate_617(ctx),
548 618 => self.evaluate_618(ctx),
549 619 => self.evaluate_619(ctx),
550 621 => self.evaluate_621(ctx),
551 622 => self.evaluate_622(ctx),
552 623 => self.evaluate_623(ctx),
553 630 => self.evaluate_630(ctx),
554 631 => self.evaluate_631(ctx),
555 632 => self.evaluate_632(ctx),
556 637 => self.evaluate_637(ctx),
557 638 => self.evaluate_638(ctx),
558 639 => self.evaluate_639(ctx),
559 640 => self.evaluate_640(ctx),
560 641 => self.evaluate_641(ctx),
561 642 => self.evaluate_642(ctx),
562 643 => self.evaluate_643(ctx),
563 645 => self.evaluate_645(ctx),
564 646 => self.evaluate_646(ctx),
565 647 => self.evaluate_647(ctx),
566 648 => self.evaluate_648(ctx),
567 651 => self.evaluate_651(ctx),
568 653 => self.evaluate_653(ctx),
569 655 => self.evaluate_655(ctx),
570 659 => self.evaluate_659(ctx),
571 660 => self.evaluate_660(ctx),
572 662 => self.evaluate_662(ctx),
573 663 => self.evaluate_663(ctx),
574 664 => self.evaluate_664(ctx),
575 665 => self.evaluate_665(ctx),
576 667 => self.evaluate_667(ctx),
577 668 => self.evaluate_668(ctx),
578 670 => self.evaluate_670(ctx),
579 671 => self.evaluate_671(ctx),
580 672 => self.evaluate_672(ctx),
581 673 => self.evaluate_673(ctx),
582 674 => self.evaluate_674(ctx),
583 675 => self.evaluate_675(ctx),
584 677 => self.evaluate_677(ctx),
585 678 => self.evaluate_678(ctx),
586 679 => self.evaluate_679(ctx),
587 680 => self.evaluate_680(ctx),
588 681 => self.evaluate_681(ctx),
589 682 => self.evaluate_682(ctx),
590 683 => self.evaluate_683(ctx),
591 684 => self.evaluate_684(ctx),
592 685 => self.evaluate_685(ctx),
593 686 => self.evaluate_686(ctx),
594 687 => self.evaluate_687(ctx),
595 688 => self.evaluate_688(ctx),
596 689 => self.evaluate_689(ctx),
597 690 => self.evaluate_690(ctx),
598 693 => self.evaluate_693(ctx),
599 694 => self.evaluate_694(ctx),
600 695 => self.evaluate_695(ctx),
601 696 => self.evaluate_696(ctx),
602 698 => self.evaluate_698(ctx),
603 699 => self.evaluate_699(ctx),
604 700 => self.evaluate_700(ctx),
605 704 => self.evaluate_704(ctx),
606 705 => self.evaluate_705(ctx),
607 706 => self.evaluate_706(ctx),
608 707 => self.evaluate_707(ctx),
609 708 => self.evaluate_708(ctx),
610 709 => self.evaluate_709(ctx),
611 710 => self.evaluate_710(ctx),
612 711 => self.evaluate_711(ctx),
613 712 => self.evaluate_712(ctx),
614 713 => self.evaluate_713(ctx),
615 714 => self.evaluate_714(ctx),
616 715 => self.evaluate_715(ctx),
617 716 => self.evaluate_716(ctx),
618 717 => self.evaluate_717(ctx),
619 718 => self.evaluate_718(ctx),
620 719 => self.evaluate_719(ctx),
621 902 => self.evaluate_902(ctx),
622 910 => self.evaluate_910(ctx),
623 914 => self.evaluate_914(ctx),
624 922 => self.evaluate_922(ctx),
625 926 => self.evaluate_926(ctx),
626 930 => self.evaluate_930(ctx),
627 931 => self.evaluate_931(ctx),
628 932 => self.evaluate_932(ctx),
629 933 => self.evaluate_933(ctx),
630 937 => self.evaluate_937(ctx),
631 938 => self.evaluate_938(ctx),
632 939 => self.evaluate_939(ctx),
633 940 => self.evaluate_940(ctx),
634 942 => self.evaluate_942(ctx),
635 943 => self.evaluate_943(ctx),
636 946 => self.evaluate_946(ctx),
637 948 => self.evaluate_948(ctx),
638 950 => self.evaluate_950(ctx),
639 951 => self.evaluate_951(ctx),
640 952 => self.evaluate_952(ctx),
641 955 => self.evaluate_955(ctx),
642 957 => self.evaluate_957(ctx),
643 960 => self.evaluate_960(ctx),
644 961 => self.evaluate_961(ctx),
645 967 => self.evaluate_967(ctx),
646 2000 => self.evaluate_2000(ctx),
647 2001 => self.evaluate_2001(ctx),
648 2002 => self.evaluate_2002(ctx),
649 2003 => self.evaluate_2003(ctx),
650 2004 => self.evaluate_2004(ctx),
651 2005 => self.evaluate_2005(ctx),
652 2006 => self.evaluate_2006(ctx),
653 2007 => self.evaluate_2007(ctx),
654 2008 => self.evaluate_2008(ctx),
655 2009 => self.evaluate_2009(ctx),
656 2010 => self.evaluate_2010(ctx),
657 2011 => self.evaluate_2011(ctx),
658 2012 => self.evaluate_2012(ctx),
659 2013 => self.evaluate_2013(ctx),
660 2014 => self.evaluate_2014(ctx),
661 2015 => self.evaluate_2015(ctx),
662 2016 => self.evaluate_2016(ctx),
663 2017 => self.evaluate_2017(ctx),
664 2018 => self.evaluate_2018(ctx),
665 2060 => self.evaluate_2060(ctx),
666 2061 => self.evaluate_2061(ctx),
667 2071 => self.evaluate_2071(ctx),
668 2073 => self.evaluate_2073(ctx),
669 2075 => self.evaluate_2075(ctx),
670 2080 => self.evaluate_2080(ctx),
671 2095 => self.evaluate_2095(ctx),
672 2096 => self.evaluate_2096(ctx),
673 2119 => self.evaluate_2119(ctx),
674 2121 => self.evaluate_2121(ctx),
675 2140 => self.evaluate_2140(ctx),
676 2182 => self.evaluate_2182(ctx),
677 2183 => self.evaluate_2183(ctx),
678 2207 => self.evaluate_2207(ctx),
679 2225 => self.evaluate_2225(ctx),
680 2236 => self.evaluate_2236(ctx),
681 2252 => self.evaluate_2252(ctx),
682 2261 => self.evaluate_2261(ctx),
683 2284 => self.evaluate_2284(ctx),
684 2286 => self.evaluate_2286(ctx),
685 2287 => self.evaluate_2287(ctx),
686 2288 => self.evaluate_2288(ctx),
687 2307 => self.evaluate_2307(ctx),
688 2308 => self.evaluate_2308(ctx),
689 2309 => self.evaluate_2309(ctx),
690 2310 => self.evaluate_2310(ctx),
691 2311 => self.evaluate_2311(ctx),
692 2312 => self.evaluate_2312(ctx),
693 2313 => self.evaluate_2313(ctx),
694 2317 => self.evaluate_2317(ctx),
695 2318 => self.evaluate_2318(ctx),
696 2344 => self.evaluate_2344(ctx),
697 2350 => self.evaluate_2350(ctx),
698 2351 => self.evaluate_2351(ctx),
699 2352 => self.evaluate_2352(ctx),
700 2356 => self.evaluate_2356(ctx),
701 2357 => self.evaluate_2357(ctx),
702 2358 => self.evaluate_2358(ctx),
703 2359 => self.evaluate_2359(ctx),
704 2360 => self.evaluate_2360(ctx),
705 2361 => self.evaluate_2361(ctx),
706 _ => ConditionResult::Unknown,
707 }
708 }
709
710 fn is_external(&self, condition: u32) -> bool {
711 self.external_conditions.contains(&condition)
712 }
713 fn is_known(&self, condition: u32) -> bool {
714 matches!(
715 condition,
716 1 | 2
717 | 3
718 | 4
719 | 5
720 | 6
721 | 7
722 | 8
723 | 9
724 | 10
725 | 11
726 | 12
727 | 13
728 | 14
729 | 15
730 | 16
731 | 17
732 | 18
733 | 19
734 | 20
735 | 21
736 | 22
737 | 23
738 | 24
739 | 25
740 | 27
741 | 28
742 | 29
743 | 30
744 | 31
745 | 32
746 | 33
747 | 34
748 | 35
749 | 36
750 | 37
751 | 38
752 | 39
753 | 40
754 | 41
755 | 42
756 | 43
757 | 44
758 | 45
759 | 46
760 | 47
761 | 48
762 | 49
763 | 50
764 | 51
765 | 52
766 | 53
767 | 54
768 | 55
769 | 56
770 | 57
771 | 58
772 | 60
773 | 61
774 | 62
775 | 63
776 | 64
777 | 65
778 | 66
779 | 67
780 | 68
781 | 69
782 | 70
783 | 71
784 | 72
785 | 73
786 | 74
787 | 75
788 | 76
789 | 77
790 | 78
791 | 79
792 | 83
793 | 84
794 | 85
795 | 86
796 | 87
797 | 88
798 | 89
799 | 90
800 | 91
801 | 92
802 | 93
803 | 94
804 | 95
805 | 96
806 | 97
807 | 98
808 | 99
809 | 100
810 | 101
811 | 102
812 | 103
813 | 104
814 | 105
815 | 106
816 | 107
817 | 108
818 | 110
819 | 111
820 | 112
821 | 113
822 | 114
823 | 115
824 | 116
825 | 117
826 | 118
827 | 119
828 | 120
829 | 121
830 | 122
831 | 123
832 | 124
833 | 125
834 | 126
835 | 127
836 | 128
837 | 129
838 | 130
839 | 131
840 | 132
841 | 133
842 | 134
843 | 135
844 | 136
845 | 137
846 | 138
847 | 139
848 | 140
849 | 141
850 | 142
851 | 143
852 | 144
853 | 145
854 | 146
855 | 147
856 | 148
857 | 149
858 | 150
859 | 151
860 | 152
861 | 153
862 | 156
863 | 157
864 | 161
865 | 162
866 | 163
867 | 164
868 | 165
869 | 166
870 | 167
871 | 168
872 | 169
873 | 170
874 | 172
875 | 173
876 | 174
877 | 175
878 | 176
879 | 177
880 | 178
881 | 179
882 | 180
883 | 184
884 | 190
885 | 191
886 | 192
887 | 193
888 | 194
889 | 195
890 | 196
891 | 197
892 | 198
893 | 199
894 | 201
895 | 202
896 | 203
897 | 204
898 | 205
899 | 206
900 | 209
901 | 210
902 | 212
903 | 213
904 | 215
905 | 216
906 | 217
907 | 219
908 | 220
909 | 221
910 | 223
911 | 224
912 | 227
913 | 229
914 | 232
915 | 233
916 | 234
917 | 237
918 | 238
919 | 239
920 | 240
921 | 241
922 | 242
923 | 243
924 | 244
925 | 248
926 | 249
927 | 251
928 | 252
929 | 253
930 | 254
931 | 255
932 | 256
933 | 257
934 | 258
935 | 259
936 | 261
937 | 262
938 | 265
939 | 266
940 | 267
941 | 268
942 | 269
943 | 270
944 | 273
945 | 279
946 | 280
947 | 282
948 | 284
949 | 285
950 | 286
951 | 287
952 | 288
953 | 291
954 | 292
955 | 293
956 | 294
957 | 295
958 | 296
959 | 297
960 | 298
961 | 300
962 | 301
963 | 302
964 | 303
965 | 304
966 | 305
967 | 306
968 | 307
969 | 309
970 | 312
971 | 313
972 | 314
973 | 315
974 | 316
975 | 317
976 | 318
977 | 321
978 | 322
979 | 323
980 | 326
981 | 327
982 | 328
983 | 329
984 | 332
985 | 333
986 | 334
987 | 335
988 | 336
989 | 337
990 | 338
991 | 339
992 | 340
993 | 341
994 | 342
995 | 344
996 | 345
997 | 346
998 | 347
999 | 348
1000 | 349
1001 | 350
1002 | 351
1003 | 352
1004 | 355
1005 | 356
1006 | 357
1007 | 358
1008 | 359
1009 | 360
1010 | 363
1011 | 365
1012 | 366
1013 | 367
1014 | 368
1015 | 370
1016 | 371
1017 | 372
1018 | 373
1019 | 375
1020 | 376
1021 | 377
1022 | 378
1023 | 379
1024 | 380
1025 | 384
1026 | 386
1027 | 387
1028 | 388
1029 | 391
1030 | 392
1031 | 393
1032 | 394
1033 | 395
1034 | 396
1035 | 397
1036 | 398
1037 | 399
1038 | 401
1039 | 402
1040 | 403
1041 | 404
1042 | 405
1043 | 406
1044 | 407
1045 | 408
1046 | 409
1047 | 410
1048 | 411
1049 | 412
1050 | 413
1051 | 414
1052 | 415
1053 | 416
1054 | 417
1055 | 419
1056 | 420
1057 | 421
1058 | 425
1059 | 426
1060 | 427
1061 | 428
1062 | 429
1063 | 430
1064 | 431
1065 | 432
1066 | 433
1067 | 435
1068 | 436
1069 | 437
1070 | 438
1071 | 440
1072 | 441
1073 | 442
1074 | 444
1075 | 445
1076 | 446
1077 | 447
1078 | 448
1079 | 449
1080 | 450
1081 | 451
1082 | 452
1083 | 453
1084 | 454
1085 | 455
1086 | 456
1087 | 457
1088 | 458
1089 | 459
1090 | 460
1091 | 461
1092 | 462
1093 | 463
1094 | 465
1095 | 466
1096 | 467
1097 | 468
1098 | 469
1099 | 470
1100 | 471
1101 | 472
1102 | 473
1103 | 474
1104 | 475
1105 | 476
1106 | 477
1107 | 478
1108 | 479
1109 | 480
1110 | 481
1111 | 483
1112 | 484
1113 | 487
1114 | 489
1115 | 490
1116 | 491
1117 | 494
1118 | 500
1119 | 501
1120 | 502
1121 | 503
1122 | 504
1123 | 505
1124 | 506
1125 | 507
1126 | 508
1127 | 509
1128 | 510
1129 | 511
1130 | 512
1131 | 513
1132 | 514
1133 | 515
1134 | 516
1135 | 517
1136 | 518
1137 | 519
1138 | 520
1139 | 521
1140 | 522
1141 | 523
1142 | 524
1143 | 525
1144 | 526
1145 | 527
1146 | 528
1147 | 529
1148 | 530
1149 | 531
1150 | 532
1151 | 533
1152 | 534
1153 | 555
1154 | 556
1155 | 557
1156 | 558
1157 | 559
1158 | 560
1159 | 561
1160 | 562
1161 | 563
1162 | 564
1163 | 565
1164 | 566
1165 | 567
1166 | 568
1167 | 569
1168 | 570
1169 | 572
1170 | 576
1171 | 577
1172 | 578
1173 | 579
1174 | 580
1175 | 581
1176 | 586
1177 | 590
1178 | 594
1179 | 599
1180 | 601
1181 | 606
1182 | 609
1183 | 611
1184 | 614
1185 | 617
1186 | 618
1187 | 619
1188 | 621
1189 | 622
1190 | 623
1191 | 630
1192 | 631
1193 | 632
1194 | 637
1195 | 638
1196 | 639
1197 | 640
1198 | 641
1199 | 642
1200 | 643
1201 | 645
1202 | 646
1203 | 647
1204 | 648
1205 | 651
1206 | 653
1207 | 655
1208 | 659
1209 | 660
1210 | 662
1211 | 663
1212 | 664
1213 | 665
1214 | 667
1215 | 668
1216 | 670
1217 | 671
1218 | 672
1219 | 673
1220 | 674
1221 | 675
1222 | 677
1223 | 678
1224 | 679
1225 | 680
1226 | 681
1227 | 682
1228 | 683
1229 | 684
1230 | 685
1231 | 686
1232 | 687
1233 | 688
1234 | 689
1235 | 690
1236 | 693
1237 | 694
1238 | 695
1239 | 696
1240 | 698
1241 | 699
1242 | 700
1243 | 704
1244 | 705
1245 | 706
1246 | 707
1247 | 708
1248 | 709
1249 | 710
1250 | 711
1251 | 712
1252 | 713
1253 | 714
1254 | 715
1255 | 716
1256 | 717
1257 | 718
1258 | 719
1259 | 902
1260 | 910
1261 | 914
1262 | 922
1263 | 926
1264 | 930
1265 | 931
1266 | 932
1267 | 933
1268 | 937
1269 | 938
1270 | 939
1271 | 940
1272 | 942
1273 | 943
1274 | 946
1275 | 948
1276 | 950
1277 | 951
1278 | 952
1279 | 955
1280 | 957
1281 | 960
1282 | 961
1283 | 967
1284 | 2000
1285 | 2001
1286 | 2002
1287 | 2003
1288 | 2004
1289 | 2005
1290 | 2006
1291 | 2007
1292 | 2008
1293 | 2009
1294 | 2010
1295 | 2011
1296 | 2012
1297 | 2013
1298 | 2014
1299 | 2015
1300 | 2016
1301 | 2017
1302 | 2018
1303 | 2060
1304 | 2061
1305 | 2071
1306 | 2073
1307 | 2075
1308 | 2080
1309 | 2095
1310 | 2096
1311 | 2119
1312 | 2121
1313 | 2140
1314 | 2182
1315 | 2183
1316 | 2207
1317 | 2225
1318 | 2236
1319 | 2252
1320 | 2261
1321 | 2284
1322 | 2286
1323 | 2287
1324 | 2288
1325 | 2307
1326 | 2308
1327 | 2309
1328 | 2310
1329 | 2311
1330 | 2312
1331 | 2313
1332 | 2317
1333 | 2318
1334 | 2344
1335 | 2350
1336 | 2351
1337 | 2352
1338 | 2356
1339 | 2357
1340 | 2358
1341 | 2359
1342 | 2360
1343 | 2361
1344 )
1345 }
1346}
1347
1348impl UtilmdStromConditionEvaluatorFV2510 {
1349 /// [2] Wenn UNH DE0070 (Übermittlungsfolgenummer) mit 1 vorhanden
1350 fn evaluate_2(&self, ctx: &EvaluationContext) -> ConditionResult {
1351 ctx.has_segment_matching("UNH", &[(3, 0, "1")])
1352 }
1353
1354 /// [3] Bei Aufteilung, in der Nachricht mit der höchsten Übermittlungsfolgenummer
1355 /// EXTERNAL: Requires context from outside the message.
1356 fn evaluate_3(&self, ctx: &EvaluationContext) -> ConditionResult {
1357 ctx.external.evaluate("is_highest_sequence_in_split")
1358 }
1359
1360 /// [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
1361 fn evaluate_20(&self, ctx: &EvaluationContext) -> ConditionResult {
1362 let nav = match ctx.navigator() {
1363 Some(n) => n,
1364 None => return ctx.has_qualified_value("CCI", 0, "Z30", 2, 0, &["Z07"]),
1365 };
1366 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
1367 for i in 0..sg8_count {
1368 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
1369 let has_z01 = seq_segs.iter().any(|s| {
1370 s.elements
1371 .first()
1372 .and_then(|e| e.first())
1373 .is_some_and(|v| v == "Z01")
1374 });
1375 if !has_z01 {
1376 continue;
1377 }
1378 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
1379 for j in 0..sg10_count {
1380 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
1381 if ccis.iter().any(|s| {
1382 s.elements
1383 .first()
1384 .and_then(|e| e.first())
1385 .is_some_and(|v| v == "Z30")
1386 && s.elements
1387 .get(2)
1388 .and_then(|e| e.first())
1389 .is_some_and(|v| v == "Z07")
1390 }) {
1391 return ConditionResult::True;
1392 }
1393 }
1394 }
1395 ConditionResult::False
1396 }
1397
1398 /// [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
1399 // 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)
1400 fn evaluate_28(&self, ctx: &EvaluationContext) -> ConditionResult {
1401 let nav = match ctx.navigator() {
1402 Some(n) => n,
1403 None => {
1404 let sts_segs = ctx.find_segments_with_qualifier("STS", 0, "E01");
1405 let found = sts_segs.iter().any(|s| {
1406 let code = s
1407 .elements
1408 .get(2)
1409 .and_then(|e| e.first())
1410 .map(|v| v.as_str());
1411 let list = s.elements.get(2).and_then(|e| e.get(1)).map(|v| v.as_str());
1412 (code == Some("A04") && list == Some("E_0017"))
1413 || (code == Some("A03") && list == Some("E_0052"))
1414 });
1415 return ConditionResult::from(!found);
1416 }
1417 };
1418 let sg4_count = nav.group_instance_count(&["SG4"]);
1419 for i in 0..sg4_count {
1420 let ide_segs = nav.find_segments_in_group("IDE", &["SG4"], i);
1421 let has_ide_24 = ide_segs.iter().any(|s| {
1422 s.elements
1423 .first()
1424 .and_then(|e| e.first())
1425 .is_some_and(|v| v == "24")
1426 });
1427 if !has_ide_24 {
1428 continue;
1429 }
1430 let sts_segs = nav.find_segments_in_group("STS", &["SG4"], i);
1431 let found = sts_segs.iter().any(|s| {
1432 let qual = s
1433 .elements
1434 .first()
1435 .and_then(|e| e.first())
1436 .map(|v| v.as_str());
1437 let code = s
1438 .elements
1439 .get(2)
1440 .and_then(|e| e.first())
1441 .map(|v| v.as_str());
1442 let list = s.elements.get(2).and_then(|e| e.get(1)).map(|v| v.as_str());
1443 qual == Some("E01")
1444 && ((code == Some("A04") && list == Some("E_0017"))
1445 || (code == Some("A03") && list == Some("E_0052")))
1446 });
1447 if !found {
1448 return ConditionResult::True;
1449 }
1450 }
1451 ConditionResult::False
1452 }
1453
1454 /// [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
1455 // 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)
1456 fn evaluate_29(&self, ctx: &EvaluationContext) -> ConditionResult {
1457 let nav = match ctx.navigator() {
1458 Some(n) => n,
1459 None => {
1460 let sts_segs = ctx.find_segments_with_qualifier("STS", 0, "E01");
1461 let found = sts_segs.iter().any(|s| {
1462 let code = s
1463 .elements
1464 .get(2)
1465 .and_then(|e| e.first())
1466 .map(|v| v.as_str());
1467 let list = s.elements.get(2).and_then(|e| e.get(1)).map(|v| v.as_str());
1468 (code == Some("A06") && list == Some("E_0017"))
1469 || (code == Some("A05") && list == Some("E_0052"))
1470 });
1471 return ConditionResult::from(!found);
1472 }
1473 };
1474 let sg4_count = nav.group_instance_count(&["SG4"]);
1475 for i in 0..sg4_count {
1476 let ide_segs = nav.find_segments_in_group("IDE", &["SG4"], i);
1477 let has_ide_24 = ide_segs.iter().any(|s| {
1478 s.elements
1479 .first()
1480 .and_then(|e| e.first())
1481 .is_some_and(|v| v == "24")
1482 });
1483 if !has_ide_24 {
1484 continue;
1485 }
1486 let sts_segs = nav.find_segments_in_group("STS", &["SG4"], i);
1487 let found = sts_segs.iter().any(|s| {
1488 let qual = s
1489 .elements
1490 .first()
1491 .and_then(|e| e.first())
1492 .map(|v| v.as_str());
1493 let code = s
1494 .elements
1495 .get(2)
1496 .and_then(|e| e.first())
1497 .map(|v| v.as_str());
1498 let list = s.elements.get(2).and_then(|e| e.get(1)).map(|v| v.as_str());
1499 qual == Some("E01")
1500 && ((code == Some("A06") && list == Some("E_0017"))
1501 || (code == Some("A05") && list == Some("E_0052")))
1502 });
1503 if !found {
1504 return ConditionResult::True;
1505 }
1506 }
1507 ConditionResult::False
1508 }
1509
1510 /// [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...
1511 fn evaluate_44(&self, _ctx: &EvaluationContext) -> ConditionResult {
1512 // Hinweis: Die Zeitraum-ID ist vom DE1156 aus einem passenden SG6 RFF+Z49/Z53
1513 // (Verwendungszeitraum der Daten) aus der Anfragenachricht, identifiziert über
1514 // SG6 RFF+TN DE1154 (Referenz Vorgangsnummer), einzutragen. Informelle Befüllungsregel.
1515 ConditionResult::True
1516 }
1517
1518 /// [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...
1519 // 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)
1520 fn evaluate_51(&self, ctx: &EvaluationContext) -> ConditionResult {
1521 let nav = match ctx.navigator() {
1522 Some(n) => n,
1523 None => return ConditionResult::Unknown,
1524 };
1525 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
1526
1527 // Step 1: Collect Zeitraum-IDs from Z78 SG8 groups that have RFF+Z31 with the target code
1528 let target_code = "9992000000018";
1529 let mut z78_zeitraum_ids: std::collections::HashSet<String> =
1530 std::collections::HashSet::new();
1531 for i in 0..sg8_count {
1532 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
1533 let is_z78 = seq_segs.iter().any(|s| {
1534 s.elements
1535 .first()
1536 .and_then(|e| e.first())
1537 .is_some_and(|v| v == "Z78")
1538 });
1539 if !is_z78 {
1540 continue;
1541 }
1542 let rff_segs = nav.find_segments_in_group("RFF", &["SG4", "SG8"], i);
1543 let has_z31_target = rff_segs.iter().any(|s| {
1544 s.elements
1545 .first()
1546 .and_then(|e| e.first())
1547 .is_some_and(|v| v == "Z31")
1548 && s.elements
1549 .first()
1550 .and_then(|e| e.get(1))
1551 .is_some_and(|v| v.replace(' ', "") == target_code)
1552 });
1553 if has_z31_target {
1554 for seq in &seq_segs {
1555 if seq
1556 .elements
1557 .first()
1558 .and_then(|e| e.first())
1559 .is_some_and(|v| v == "Z78")
1560 {
1561 if let Some(zeit_id) = seq.elements.get(1).and_then(|e| e.first()) {
1562 if !zeit_id.is_empty() {
1563 z78_zeitraum_ids.insert(zeit_id.clone());
1564 }
1565 }
1566 }
1567 }
1568 }
1569 }
1570
1571 if z78_zeitraum_ids.is_empty() {
1572 // No Z78 with the target code exists — the Z98 group cannot reference it, condition True
1573 return ConditionResult::True;
1574 }
1575
1576 // Step 2: Check if any Z98 SG8 shares a Zeitraum-ID with a target Z78 SG8
1577 for i in 0..sg8_count {
1578 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
1579 for seq in &seq_segs {
1580 if seq
1581 .elements
1582 .first()
1583 .and_then(|e| e.first())
1584 .is_some_and(|v| v == "Z98")
1585 {
1586 if let Some(zeit_id) = seq.elements.get(1).and_then(|e| e.first()) {
1587 if z78_zeitraum_ids.contains(zeit_id) {
1588 // Z98 SG8 references a Z78 with the Pauschal code — condition False
1589 return ConditionResult::False;
1590 }
1591 }
1592 }
1593 }
1594 }
1595 ConditionResult::True
1596 }
1597
1598 /// [79] Wenn SG4 STS+7+++Z33 (Auszug wegen Stilllegung) vorhanden
1599 fn evaluate_79(&self, ctx: &EvaluationContext) -> ConditionResult {
1600 // STS+7+++Z33: elements[0][0]="7" (Statuskategorie), elements[3][0]="Z33" (Transaktionsgrundergänzung: Auszug wegen Stilllegung)
1601 ctx.has_segment_matching("STS", &[(0, 0, "7"), (3, 0, "Z33")])
1602 }
1603
1604 /// [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 ...
1605 // 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)
1606 fn evaluate_134(&self, ctx: &EvaluationContext) -> ConditionResult {
1607 let nav = match ctx.navigator() {
1608 Some(n) => n,
1609 None => return ConditionResult::Unknown,
1610 };
1611 let sg6_count = nav.group_instance_count(&["SG4", "SG6"]);
1612
1613 // Collect (zeitraum_id_numeric, dtm_z25_value, dtm_z26_value) for SG6 groups with RFF+Z48 or RFF+Z55
1614 let mut slices: Vec<(i64, String, String)> = Vec::new();
1615 for i in 0..sg6_count {
1616 let rff_segs = nav.find_segments_in_group("RFF", &["SG4", "SG6"], i);
1617 // DE1156 is elements[0][2] for RFF Verwendungszeitraum
1618 let zeitraum_id = rff_segs.iter().find_map(|s| {
1619 let qual = s.elements.first().and_then(|e| e.first())?;
1620 if qual == "Z48" || qual == "Z55" {
1621 let id = s.elements.first().and_then(|e| e.get(2))?;
1622 if !id.is_empty() {
1623 Some(id.clone())
1624 } else {
1625 None
1626 }
1627 } else {
1628 None
1629 }
1630 });
1631 let Some(zid_str) = zeitraum_id else { continue };
1632 let Ok(zid_num) = zid_str.parse::<i64>() else {
1633 continue;
1634 };
1635 let dtm_segs = nav.find_segments_in_group("DTM", &["SG4", "SG6"], i);
1636 let z25 = dtm_segs
1637 .iter()
1638 .find_map(|s| {
1639 if s.elements
1640 .first()
1641 .and_then(|e| e.first())
1642 .is_some_and(|v| v == "Z25")
1643 {
1644 s.elements.first().and_then(|e| e.get(1)).cloned()
1645 } else {
1646 None
1647 }
1648 })
1649 .unwrap_or_default();
1650 let z26 = dtm_segs
1651 .iter()
1652 .find_map(|s| {
1653 if s.elements
1654 .first()
1655 .and_then(|e| e.first())
1656 .is_some_and(|v| v == "Z26")
1657 {
1658 s.elements.first().and_then(|e| e.get(1)).cloned()
1659 } else {
1660 None
1661 }
1662 })
1663 .unwrap_or_default();
1664 slices.push((zid_num, z25, z26));
1665 }
1666 if slices.len() < 2 {
1667 return ConditionResult::Unknown;
1668 }
1669 slices.sort_by_key(|s| s.0);
1670 // For each slice with Zeitraum-ID != 1, DTM+Z25 must equal DTM+Z26 of the immediately preceding slice
1671 for idx in 1..slices.len() {
1672 let (id, z25, _) = &slices[idx];
1673 let (_, _, prev_z26) = &slices[idx - 1];
1674 if *id != 1 && !z25.is_empty() && !prev_z26.is_empty() && z25 != prev_z26 {
1675 return ConditionResult::False;
1676 }
1677 }
1678 ConditionResult::True
1679 }
1680
1681 /// [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...
1682 // 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)
1683 fn evaluate_135(&self, ctx: &EvaluationContext) -> ConditionResult {
1684 let nav = match ctx.navigator() {
1685 Some(n) => n,
1686 None => return ConditionResult::Unknown,
1687 };
1688 let sg6_count = nav.group_instance_count(&["SG4", "SG6"]);
1689
1690 // Collect (zeitraum_id_numeric, dtm_z25_value, dtm_z26_value) for SG6 groups with RFF+Z47 or RFF+Z54
1691 let mut slices: Vec<(i64, String, String)> = Vec::new();
1692 for i in 0..sg6_count {
1693 let rff_segs = nav.find_segments_in_group("RFF", &["SG4", "SG6"], i);
1694 // DE1156 is elements[0][2] for RFF Verwendungszeitraum
1695 let zeitraum_id = rff_segs.iter().find_map(|s| {
1696 let qual = s.elements.first().and_then(|e| e.first())?;
1697 if qual == "Z47" || qual == "Z54" {
1698 let id = s.elements.first().and_then(|e| e.get(2))?;
1699 if !id.is_empty() {
1700 Some(id.clone())
1701 } else {
1702 None
1703 }
1704 } else {
1705 None
1706 }
1707 });
1708 let Some(zid_str) = zeitraum_id else { continue };
1709 let Ok(zid_num) = zid_str.parse::<i64>() else {
1710 continue;
1711 };
1712 let dtm_segs = nav.find_segments_in_group("DTM", &["SG4", "SG6"], i);
1713 let z25 = dtm_segs
1714 .iter()
1715 .find_map(|s| {
1716 if s.elements
1717 .first()
1718 .and_then(|e| e.first())
1719 .is_some_and(|v| v == "Z25")
1720 {
1721 s.elements.first().and_then(|e| e.get(1)).cloned()
1722 } else {
1723 None
1724 }
1725 })
1726 .unwrap_or_default();
1727 let z26 = dtm_segs
1728 .iter()
1729 .find_map(|s| {
1730 if s.elements
1731 .first()
1732 .and_then(|e| e.first())
1733 .is_some_and(|v| v == "Z26")
1734 {
1735 s.elements.first().and_then(|e| e.get(1)).cloned()
1736 } else {
1737 None
1738 }
1739 })
1740 .unwrap_or_default();
1741 slices.push((zid_num, z25, z26));
1742 }
1743 if slices.len() < 2 {
1744 return ConditionResult::Unknown;
1745 }
1746 slices.sort_by_key(|s| s.0);
1747 // For each slice with Zeitraum-ID != 1, DTM+Z25 must equal DTM+Z26 of the immediately preceding slice
1748 for idx in 1..slices.len() {
1749 let (id, z25, _) = &slices[idx];
1750 let (_, _, prev_z26) = &slices[idx - 1];
1751 if *id != 1 && !z25.is_empty() && !prev_z26.is_empty() && z25 != prev_z26 {
1752 return ConditionResult::False;
1753 }
1754 }
1755 ConditionResult::True
1756 }
1757
1758 /// [136] Wenn SG10 CCI+++E13 (Zählertyp) CAV+EHZ (elektronischer Haushaltszähler) in dieser SG8 vorhanden
1759 fn evaluate_136(&self, ctx: &EvaluationContext) -> ConditionResult {
1760 let nav = match ctx.navigator() {
1761 Some(n) => n,
1762 None => return ctx.has_qualified_value("CAV", 0, "EHZ", 0, 0, &["EHZ"]),
1763 };
1764 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
1765 for i in 0..sg8_count {
1766 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
1767 for j in 0..sg10_count {
1768 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
1769 let has_cci_e13 = ccis.iter().any(|s| {
1770 s.elements
1771 .get(2)
1772 .and_then(|e| e.first())
1773 .is_some_and(|v| v == "E13")
1774 });
1775 if has_cci_e13 {
1776 let cavs =
1777 nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
1778 if cavs.iter().any(|s| {
1779 s.elements
1780 .first()
1781 .and_then(|e| e.first())
1782 .is_some_and(|v| v == "EHZ")
1783 }) {
1784 return ConditionResult::True;
1785 }
1786 }
1787 }
1788 }
1789 ConditionResult::False
1790 }
1791
1792 /// [139] Wenn SG10 CAV+IVA (Individuelle Abstimmung) in dieser SG8 nicht vorhanden
1793 // 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)
1794 fn evaluate_139(&self, ctx: &EvaluationContext) -> ConditionResult {
1795 let nav = match ctx.navigator() {
1796 Some(n) => n,
1797 None => return ctx.lacks_qualifier("CAV", 0, "IVA"),
1798 };
1799 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
1800 for i in 0..sg8_count {
1801 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
1802 for j in 0..sg10_count {
1803 let cavs = nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
1804 if cavs.iter().any(|s| {
1805 s.elements
1806 .first()
1807 .and_then(|e| e.first())
1808 .is_some_and(|v| v == "IVA")
1809 }) {
1810 return ConditionResult::False;
1811 }
1812 }
1813 }
1814 ConditionResult::True
1815 }
1816
1817 /// [157] Wenn SG4 STS+7++Z33+ZZB nicht vorhanden
1818 fn evaluate_157(&self, ctx: &EvaluationContext) -> ConditionResult {
1819 let result = ctx.has_segment_matching("STS", &[(0, 0, "7"), (2, 0, "Z33"), (3, 0, "ZZB")]);
1820 match result {
1821 ConditionResult::True => ConditionResult::False,
1822 ConditionResult::False => ConditionResult::True,
1823 ConditionResult::Unknown => ConditionResult::Unknown,
1824 }
1825 }
1826
1827 /// [168] Wenn in dieser SG8 im SG8 PIA+Z02 (Gruppenartikel- ID / Artikel-ID), die Artikel-ID 1-02-0-002/ 003/ 004 vorhanden
1828 fn evaluate_168(&self, ctx: &EvaluationContext) -> ConditionResult {
1829 ctx.any_group_has_qualified_value(
1830 "PIA",
1831 0,
1832 "Z02",
1833 1,
1834 0,
1835 &["1-02-0-002", "1-02-0-003", "1-02-0-004"],
1836 &["SG4", "SG8"],
1837 )
1838 }
1839
1840 /// [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 ...
1841 // 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)
1842 fn evaluate_169(&self, ctx: &EvaluationContext) -> ConditionResult {
1843 let nav = match ctx.navigator() {
1844 Some(n) => n,
1845 None => return ConditionResult::Unknown,
1846 };
1847 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
1848 let mut sg8_data: Vec<(String, String)> = Vec::new();
1849 for i in 0..sg8_count {
1850 let seqs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
1851 let zeitraum_id = seqs
1852 .iter()
1853 .find(|s| {
1854 s.elements
1855 .first()
1856 .and_then(|e| e.first())
1857 .is_some_and(|v| v == "Z45")
1858 })
1859 .and_then(|s| s.elements.get(1))
1860 .and_then(|e| e.first())
1861 .filter(|v| !v.is_empty())
1862 .cloned();
1863 if let Some(zid) = zeitraum_id {
1864 let pias = nav.find_segments_in_group("PIA", &["SG4", "SG8"], i);
1865 let article_id = pias
1866 .iter()
1867 .find(|s| {
1868 s.elements
1869 .first()
1870 .and_then(|e| e.first())
1871 .is_some_and(|v| v == "Z02")
1872 })
1873 .and_then(|s| s.elements.get(1))
1874 .and_then(|e| e.first())
1875 .cloned()
1876 .unwrap_or_default();
1877 sg8_data.push((zid, article_id));
1878 }
1879 }
1880 for i in 0..sg8_data.len() {
1881 for j in (i + 1)..sg8_data.len() {
1882 if sg8_data[i].0 == sg8_data[j].0 {
1883 let (id_i, id_j) = (&sg8_data[i].1, &sg8_data[j].1);
1884 let i_is_002 = id_i == "1-02-0-002";
1885 let j_is_002 = id_j == "1-02-0-002";
1886 let i_is_003_004 = id_i == "1-02-0-003" || id_i == "1-02-0-004";
1887 let j_is_003_004 = id_j == "1-02-0-003" || id_j == "1-02-0-004";
1888 if (i_is_002 && j_is_003_004) || (j_is_002 && i_is_003_004) {
1889 return ConditionResult::True;
1890 }
1891 }
1892 }
1893 }
1894 if sg8_data.is_empty() {
1895 ConditionResult::Unknown
1896 } else {
1897 ConditionResult::False
1898 }
1899 }
1900
1901 /// [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
1902 fn evaluate_206(&self, ctx: &EvaluationContext) -> ConditionResult {
1903 match ctx.has_segment_matching("STS", &[(0, 0, "7"), (2, 0, "ZG5")]) {
1904 ConditionResult::True => ConditionResult::False,
1905 ConditionResult::False => ConditionResult::True,
1906 ConditionResult::Unknown => ConditionResult::Unknown,
1907 }
1908 }
1909
1910 /// [242] Wenn mehr als ein SG8 (Referenz auf die Lokationsbündelstruktur) mit der selben Zeitraum-ID im DE1050 vorhanden
1911 fn evaluate_242(&self, ctx: &EvaluationContext) -> ConditionResult {
1912 let nav = match ctx.navigator() {
1913 Some(n) => n,
1914 None => return ConditionResult::Unknown,
1915 };
1916 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
1917 let mut ids: Vec<String> = Vec::new();
1918 for i in 0..sg8_count {
1919 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
1920 for seq in &seq_segs {
1921 let qual = seq
1922 .elements
1923 .first()
1924 .and_then(|e| e.first())
1925 .map(|s| s.as_str());
1926 if matches!(qual, Some("Z78") | Some("ZC7") | Some("ZC8") | Some("ZD5")) {
1927 if let Some(id) = seq.elements.get(1).and_then(|e| e.first()) {
1928 if !id.is_empty() {
1929 ids.push(id.clone());
1930 }
1931 }
1932 }
1933 }
1934 }
1935 if ids.is_empty() {
1936 return ConditionResult::Unknown;
1937 }
1938 let mut seen = std::collections::HashSet::new();
1939 ConditionResult::from(ids.iter().any(|id| !seen.insert(id.as_str())))
1940 }
1941
1942 /// [253] Wenn SG4 STS+E01++ZC9 (Ablehnung (keine Zuordnung möglich)) nicht vorhanden
1943 fn evaluate_253(&self, ctx: &EvaluationContext) -> ConditionResult {
1944 match ctx.has_segment_matching("STS", &[(0, 0, "E01"), (2, 0, "ZC9")]) {
1945 ConditionResult::True => ConditionResult::False,
1946 ConditionResult::False => ConditionResult::True,
1947 ConditionResult::Unknown => ConditionResult::Unknown,
1948 }
1949 }
1950
1951 /// [258] Wenn in dieser SG8 SEQ+Z01 (Daten der Marktlokation) SG10 CCI+Z30++Z07 (Verbrauch) vorhanden
1952 fn evaluate_258(&self, ctx: &EvaluationContext) -> ConditionResult {
1953 let nav = match ctx.navigator() {
1954 Some(n) => n,
1955 None => return ctx.has_qualified_value("CCI", 0, "Z30", 2, 0, &["Z07"]),
1956 };
1957 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
1958 for i in 0..sg8_count {
1959 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
1960 let has_z01 = seq_segs.iter().any(|s| {
1961 s.elements
1962 .first()
1963 .and_then(|e| e.first())
1964 .is_some_and(|v| v == "Z01")
1965 });
1966 if has_z01 {
1967 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
1968 for j in 0..sg10_count {
1969 let ccis =
1970 nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
1971 if ccis.iter().any(|s| {
1972 s.elements
1973 .first()
1974 .and_then(|e| e.first())
1975 .is_some_and(|v| v == "Z30")
1976 && s.elements
1977 .get(2)
1978 .and_then(|e| e.first())
1979 .is_some_and(|v| v == "Z07")
1980 }) {
1981 return ConditionResult::True;
1982 }
1983 }
1984 }
1985 }
1986 ConditionResult::False
1987 }
1988
1989 /// [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...
1990 // 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)
1991 fn evaluate_297(&self, ctx: &EvaluationContext) -> ConditionResult {
1992 let nav = match ctx.navigator() {
1993 Some(n) => n,
1994 None => return ConditionResult::Unknown,
1995 };
1996 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
1997 // Collect (seq_qualifier, zeitraum_id) tuples from SG8 instances with SEQ+Z02/ZE3 that also have PIA+5
1998 let mut keys: Vec<(String, String)> = Vec::new();
1999 for i in 0..sg8_count {
2000 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
2001 for seq in &seq_segs {
2002 let qual = seq
2003 .elements
2004 .first()
2005 .and_then(|e| e.first())
2006 .map(|s| s.as_str());
2007 if matches!(qual, Some("Z02") | Some("ZE3")) {
2008 let pia_segs = nav.find_segments_in_group("PIA", &["SG4", "SG8"], i);
2009 let has_pia5 = pia_segs.iter().any(|s| {
2010 s.elements
2011 .first()
2012 .and_then(|e| e.first())
2013 .is_some_and(|v| v == "5")
2014 });
2015 if has_pia5 {
2016 let zeitraum_id = seq
2017 .elements
2018 .get(1)
2019 .and_then(|e| e.first())
2020 .cloned()
2021 .unwrap_or_default();
2022 if !zeitraum_id.is_empty() {
2023 keys.push((qual.unwrap_or_default().to_string(), zeitraum_id));
2024 }
2025 }
2026 }
2027 }
2028 }
2029 if keys.is_empty() {
2030 return ConditionResult::Unknown;
2031 }
2032 let mut seen = std::collections::HashSet::new();
2033 ConditionResult::from(keys.iter().any(|k| !seen.insert(k)))
2034 }
2035
2036 /// [312] Wenn DTM+137 (Nachrichtendatum) im DE2380 < 202603312200?+00
2037 fn evaluate_312(&self, ctx: &EvaluationContext) -> ConditionResult {
2038 ctx.dtm_lt("137", "202603312200+00")
2039 }
2040
2041 /// [313] Wenn DTM+137 (Nachrichtendatum) im DE2380 ≥ 202603312200?+00
2042 fn evaluate_313(&self, ctx: &EvaluationContext) -> ConditionResult {
2043 ctx.dtm_ge("137", "202603312200+00")
2044 }
2045
2046 /// [326] Wenn die Marktlokation nicht stillgelegt wird
2047 /// EXTERNAL: Requires context from outside the message.
2048 fn evaluate_326(&self, ctx: &EvaluationContext) -> ConditionResult {
2049 ctx.external.evaluate("market_location_not_decommissioned")
2050 }
2051
2052 /// [328] Wenn die Marktlokation stillgelegt wird
2053 /// EXTERNAL: Requires context from outside the message.
2054 fn evaluate_328(&self, ctx: &EvaluationContext) -> ConditionResult {
2055 ctx.external.evaluate("market_location_decommissioned")
2056 }
2057
2058 /// [346] Wenn SG10 CCI+++E13 (Zählertyp) CAV+MME (mME) in dieser SG8 vorhanden
2059 fn evaluate_346(&self, ctx: &EvaluationContext) -> ConditionResult {
2060 let nav = match ctx.navigator() {
2061 Some(n) => n,
2062 None => {
2063 // Fallback: message-wide check for both CCI+E13 and CAV+MME
2064 let has_cci = ctx.has_qualifier("CCI", 2, "E13");
2065 let has_cav = ctx.has_qualifier("CAV", 0, "MME");
2066 return match (has_cci, has_cav) {
2067 (ConditionResult::True, ConditionResult::True) => ConditionResult::True,
2068 (ConditionResult::False, _) | (_, ConditionResult::False) => {
2069 ConditionResult::False
2070 }
2071 _ => ConditionResult::Unknown,
2072 };
2073 }
2074 };
2075 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
2076 for i in 0..sg8_count {
2077 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
2078 for j in 0..sg10_count {
2079 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
2080 let has_cci_e13 = ccis.iter().any(|s| {
2081 s.elements
2082 .get(2)
2083 .and_then(|e| e.first())
2084 .is_some_and(|v| v == "E13")
2085 });
2086 if has_cci_e13 {
2087 let cavs =
2088 nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
2089 if cavs.iter().any(|s| {
2090 s.elements
2091 .first()
2092 .and_then(|e| e.first())
2093 .is_some_and(|v| v == "MME")
2094 }) {
2095 return ConditionResult::True;
2096 }
2097 }
2098 }
2099 }
2100 ConditionResult::False
2101 }
2102
2103 /// [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...
2104 // 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)
2105 fn evaluate_387(&self, ctx: &EvaluationContext) -> ConditionResult {
2106 let nav = match ctx.navigator() {
2107 Some(n) => n,
2108 None => return ConditionResult::Unknown,
2109 };
2110 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
2111 for i in 0..sg8_count {
2112 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
2113 let is_obis_malo = seq_segs.iter().any(|s| {
2114 s.elements
2115 .first()
2116 .and_then(|e| e.first())
2117 .is_some_and(|v| matches!(v.as_str(), "Z02" | "ZA1" | "ZA2" | "ZE3"))
2118 });
2119 if !is_obis_malo {
2120 continue;
2121 }
2122 let pia_segs = nav.find_segments_in_group("PIA", &["SG4", "SG8"], i);
2123 for pia in &pia_segs {
2124 if !pia
2125 .elements
2126 .first()
2127 .and_then(|e| e.first())
2128 .is_some_and(|v| v == "5")
2129 {
2130 continue;
2131 }
2132 let obis = match pia.elements.get(1).and_then(|e| e.first()) {
2133 Some(o) => o.as_str(),
2134 None => continue,
2135 };
2136 // OBIS format: A-B:C.D.E*F — extract E (Tarif/Zählzeit) as split('.')[2] after ':'
2137 let after_colon = obis.find(':').map(|p| &obis[p + 1..]).unwrap_or(obis);
2138 let parts: Vec<&str> = after_colon.split('.').collect();
2139 if parts.len() >= 3 {
2140 let e_str = parts[2].split('*').next().unwrap_or("");
2141 if let Ok(e_val) = e_str.parse::<u32>() {
2142 if e_val >= 1 && e_val <= 62 {
2143 return ConditionResult::True;
2144 }
2145 }
2146 }
2147 }
2148 }
2149 ConditionResult::False
2150 }
2151
2152 /// [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...
2153 fn evaluate_399(&self, _ctx: &EvaluationContext) -> ConditionResult {
2154 // TODO: Condition [399] requires manual implementation
2155 // 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.
2156 ConditionResult::Unknown
2157 }
2158
2159 /// [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/...
2160 fn evaluate_413(&self, _ctx: &EvaluationContext) -> ConditionResult {
2161 // TODO: Condition [413] requires manual implementation
2162 // 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.
2163 ConditionResult::Unknown
2164 }
2165
2166 /// [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...
2167 fn evaluate_414(&self, _ctx: &EvaluationContext) -> ConditionResult {
2168 // TODO: Condition [414] requires manual implementation
2169 // 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.
2170 ConditionResult::Unknown
2171 }
2172
2173 /// [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...
2174 fn evaluate_415(&self, _ctx: &EvaluationContext) -> ConditionResult {
2175 // TODO: Condition [415] requires manual implementation
2176 // 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.
2177 ConditionResult::Unknown
2178 }
2179
2180 /// [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...
2181 fn evaluate_416(&self, _ctx: &EvaluationContext) -> ConditionResult {
2182 // TODO: Condition [416] requires manual implementation
2183 // 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.
2184 ConditionResult::Unknown
2185 }
2186
2187 /// [461] Wenn in derselben SG10 das CCI (Art und Nutzung der Technischen Ressource) im CAV+ZG8 (Technischen Ressource fällt unter § 14a EnWG) vorhanden
2188 fn evaluate_461(&self, ctx: &EvaluationContext) -> ConditionResult {
2189 // Wenn in derselben SG10 das CCI (Art und Nutzung der Technischen Ressource)
2190 // im CAV+ZG8 (Technische Ressource fällt unter § 14a EnWG) vorhanden
2191 // CCI is the SG10 entry segment; condition reduces to: any SG10 has CAV with ZG8
2192 ctx.any_group_has_qualifier("CAV", 0, "ZG8", &["SG4", "SG8", "SG10"])
2193 }
2194
2195 /// [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
2196 fn evaluate_517(&self, _ctx: &EvaluationContext) -> ConditionResult {
2197 // Hinweis: Anzuwenden, wenn einer Marktlokation eine Paket-ID zugeordnet wurde
2198 // und diese wieder gelöscht werden soll, da sie nicht unter den genannten
2199 // NB-Wechsel fällt — informational note, always applies
2200 ConditionResult::True
2201 }
2202
2203 /// [534] Hinweis: Aufgrund der Wiederholbarkeit des SG4 STS Status der Antwort ist die Angabe von max. acht Verwendungszeiträumen möglich
2204 fn evaluate_534(&self, _ctx: &EvaluationContext) -> ConditionResult {
2205 // Hinweis: Aufgrund der Wiederholbarkeit des SG4 STS Status der Antwort ist
2206 // die Angabe von max. acht Verwendungszeiträumen möglich
2207 // — informational note about cardinality, always applies
2208 ConditionResult::True
2209 }
2210
2211 /// [557] Hinweis: Wurden vom Verantwortlichen mehr als acht Verwendungszeiträume gesendet, so werden acht beliebige Verwendungszeiträume beantwortet
2212 fn evaluate_557(&self, _ctx: &EvaluationContext) -> ConditionResult {
2213 // Hinweis: Wurden vom Verantwortlichen mehr als acht Verwendungszeiträume
2214 // gesendet, so werden acht beliebige Verwendungszeiträume beantwortet
2215 // — informational processing note, always applies
2216 ConditionResult::True
2217 }
2218
2219 /// [560] Hinweis: Dies entspricht dem Geschäftsvorfall A
2220 fn evaluate_560(&self, _ctx: &EvaluationContext) -> ConditionResult {
2221 // Hinweis: Dies entspricht dem Geschäftsvorfall A — informational note, always applies
2222 ConditionResult::True
2223 }
2224
2225 /// [561] Hinweis: Dies entspricht dem Geschäftsvorfall B
2226 fn evaluate_561(&self, _ctx: &EvaluationContext) -> ConditionResult {
2227 // Hinweis: Dies entspricht dem Geschäftsvorfall B — informational note, always applies
2228 ConditionResult::True
2229 }
2230
2231 /// [562] Hinweis: Bei Marktlokationen, welche auf Basis von Werten bilanziert werden, wird der erste Tag des Jahres angegeben.
2232 fn evaluate_562(&self, _ctx: &EvaluationContext) -> ConditionResult {
2233 // Hinweis: Bei Marktlokationen, welche auf Basis von Werten bilanziert werden, wird der erste Tag des Jahres angegeben — informational note, always applies
2234 ConditionResult::True
2235 }
2236
2237 /// [564] Hinweis: Das IDE+Z01 (Liste) definiert den Geschäftsvorfall. Alle aufgelisteten IDE+24 sind Bestandteil des Geschäftsvorfalls
2238 fn evaluate_564(&self, _ctx: &EvaluationContext) -> ConditionResult {
2239 // Hinweis: Das IDE+Z01 (Liste) definiert den Geschäftsvorfall. Alle aufgelisteten IDE+24 sind Bestandteil des Geschäftsvorfalls — informational note, always applies
2240 ConditionResult::True
2241 }
2242
2243 /// [565] Hinweis: Das IDE+24 beschreibt einen Bestandteil einer Liste, wenn ein IDE+Z01 vorhanden ist. Es beschreibt nicht den Geschäftsvorfall
2244 fn evaluate_565(&self, _ctx: &EvaluationContext) -> ConditionResult {
2245 // 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
2246 ConditionResult::True
2247 }
2248
2249 /// [578] Hinweis: Dies gilt für den Zeitraum welcher mit Z53 (keine Daten) definiert ist
2250 fn evaluate_578(&self, _ctx: &EvaluationContext) -> ConditionResult {
2251 // Hinweis: Dies gilt für den Zeitraum welcher mit Z53 (keine Daten) definiert ist — informational note, always applies
2252 ConditionResult::True
2253 }
2254
2255 /// [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...
2256 fn evaluate_580(&self, _ctx: &EvaluationContext) -> ConditionResult {
2257 // Hinweis: Ersatzbelieferung context note (Niederspannung non-household / Mittelspannung/Hochspannung) — informational note, always applies
2258 ConditionResult::True
2259 }
2260
2261 /// [681] Hinweis: Übergangsversorgung gibt es nur bei Marktlokationen, die unter § 38a EnWG fallen. Grundlage ist eine bilaterale Vereinbarung
2262 fn evaluate_681(&self, _ctx: &EvaluationContext) -> ConditionResult {
2263 // Hinweis: Übergangsversorgung applies only to Marktlokationen under § 38a EnWG based on bilateral agreement — informational note, always applies
2264 ConditionResult::True
2265 }
2266
2267 /// [686] Hinweis: Zu verwenden bei der Abmeldung der Übergangsversorgung.
2268 fn evaluate_686(&self, _ctx: &EvaluationContext) -> ConditionResult {
2269 // Hinweis: Zu verwenden bei der Abmeldung der Übergangsversorgung — informational note, always applies
2270 ConditionResult::True
2271 }
2272
2273 /// [2000] Je SG5 LOC+Z16 (Marktlokation) ist genau einmal die Segmentgruppe anzugeben
2274 // 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)
2275 fn evaluate_2000(&self, ctx: &EvaluationContext) -> ConditionResult {
2276 // Je SG5 LOC+Z16 (Marktlokation) ist genau einmal die Segmentgruppe anzugeben
2277 // Per SG4 transaction group, exactly one SG5 instance should contain LOC+Z16
2278 let nav = match ctx.navigator() {
2279 Some(n) => n,
2280 None => {
2281 let count = ctx.count_qualified_in_group("LOC", 0, "Z16", &["SG4", "SG5"]);
2282 return ConditionResult::from(count == 1);
2283 }
2284 };
2285 let sg4_count = nav.group_instance_count(&["SG4"]);
2286 if sg4_count == 0 {
2287 return ConditionResult::Unknown;
2288 }
2289 for i in 0..sg4_count {
2290 let sg5_count = nav.child_group_instance_count(&["SG4"], i, "SG5");
2291 let mut loc_z16_count = 0usize;
2292 for j in 0..sg5_count {
2293 let locs = nav.find_segments_in_child_group("LOC", &["SG4"], i, "SG5", j);
2294 for loc in &locs {
2295 if loc
2296 .elements
2297 .first()
2298 .and_then(|e| e.first())
2299 .is_some_and(|v| v == "Z16")
2300 {
2301 loc_z16_count += 1;
2302 }
2303 }
2304 }
2305 if loc_z16_count != 1 {
2306 return ConditionResult::False;
2307 }
2308 }
2309 ConditionResult::True
2310 }
2311
2312 /// [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...
2313 // 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)
2314 fn evaluate_2006(&self, ctx: &EvaluationContext) -> ConditionResult {
2315 let nav = match ctx.navigator() {
2316 Some(n) => n,
2317 None => return ConditionResult::Unknown,
2318 };
2319 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
2320 let mut qualifying_zeitraum_ids: Vec<String> = Vec::new();
2321 for i in 0..sg8_count {
2322 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
2323 let z01_seq = seq_segs.iter().find(|s| {
2324 s.elements
2325 .first()
2326 .and_then(|e| e.first())
2327 .is_some_and(|v| v == "Z01")
2328 });
2329 if let Some(seq) = z01_seq {
2330 if self.evaluate(199, ctx).is_true() {
2331 if let Some(zeitraum_id) = seq.elements.get(1).and_then(|e| e.first()) {
2332 if !zeitraum_id.is_empty() {
2333 qualifying_zeitraum_ids.push(zeitraum_id.clone());
2334 }
2335 }
2336 }
2337 }
2338 }
2339 if qualifying_zeitraum_ids.is_empty() {
2340 return ConditionResult::Unknown;
2341 }
2342 // Verify each qualifying Zeitraum-ID appears exactly once across all SG8 SEQ groups
2343 let mut id_counts: std::collections::HashMap<String, usize> =
2344 std::collections::HashMap::new();
2345 for i in 0..sg8_count {
2346 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
2347 for seq in &seq_segs {
2348 if let Some(zeitraum_id) = seq.elements.get(1).and_then(|e| e.first()) {
2349 if !zeitraum_id.is_empty() && qualifying_zeitraum_ids.contains(zeitraum_id) {
2350 *id_counts.entry(zeitraum_id.clone()).or_insert(0) += 1;
2351 }
2352 }
2353 }
2354 }
2355 ConditionResult::from(
2356 qualifying_zeitraum_ids
2357 .iter()
2358 .all(|id| id_counts.get(id).copied().unwrap_or(0) == 1),
2359 )
2360 }
2361
2362 /// [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...
2363 // 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)
2364 fn evaluate_2007(&self, ctx: &EvaluationContext) -> ConditionResult {
2365 let nav = match ctx.navigator() {
2366 Some(n) => n,
2367 None => return ConditionResult::Unknown,
2368 };
2369 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
2370 let mut qualifying_zeitraum_ids: Vec<String> = Vec::new();
2371 for i in 0..sg8_count {
2372 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
2373 let z01_seq = seq_segs.iter().find(|s| {
2374 s.elements
2375 .first()
2376 .and_then(|e| e.first())
2377 .is_some_and(|v| v == "Z01")
2378 });
2379 if let Some(seq) = z01_seq {
2380 if self.evaluate(199, ctx).is_true() {
2381 if let Some(zeitraum_id) = seq.elements.get(1).and_then(|e| e.first()) {
2382 if !zeitraum_id.is_empty() {
2383 qualifying_zeitraum_ids.push(zeitraum_id.clone());
2384 }
2385 }
2386 }
2387 }
2388 }
2389 if qualifying_zeitraum_ids.is_empty() {
2390 return ConditionResult::Unknown;
2391 }
2392 let mut id_counts: std::collections::HashMap<String, usize> =
2393 std::collections::HashMap::new();
2394 for i in 0..sg8_count {
2395 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
2396 for seq in &seq_segs {
2397 if let Some(zeitraum_id) = seq.elements.get(1).and_then(|e| e.first()) {
2398 if !zeitraum_id.is_empty() && qualifying_zeitraum_ids.contains(zeitraum_id) {
2399 *id_counts.entry(zeitraum_id.clone()).or_insert(0) += 1;
2400 }
2401 }
2402 }
2403 }
2404 ConditionResult::from(
2405 qualifying_zeitraum_ids
2406 .iter()
2407 .all(|id| id_counts.get(id).copied().unwrap_or(0) == 1),
2408 )
2409 }
2410
2411 /// [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...
2412 // 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)
2413 fn evaluate_2008(&self, ctx: &EvaluationContext) -> ConditionResult {
2414 let nav = match ctx.navigator() {
2415 Some(n) => n,
2416 None => return ConditionResult::Unknown,
2417 };
2418 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
2419 let mut qualifying_zeitraum_ids: Vec<String> = Vec::new();
2420 for i in 0..sg8_count {
2421 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
2422 let z01_seq = seq_segs.iter().find(|s| {
2423 s.elements
2424 .first()
2425 .and_then(|e| e.first())
2426 .is_some_and(|v| v == "Z01")
2427 });
2428 if let Some(seq) = z01_seq {
2429 if self.evaluate(89, ctx).is_true() {
2430 if let Some(zeitraum_id) = seq.elements.get(1).and_then(|e| e.first()) {
2431 if !zeitraum_id.is_empty() {
2432 qualifying_zeitraum_ids.push(zeitraum_id.clone());
2433 }
2434 }
2435 }
2436 }
2437 }
2438 if qualifying_zeitraum_ids.is_empty() {
2439 return ConditionResult::Unknown;
2440 }
2441 let mut id_counts: std::collections::HashMap<String, usize> =
2442 std::collections::HashMap::new();
2443 for i in 0..sg8_count {
2444 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
2445 for seq in &seq_segs {
2446 if let Some(zeitraum_id) = seq.elements.get(1).and_then(|e| e.first()) {
2447 if !zeitraum_id.is_empty() && qualifying_zeitraum_ids.contains(zeitraum_id) {
2448 *id_counts.entry(zeitraum_id.clone()).or_insert(0) += 1;
2449 }
2450 }
2451 }
2452 }
2453 ConditionResult::from(
2454 qualifying_zeitraum_ids
2455 .iter()
2456 .all(|id| id_counts.get(id).copied().unwrap_or(0) == 1),
2457 )
2458 }
2459
2460 /// [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...
2461 // REVIEW: Condition 2009 is the plural-grammar variant of 2008 ('Bedingungen' vs 'Bedingung'), semantically identical. Same implementation as 2008 referencing condition [89]. (medium confidence)
2462 fn evaluate_2009(&self, ctx: &EvaluationContext) -> ConditionResult {
2463 let nav = match ctx.navigator() {
2464 Some(n) => n,
2465 None => return ConditionResult::Unknown,
2466 };
2467 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
2468 let mut qualifying_zeitraum_ids: Vec<String> = Vec::new();
2469 for i in 0..sg8_count {
2470 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
2471 let z01_seq = seq_segs.iter().find(|s| {
2472 s.elements
2473 .first()
2474 .and_then(|e| e.first())
2475 .is_some_and(|v| v == "Z01")
2476 });
2477 if let Some(seq) = z01_seq {
2478 if self.evaluate(89, ctx).is_true() {
2479 if let Some(zeitraum_id) = seq.elements.get(1).and_then(|e| e.first()) {
2480 if !zeitraum_id.is_empty() {
2481 qualifying_zeitraum_ids.push(zeitraum_id.clone());
2482 }
2483 }
2484 }
2485 }
2486 }
2487 if qualifying_zeitraum_ids.is_empty() {
2488 return ConditionResult::Unknown;
2489 }
2490 let mut id_counts: std::collections::HashMap<String, usize> =
2491 std::collections::HashMap::new();
2492 for i in 0..sg8_count {
2493 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
2494 for seq in &seq_segs {
2495 if let Some(zeitraum_id) = seq.elements.get(1).and_then(|e| e.first()) {
2496 if !zeitraum_id.is_empty() && qualifying_zeitraum_ids.contains(zeitraum_id) {
2497 *id_counts.entry(zeitraum_id.clone()).or_insert(0) += 1;
2498 }
2499 }
2500 }
2501 }
2502 ConditionResult::from(
2503 qualifying_zeitraum_ids
2504 .iter()
2505 .all(|id| id_counts.get(id).copied().unwrap_or(0) == 1),
2506 )
2507 }
2508
2509 /// [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 ...
2510 // 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)
2511 fn evaluate_2011(&self, ctx: &EvaluationContext) -> ConditionResult {
2512 let nav = match ctx.navigator() {
2513 Some(n) => n,
2514 None => {
2515 // Fallback: check message-wide RFF+Z49/Z53 for DE1156 Zeitraum-IDs
2516 let rff_segs = ctx.find_segments("RFF");
2517 let has_qualifying = rff_segs.iter().any(|s| {
2518 let qual = s
2519 .elements
2520 .first()
2521 .and_then(|e| e.first())
2522 .map(|v| v.as_str());
2523 matches!(qual, Some("Z49") | Some("Z53"))
2524 && s.elements
2525 .first()
2526 .and_then(|e| e.get(2))
2527 .is_some_and(|v| !v.is_empty())
2528 });
2529 return if has_qualifying {
2530 ConditionResult::True
2531 } else {
2532 ConditionResult::Unknown
2533 };
2534 }
2535 };
2536 let sg6_count = nav.group_instance_count(&["SG4", "SG6"]);
2537 let mut zeitraum_ids: std::collections::HashSet<String> = std::collections::HashSet::new();
2538 for i in 0..sg6_count {
2539 let rff_segs = nav.find_segments_in_group("RFF", &["SG4", "SG6"], i);
2540 for rff in &rff_segs {
2541 let qual = rff
2542 .elements
2543 .first()
2544 .and_then(|e| e.first())
2545 .map(|s| s.as_str());
2546 if matches!(qual, Some("Z49") | Some("Z53")) {
2547 // DE1156 is elements[0][2]
2548 if let Some(zeitraum_id) = rff.elements.first().and_then(|e| e.get(2)) {
2549 if !zeitraum_id.is_empty() {
2550 zeitraum_ids.insert(zeitraum_id.clone());
2551 }
2552 }
2553 }
2554 }
2555 }
2556 if zeitraum_ids.is_empty() {
2557 return ConditionResult::Unknown;
2558 }
2559 // The segment group should appear exactly once per distinct Zeitraum-ID from SG6 RFF+Z49/Z53
2560 // We verify that qualifying Zeitraum-IDs are present — cardinality enforcement is structural
2561 ConditionResult::True
2562 }
2563
2564 /// [2013] Mindesten einmal anzugeben, wenn kein SG6 RFF+Z54 (Verwendungszeitraum der Daten: Im System keine Daten vorhanden) vorhanden
2565 fn evaluate_2013(&self, ctx: &EvaluationContext) -> ConditionResult {
2566 // Mindestens einmal anzugeben, wenn kein SG6 RFF+Z54 vorhanden
2567 // True when RFF+Z54 (Verwendungszeitraum: Im System keine Daten vorhanden) is absent
2568 ctx.lacks_qualifier("RFF", 0, "Z54")
2569 }
2570
2571 /// [2014] Mindesten einmal anzugeben, wenn kein SG6 RFF+Z47 (Verwendungszeitraum der Daten: Im System vorhandene Daten) vorhanden
2572 fn evaluate_2014(&self, ctx: &EvaluationContext) -> ConditionResult {
2573 // Mindestens einmal anzugeben, wenn kein SG6 RFF+Z47 vorhanden
2574 // True when RFF+Z47 (Verwendungszeitraum: Im System vorhandene Daten) is absent
2575 ctx.lacks_qualifier("RFF", 0, "Z47")
2576 }
2577
2578 /// [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 ...
2579 // 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)
2580 fn evaluate_2016(&self, ctx: &EvaluationContext) -> ConditionResult {
2581 // Segmentgruppe ist mind. einmal für jede Zeitraum-ID aus DE1156 der SG6 RFF+Z49/Z53 anzugeben
2582 // Collect Zeitraum-IDs from SG6 RFF+Z49 and Z53 (DE1156 = elements[0][2])
2583 // Then verify each required Zeitraum-ID is referenced by at least one SG8 SEQ (DE1050 = elements[1][0])
2584 let nav = match ctx.navigator() {
2585 Some(n) => n,
2586 None => return ConditionResult::Unknown,
2587 };
2588 let sg6_count = nav.group_instance_count(&["SG4", "SG6"]);
2589 let mut required_ids: std::collections::HashSet<String> = std::collections::HashSet::new();
2590 for i in 0..sg6_count {
2591 let rffs = nav.find_segments_in_group("RFF", &["SG4", "SG6"], i);
2592 for rff in &rffs {
2593 let qual = rff
2594 .elements
2595 .first()
2596 .and_then(|e| e.first())
2597 .map(|s| s.as_str());
2598 if matches!(qual, Some("Z49") | Some("Z53")) {
2599 if let Some(zeitraum_id) = rff.elements.first().and_then(|e| e.get(2)) {
2600 if !zeitraum_id.is_empty() {
2601 required_ids.insert(zeitraum_id.clone());
2602 }
2603 }
2604 }
2605 }
2606 }
2607 if required_ids.is_empty() {
2608 return ConditionResult::Unknown;
2609 }
2610 // Check that for each required Zeitraum-ID at least one SG8 SEQ references it via DE1050
2611 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
2612 let mut found_ids: std::collections::HashSet<String> = std::collections::HashSet::new();
2613 for i in 0..sg8_count {
2614 let seqs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
2615 for seq in &seqs {
2616 if let Some(ref_id) = seq.elements.get(1).and_then(|e| e.first()) {
2617 if !ref_id.is_empty() {
2618 found_ids.insert(ref_id.clone());
2619 }
2620 }
2621 }
2622 }
2623 ConditionResult::from(required_ids.iter().all(|id| found_ids.contains(id)))
2624 }
2625
2626 /// [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
2627 // 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)
2628 fn evaluate_2121(&self, ctx: &EvaluationContext) -> ConditionResult {
2629 // Segmentgruppe ist genau einmal je SG8 SEQ+Z01/Z80/Z81 anzugeben
2630 // True when at least one SG8 with SEQ+Z01, Z80, or Z81 exists (cardinality trigger)
2631 ctx.any_group_has_any_qualifier("SEQ", 0, &["Z01", "Z80", "Z81"], &["SG4", "SG8"])
2632 }
2633
2634 /// [1] Wenn Aufteilung vorhanden
2635 fn evaluate_1(&self, ctx: &EvaluationContext) -> ConditionResult {
2636 ctx.external.evaluate("message_splitting")
2637 }
2638
2639 /// [4] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle LF
2640 fn evaluate_4(&self, ctx: &EvaluationContext) -> ConditionResult {
2641 ctx.external.evaluate("recipient_is_lf")
2642 }
2643
2644 /// [5] Wenn MP-ID in SG2 NAD+MS (Nachrichtenabsender) in der Rolle LF
2645 fn evaluate_5(&self, ctx: &EvaluationContext) -> ConditionResult {
2646 ctx.external.evaluate("sender_is_lf")
2647 }
2648
2649 /// [6] Wenn MP-ID in SG2 NAD+MR (Nachrichtenempfänger) in der Rolle ÜNB
2650 fn evaluate_6(&self, ctx: &EvaluationContext) -> ConditionResult {
2651 ctx.external.evaluate("recipient_role_check")
2652 }
2653
2654 /// [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
2655 fn evaluate_7(&self, _ctx: &EvaluationContext) -> ConditionResult {
2656 // TODO: implement
2657 ConditionResult::Unknown
2658 }
2659
2660 /// [8] Wenn für Datenclearing erforderlich
2661 fn evaluate_8(&self, ctx: &EvaluationContext) -> ConditionResult {
2662 ctx.external.evaluate("data_clearing_required")
2663 }
2664
2665 /// [9] Wenn MP-ID in SG2 NAD+MS (Nachrichtenabsender) in der Rolle MSB
2666 fn evaluate_9(&self, ctx: &EvaluationContext) -> ConditionResult {
2667 ctx.external.evaluate("sender_role_check")
2668 }
2669
2670 /// [10] Wenn SG4 STS+7++xxx+xxx+E01/E03 (Transaktionsgrund befristete Anmeldung) vorhanden
2671 fn evaluate_10(&self, ctx: &EvaluationContext) -> ConditionResult {
2672 // STS+7++E01+ZW4+E03: element[4] is c556_3.d9013 = transaktionsgrundErgaenzungBefristeteAnmeldung
2673 ctx.has_qualified_value("STS", 0, "7", 4, 0, &["E01", "E03"])
2674 }
2675
2676 /// [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
2677 fn evaluate_11(&self, _ctx: &EvaluationContext) -> ConditionResult {
2678 // TODO: implement
2679 ConditionResult::Unknown
2680 }
2681
2682 /// [12] Wenn SG4 DTM+471 (Ende zum nächstmöglichem Termin) nicht vorhanden
2683 fn evaluate_12(&self, _ctx: &EvaluationContext) -> ConditionResult {
2684 // TODO: implement
2685 ConditionResult::Unknown
2686 }
2687
2688 /// [13] Wenn SG4 STS+E01++Z01 (Status der Antwort: Zustimmung mit Terminänderung) nicht vorhanden
2689 fn evaluate_13(&self, _ctx: &EvaluationContext) -> ConditionResult {
2690 // TODO: implement
2691 ConditionResult::Unknown
2692 }
2693
2694 /// [14] Wenn Datum bekannt
2695 fn evaluate_14(&self, ctx: &EvaluationContext) -> ConditionResult {
2696 ctx.external.evaluate("date_known")
2697 }
2698
2699 /// [15] Wenn in derselben SG8 das SEQ+Z98 (Informative Daten der Marktlokation) vorhanden
2700 fn evaluate_15(&self, _ctx: &EvaluationContext) -> ConditionResult {
2701 // TODO: implement
2702 ConditionResult::Unknown
2703 }
2704
2705 /// [16] Wenn SG4 STS+E01++Z12 (Status der Antwort: Ablehnung Vertragsbindung) vorhanden
2706 fn evaluate_16(&self, _ctx: &EvaluationContext) -> ConditionResult {
2707 // TODO: implement
2708 ConditionResult::Unknown
2709 }
2710
2711 /// [17] Wenn in derselben SG8 das SEQ+Z01/Z80/Z81 (Daten der Marktlokation) vorhanden
2712 fn evaluate_17(&self, _ctx: &EvaluationContext) -> ConditionResult {
2713 // TODO: implement
2714 ConditionResult::Unknown
2715 }
2716
2717 /// [18] Wenn SG4 DTM+93 (Ende zum) nicht vorhanden
2718 fn evaluate_18(&self, _ctx: &EvaluationContext) -> ConditionResult {
2719 // TODO: implement
2720 ConditionResult::Unknown
2721 }
2722
2723 /// [19] Wenn SG8 SEQ+Z01/ Z98 (Daten der Marktlokation) SG10 CCI+++ZC0 (Prognose auf Basis von Werten) vorhanden
2724 fn evaluate_19(&self, _ctx: &EvaluationContext) -> ConditionResult {
2725 // TODO: implement
2726 ConditionResult::Unknown
2727 }
2728
2729 /// [21] Wenn SG10 CCI+++ZA6 (Prognose auf Basis von Profilen) in dieser SG8 vorhanden
2730 fn evaluate_21(&self, _ctx: &EvaluationContext) -> ConditionResult {
2731 // TODO: implement
2732 ConditionResult::Unknown
2733 }
2734
2735 /// [22] Es ist die Zeitraum-ID vom DE1156 aus einem passenden SG6 RFF+Z47/ Z48/ Z49 (Verwendungszeitraum der Daten) einzutragen
2736 // 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)
2737 fn evaluate_22(&self, ctx: &EvaluationContext) -> ConditionResult {
2738 for qual in &["Z47", "Z48", "Z49"] {
2739 if matches!(
2740 ctx.groups_share_qualified_value(
2741 "RFF",
2742 0,
2743 qual,
2744 0,
2745 2,
2746 &["SG4", "SG6"],
2747 "SEQ",
2748 1,
2749 0,
2750 &["SG4", "SG8"],
2751 ),
2752 ConditionResult::True
2753 ) {
2754 return ConditionResult::True;
2755 }
2756 }
2757 ConditionResult::False
2758 }
2759
2760 /// [23] Wenn in dieser SG4 das STS+E01++A05/A99 (Status der Antwort) vorhanden
2761 fn evaluate_23(&self, _ctx: &EvaluationContext) -> ConditionResult {
2762 // TODO: implement
2763 ConditionResult::Unknown
2764 }
2765
2766 /// [24] Wenn in dieser SG4 das STS+E01++A25/A99 (Status der Antwort) vorhanden
2767 fn evaluate_24(&self, _ctx: &EvaluationContext) -> ConditionResult {
2768 // TODO: implement
2769 ConditionResult::Unknown
2770 }
2771
2772 /// [25] Wenn die Veräußerungsform der erzeugenden Marktlokation der Marktprämie zugeordnet ist
2773 fn evaluate_25(&self, _ctx: &EvaluationContext) -> ConditionResult {
2774 // TODO: implement
2775 ConditionResult::Unknown
2776 }
2777
2778 /// [27] Wenn das DE2380 von SG4 DTM+Z01 (Kündigungsfrist des Vertrags) an vierter Stelle ein T oder R enthält
2779 fn evaluate_27(&self, _ctx: &EvaluationContext) -> ConditionResult {
2780 // TODO: implement
2781 ConditionResult::Unknown
2782 }
2783
2784 /// [30] Wenn Antwort auf Aktivierung übermittelt wird
2785 fn evaluate_30(&self, _ctx: &EvaluationContext) -> ConditionResult {
2786 // TODO: implement
2787 ConditionResult::Unknown
2788 }
2789
2790 /// [31] Wenn eine Korrektur erfolgt
2791 fn evaluate_31(&self, ctx: &EvaluationContext) -> ConditionResult {
2792 ctx.external.evaluate("correction_in_progress")
2793 }
2794
2795 /// [32] Wenn mehr als ein SG8 (Referenz auf die Lokationsbündelstruktur) vorhanden
2796 fn evaluate_32(&self, _ctx: &EvaluationContext) -> ConditionResult {
2797 // TODO: implement
2798 ConditionResult::Unknown
2799 }
2800
2801 /// [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...
2802 fn evaluate_33(&self, ctx: &EvaluationContext) -> ConditionResult {
2803 ctx.external.evaluate("code_list_membership_check")
2804 }
2805
2806 /// [34] Wenn Antwort auf Deaktivierung übermittelt wird
2807 fn evaluate_34(&self, _ctx: &EvaluationContext) -> ConditionResult {
2808 // TODO: implement
2809 ConditionResult::Unknown
2810 }
2811
2812 /// [35] Wenn das DE2380 von SG4 DTM+Z01 (Kündigungsfrist des Vertrags) an vierter Stelle T (Termin) enthält
2813 fn evaluate_35(&self, _ctx: &EvaluationContext) -> ConditionResult {
2814 // TODO: implement
2815 ConditionResult::Unknown
2816 }
2817
2818 /// [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...
2819 fn evaluate_36(&self, ctx: &EvaluationContext) -> ConditionResult {
2820 ctx.external.evaluate("code_list_membership_check")
2821 }
2822
2823 /// [37] Wenn Anmeldung/ Änderung befristet
2824 fn evaluate_37(&self, ctx: &EvaluationContext) -> ConditionResult {
2825 // Same check as [10]: STS element[4] is befristete Anmeldung code
2826 ctx.has_qualified_value("STS", 0, "7", 4, 0, &["E01", "E03"])
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}