automapper_validation/generated/fv2510/ordrsp_conditions_fv2510.rs
1// <auto-generated>
2// Generated by automapper-generator generate-conditions
3// AHB: xml-migs-and-ahbs/FV2510/ORDRSP_AHB_1_1_Fehlerkorrektur_20250417.xml
4// Generated: 2026-03-12T10:41:52Z
5// </auto-generated>
6
7// LLM-produced bodies aren't idiomatic Rust — silence stylistic lints at
8// file scope so `cargo clippy -D warnings` stays green. Correctness,
9// suspicious, and perf categories stay on so real bugs still surface.
10#![allow(clippy::style, clippy::complexity)]
11
12#[allow(unused_imports)]
13use crate::eval::format_validators::*;
14use crate::eval::{Cluster, ConditionEvaluator, ConditionResult, EvaluationContext};
15// HAND-EDITED: shared cluster helpers for conditions [17]/[18].
16// Preserve across regeneration — see CLAUDE.md "Codelist Providers".
17use crate::eval::ebd_cluster::resolved_sts_code_in_cluster;
18
19/// Generated condition evaluator for ORDRSP FV2510.
20pub struct OrdrspConditionEvaluatorFV2510 {
21 // External condition IDs that require runtime context.
22 external_conditions: std::collections::HashSet<u32>,
23}
24
25impl Default for OrdrspConditionEvaluatorFV2510 {
26 fn default() -> Self {
27 let mut external_conditions = std::collections::HashSet::new();
28 external_conditions.insert(3);
29 external_conditions.insert(4);
30 external_conditions.insert(5);
31 external_conditions.insert(7);
32 external_conditions.insert(9);
33 external_conditions.insert(10);
34 external_conditions.insert(12);
35 external_conditions.insert(13);
36 external_conditions.insert(14);
37 external_conditions.insert(15);
38 external_conditions.insert(16);
39 // HAND-EDITED: [17]/[18] are no longer external — they now read
40 // the EBD cluster lookup directly. See FV2504 counterpart.
41 // external_conditions.insert(17);
42 // external_conditions.insert(18);
43 external_conditions.insert(29);
44 external_conditions.insert(30);
45 external_conditions.insert(31);
46 external_conditions.insert(32);
47 external_conditions.insert(40);
48 external_conditions.insert(49);
49 external_conditions.insert(52);
50 external_conditions.insert(60);
51 external_conditions.insert(70);
52 external_conditions.insert(71);
53 external_conditions.insert(75);
54 external_conditions.insert(492);
55 external_conditions.insert(493);
56 Self {
57 external_conditions,
58 }
59 }
60}
61
62impl ConditionEvaluator for OrdrspConditionEvaluatorFV2510 {
63 fn message_type(&self) -> &str {
64 "ORDRSP"
65 }
66
67 fn format_version(&self) -> &str {
68 "FV2510"
69 }
70
71 fn evaluate(&self, condition: u32, ctx: &EvaluationContext) -> ConditionResult {
72 match condition {
73 1 => self.evaluate_1(ctx),
74 3 => self.evaluate_3(ctx),
75 4 => self.evaluate_4(ctx),
76 5 => self.evaluate_5(ctx),
77 7 => self.evaluate_7(ctx),
78 9 => self.evaluate_9(ctx),
79 10 => self.evaluate_10(ctx),
80 11 => self.evaluate_11(ctx),
81 12 => self.evaluate_12(ctx),
82 13 => self.evaluate_13(ctx),
83 14 => self.evaluate_14(ctx),
84 15 => self.evaluate_15(ctx),
85 16 => self.evaluate_16(ctx),
86 17 => self.evaluate_17(ctx),
87 18 => self.evaluate_18(ctx),
88 21 => self.evaluate_21(ctx),
89 22 => self.evaluate_22(ctx),
90 23 => self.evaluate_23(ctx),
91 24 => self.evaluate_24(ctx),
92 25 => self.evaluate_25(ctx),
93 27 => self.evaluate_27(ctx),
94 28 => self.evaluate_28(ctx),
95 29 => self.evaluate_29(ctx),
96 30 => self.evaluate_30(ctx),
97 31 => self.evaluate_31(ctx),
98 32 => self.evaluate_32(ctx),
99 33 => self.evaluate_33(ctx),
100 34 => self.evaluate_34(ctx),
101 37 => self.evaluate_37(ctx),
102 38 => self.evaluate_38(ctx),
103 39 => self.evaluate_39(ctx),
104 40 => self.evaluate_40(ctx),
105 41 => self.evaluate_41(ctx),
106 42 => self.evaluate_42(ctx),
107 43 => self.evaluate_43(ctx),
108 44 => self.evaluate_44(ctx),
109 45 => self.evaluate_45(ctx),
110 46 => self.evaluate_46(ctx),
111 47 => self.evaluate_47(ctx),
112 48 => self.evaluate_48(ctx),
113 49 => self.evaluate_49(ctx),
114 50 => self.evaluate_50(ctx),
115 51 => self.evaluate_51(ctx),
116 52 => self.evaluate_52(ctx),
117 53 => self.evaluate_53(ctx),
118 54 => self.evaluate_54(ctx),
119 55 => self.evaluate_55(ctx),
120 56 => self.evaluate_56(ctx),
121 57 => self.evaluate_57(ctx),
122 58 => self.evaluate_58(ctx),
123 59 => self.evaluate_59(ctx),
124 60 => self.evaluate_60(ctx),
125 61 => self.evaluate_61(ctx),
126 62 => self.evaluate_62(ctx),
127 63 => self.evaluate_63(ctx),
128 64 => self.evaluate_64(ctx),
129 65 => self.evaluate_65(ctx),
130 66 => self.evaluate_66(ctx),
131 67 => self.evaluate_67(ctx),
132 68 => self.evaluate_68(ctx),
133 69 => self.evaluate_69(ctx),
134 70 => self.evaluate_70(ctx),
135 71 => self.evaluate_71(ctx),
136 72 => self.evaluate_72(ctx),
137 73 => self.evaluate_73(ctx),
138 74 => self.evaluate_74(ctx),
139 75 => self.evaluate_75(ctx),
140 76 => self.evaluate_76(ctx),
141 77 => self.evaluate_77(ctx),
142 78 => self.evaluate_78(ctx),
143 79 => self.evaluate_79(ctx),
144 80 => self.evaluate_80(ctx),
145 81 => self.evaluate_81(ctx),
146 82 => self.evaluate_82(ctx),
147 83 => self.evaluate_83(ctx),
148 490 => self.evaluate_490(ctx),
149 491 => self.evaluate_491(ctx),
150 492 => self.evaluate_492(ctx),
151 493 => self.evaluate_493(ctx),
152 494 => self.evaluate_494(ctx),
153 500 => self.evaluate_500(ctx),
154 503 => self.evaluate_503(ctx),
155 504 => self.evaluate_504(ctx),
156 513 => self.evaluate_513(ctx),
157 518 => self.evaluate_518(ctx),
158 519 => self.evaluate_519(ctx),
159 520 => self.evaluate_520(ctx),
160 521 => self.evaluate_521(ctx),
161 522 => self.evaluate_522(ctx),
162 523 => self.evaluate_523(ctx),
163 524 => self.evaluate_524(ctx),
164 525 => self.evaluate_525(ctx),
165 526 => self.evaluate_526(ctx),
166 527 => self.evaluate_527(ctx),
167 529 => self.evaluate_529(ctx),
168 530 => self.evaluate_530(ctx),
169 533 => self.evaluate_533(ctx),
170 534 => self.evaluate_534(ctx),
171 535 => self.evaluate_535(ctx),
172 536 => self.evaluate_536(ctx),
173 537 => self.evaluate_537(ctx),
174 538 => self.evaluate_538(ctx),
175 539 => self.evaluate_539(ctx),
176 540 => self.evaluate_540(ctx),
177 542 => self.evaluate_542(ctx),
178 543 => self.evaluate_543(ctx),
179 544 => self.evaluate_544(ctx),
180 545 => self.evaluate_545(ctx),
181 546 => self.evaluate_546(ctx),
182 547 => self.evaluate_547(ctx),
183 548 => self.evaluate_548(ctx),
184 902 => self.evaluate_902(ctx),
185 903 => self.evaluate_903(ctx),
186 930 => self.evaluate_930(ctx),
187 931 => self.evaluate_931(ctx),
188 932 => self.evaluate_932(ctx),
189 933 => self.evaluate_933(ctx),
190 934 => self.evaluate_934(ctx),
191 935 => self.evaluate_935(ctx),
192 939 => self.evaluate_939(ctx),
193 940 => self.evaluate_940(ctx),
194 2036 => self.evaluate_2036(ctx),
195 _ => ConditionResult::Unknown,
196 }
197 }
198
199 fn is_external(&self, condition: u32) -> bool {
200 self.external_conditions.contains(&condition)
201 }
202 fn is_known(&self, condition: u32) -> bool {
203 matches!(
204 condition,
205 1 | 3
206 | 4
207 | 5
208 | 7
209 | 9
210 | 10
211 | 11
212 | 12
213 | 13
214 | 14
215 | 15
216 | 16
217 | 17
218 | 18
219 | 21
220 | 22
221 | 23
222 | 24
223 | 25
224 | 27
225 | 28
226 | 29
227 | 30
228 | 31
229 | 32
230 | 33
231 | 34
232 | 37
233 | 38
234 | 39
235 | 40
236 | 41
237 | 42
238 | 43
239 | 44
240 | 45
241 | 46
242 | 47
243 | 48
244 | 49
245 | 50
246 | 51
247 | 52
248 | 53
249 | 54
250 | 55
251 | 56
252 | 57
253 | 58
254 | 59
255 | 60
256 | 61
257 | 62
258 | 63
259 | 64
260 | 65
261 | 66
262 | 67
263 | 68
264 | 69
265 | 70
266 | 71
267 | 72
268 | 73
269 | 74
270 | 75
271 | 76
272 | 77
273 | 78
274 | 79
275 | 80
276 | 81
277 | 82
278 | 83
279 | 490
280 | 491
281 | 492
282 | 493
283 | 494
284 | 500
285 | 503
286 | 504
287 | 513
288 | 518
289 | 519
290 | 520
291 | 521
292 | 522
293 | 523
294 | 524
295 | 525
296 | 526
297 | 527
298 | 529
299 | 530
300 | 533
301 | 534
302 | 535
303 | 536
304 | 537
305 | 538
306 | 539
307 | 540
308 | 542
309 | 543
310 | 544
311 | 545
312 | 546
313 | 547
314 | 548
315 | 902
316 | 903
317 | 930
318 | 931
319 | 932
320 | 933
321 | 934
322 | 935
323 | 939
324 | 940
325 | 2036
326 )
327 }
328}
329
330impl OrdrspConditionEvaluatorFV2510 {
331 /// [7] Wenn MP-ID in SG3 NAD+MR aus Sparte Strom
332 /// EXTERNAL: Requires context from outside the message.
333 fn evaluate_7(&self, ctx: &EvaluationContext) -> ConditionResult {
334 ctx.external.evaluate("recipient_is_strom")
335 }
336
337 /// [13] Wenn MP-ID in SG3 NAD+MR aus Sparte Gas
338 /// EXTERNAL: Requires context from outside the message.
339 fn evaluate_13(&self, ctx: &EvaluationContext) -> ConditionResult {
340 ctx.external.evaluate("recipient_is_gas")
341 }
342
343 /// [52] wenn es sich bei der Reklamation um die Reklamation der ausgerollten Leistungskurvendefinitionen handelte
344 /// EXTERNAL: Requires context from outside the message.
345 fn evaluate_52(&self, ctx: &EvaluationContext) -> ConditionResult {
346 ctx.external
347 .evaluate("reklamation_ausgerollte_leistungskurvendefinitionen")
348 }
349
350 /// [60] wenn es sich bei der Reklamation um die Reklamation der Übersicht der Zählzeitdefinitionen handelte
351 /// EXTERNAL: Requires context from outside the message.
352 fn evaluate_60(&self, ctx: &EvaluationContext) -> ConditionResult {
353 ctx.external
354 .evaluate("reklamation_uebersicht_zaehlzeitdefinitionen")
355 }
356
357 /// [70] wenn es sich bei der Reklamation um die Reklamation der ausgerollten Zählzeitdefinitionen handelte
358 /// EXTERNAL: Requires context from outside the message.
359 fn evaluate_70(&self, ctx: &EvaluationContext) -> ConditionResult {
360 ctx.external
361 .evaluate("reklamation_ausgerollte_zaehlzeitdefinitionen")
362 }
363
364 /// [71] wenn es sich bei der Reklamation um die Reklamation der ausgerollten Schaltzeitdefinitionen handelte
365 /// EXTERNAL: Requires context from outside the message.
366 fn evaluate_71(&self, ctx: &EvaluationContext) -> ConditionResult {
367 ctx.external
368 .evaluate("complaint_is_about_rolled_out_switch_time_definitions")
369 }
370
371 /// [75] Wenn es sich um die Antwort auf eine Bestellung handelt in der ein Messprodukt der Codeliste der Konfigurationen aus dem Kapitel 4.6.2 „Werte nach Typ 2 aus SMGW“ bestellt wurde.
372 /// EXTERNAL: Requires context from outside the message.
373 fn evaluate_75(&self, ctx: &EvaluationContext) -> ConditionResult {
374 ctx.external
375 .evaluate("order_contains_smgw_type2_messprodukt")
376 }
377
378 /// [78] Wenn AJT+A04+E_0279 vorhanden
379 fn evaluate_78(&self, ctx: &EvaluationContext) -> ConditionResult {
380 ctx.has_segment_matching("AJT", &[(0, 0, "A04"), (1, 0, "E_0279")])
381 }
382
383 /// [79] Wenn AJT+A04+E_0283 vorhanden
384 fn evaluate_79(&self, ctx: &EvaluationContext) -> ConditionResult {
385 ctx.has_segment_matching("AJT", &[(0, 0, "A04"), (1, 0, "E_0283")])
386 }
387
388 /// [80] Wenn AJT+A05+E_0279 vorhanden
389 fn evaluate_80(&self, ctx: &EvaluationContext) -> ConditionResult {
390 ctx.has_segment_matching("AJT", &[(0, 0, "A05"), (1, 0, "E_0279")])
391 }
392
393 /// [81] Wenn AJT+A05+E_0283 vorhanden
394 fn evaluate_81(&self, ctx: &EvaluationContext) -> ConditionResult {
395 ctx.has_segment_matching("AJT", &[(0, 0, "A05"), (1, 0, "E_0283")])
396 }
397
398 /// [82] Wenn BGM+Z93 (Bestellung eines Angebots Änderung der Technik der Lokation) vorhanden
399 fn evaluate_82(&self, ctx: &EvaluationContext) -> ConditionResult {
400 ctx.has_qualifier("BGM", 0, "Z93")
401 }
402
403 /// [83] Wenn BGM+Z12 (Änderung der Technik der Lokation) vorhanden
404 fn evaluate_83(&self, ctx: &EvaluationContext) -> ConditionResult {
405 ctx.has_qualifier("BGM", 0, "Z12")
406 }
407
408 /// [513] Hinweis: Wert aus BGM+Z12 (Änderung der Technik der Lokation) DE1004 der ORDERS, mit der die Bestellung erfolgt ist.
409 fn evaluate_513(&self, _ctx: &EvaluationContext) -> ConditionResult {
410 // Hinweis: Wert aus BGM+Z12 (Änderung der Technik der Lokation) DE1004 der ORDERS — informational note, always applies
411 ConditionResult::True
412 }
413
414 /// [543] Hinweis: Wert aus BGM+Z93 (Bestellung eines Angebots Änderung der Technik der Lokation) DE1004 der ORDERS, mit der die Bestellung erfolgt ist.
415 fn evaluate_543(&self, _ctx: &EvaluationContext) -> ConditionResult {
416 // Hinweis: Wert aus BGM+Z93 (Bestellung eines Angebots Änderung der Technik der Lokation) DE1004 der ORDERS — informational note, always applies
417 ConditionResult::True
418 }
419
420 /// [544] Hinweis: Wert aus BGM DE1004 der PRICAT mit der das Preisblatt B des MSB, auf die aus Sicht des MSB das Angebot basiert, übermittelt wurde.
421 fn evaluate_544(&self, _ctx: &EvaluationContext) -> ConditionResult {
422 // Hinweis: Wert aus BGM DE1004 der PRICAT mit der das Preisblatt B des MSB — informational note, always applies
423 ConditionResult::True
424 }
425
426 /// [545] Hinweis: Angabe des Beginnzeitpunkts des realistisch möglichen Umsetzungstermins der zum Zeitpunkt der Ablehnung ermittelt werden kann.
427 fn evaluate_545(&self, _ctx: &EvaluationContext) -> ConditionResult {
428 // Hinweis: Angabe des Beginnzeitpunkts des realistisch möglichen Umsetzungstermins — informational note, always applies
429 ConditionResult::True
430 }
431
432 /// [546] Hinweis: Angabe des Endezeitpunkts des realistisch möglichen Umsetzungstermins der zum Zeitpunkt der Ablehnung ermittelt werden kann.
433 fn evaluate_546(&self, _ctx: &EvaluationContext) -> ConditionResult {
434 // Hinweis: Angabe des Endezeitpunkts des realistisch möglichen Umsetzungstermins — informational note, always applies
435 ConditionResult::True
436 }
437
438 /// [547] Hinweis: Wenn es sich um die Bestellung eines vorherigen Angebots im Rahmen der BDEW Anwendungshilfe "Prozesse zur Änderung der Technik an Lokationen" handelt.
439 fn evaluate_547(&self, _ctx: &EvaluationContext) -> ConditionResult {
440 // Hinweis: Bestellung eines vorherigen Angebots im Rahmen der BDEW Anwendungshilfe 'Prozesse zur Änderung der Technik an Lokationen' — informational note, always applies
441 ConditionResult::True
442 }
443
444 /// [548] Hinweis: Hinweis: wenn es sich um die Beauftragung einer Änderung gemäß WiM Teil1 UC "Messlokationsänderung" handelt.
445 fn evaluate_548(&self, _ctx: &EvaluationContext) -> ConditionResult {
446 // Hinweis: Beauftragung einer Änderung gemäß WiM Teil1 UC 'Messlokationsänderung' — informational note, always applies
447 ConditionResult::True
448 }
449
450 /// [1] Wenn BGM+7 vorhanden
451 fn evaluate_1(&self, ctx: &EvaluationContext) -> ConditionResult {
452 ctx.has_qualifier("BGM", 0, "7")
453 }
454
455 /// [3] Wenn MP-ID in SG3 NAD+MS mit Rolle NB vorhanden
456 /// EXTERNAL: Requires context from outside the message.
457 fn evaluate_3(&self, ctx: &EvaluationContext) -> ConditionResult {
458 ctx.external.evaluate("sender_is_nb")
459 }
460
461 /// [4] Wenn MP-ID in SG3 NAD+MR mit Rolle LF vorhanden
462 /// EXTERNAL: Requires context from outside the message.
463 fn evaluate_4(&self, ctx: &EvaluationContext) -> ConditionResult {
464 ctx.external.evaluate("recipient_is_lf")
465 }
466
467 /// [5] Wenn MP-ID in SG3 NAD+MS mit Rolle LF vorhanden
468 /// EXTERNAL: Requires context from outside the message.
469 fn evaluate_5(&self, ctx: &EvaluationContext) -> ConditionResult {
470 ctx.external.evaluate("sender_is_lf")
471 }
472
473 /// [9] Wenn MP-ID in SG3 NAD+MS mit Rolle LF vorhanden
474 /// EXTERNAL: Requires context from outside the message.
475 fn evaluate_9(&self, ctx: &EvaluationContext) -> ConditionResult {
476 ctx.external.evaluate("sender_is_lf")
477 }
478
479 /// [10] Wenn MP-ID in SG3 NAD+MS mit Rolle MSB vorhanden
480 /// EXTERNAL: Requires context from outside the message.
481 fn evaluate_10(&self, ctx: &EvaluationContext) -> ConditionResult {
482 ctx.external.evaluate("sender_is_msb")
483 }
484
485 /// [11] Wenn AJT+A09+E_0470 vorhanden
486 fn evaluate_11(&self, ctx: &EvaluationContext) -> ConditionResult {
487 ctx.has_qualified_value("AJT", 0, "A09", 1, 0, &["E_0470"])
488 }
489
490 /// [12] Wenn der NB eine unverbindliche Preisinformation angeben kann
491 /// EXTERNAL: Requires context from outside the message.
492 fn evaluate_12(&self, ctx: &EvaluationContext) -> ConditionResult {
493 ctx.external.evaluate("nb_can_provide_price_info")
494 }
495
496 /// [14] Wenn MP-ID in SG3 NAD+MR mit Rolle MSB vorhanden
497 /// EXTERNAL: Requires context from outside the message.
498 fn evaluate_14(&self, ctx: &EvaluationContext) -> ConditionResult {
499 ctx.external.evaluate("recipient_is_msb")
500 }
501
502 /// [15] Wenn MP-ID in SG3 NAD+MR mit Rolle NB vorhanden
503 /// EXTERNAL: Requires context from outside the message.
504 fn evaluate_15(&self, ctx: &EvaluationContext) -> ConditionResult {
505 ctx.external.evaluate("recipient_is_nb")
506 }
507
508 /// [16] Wenn MP-ID in SG3 NAD+MR mit Rolle ÜNB vorhanden
509 /// EXTERNAL: Requires context from outside the message.
510 fn evaluate_16(&self, ctx: &EvaluationContext) -> ConditionResult {
511 ctx.external.evaluate("recipient_is_uenb")
512 }
513
514 /// [17] Der hier angegebene Code des Prüfschritts muss im EBD dem Cluster Zustimmung zugeordnet sein
515 // HAND-EDITED: driven by per-EBD cluster data (mako_prozesse).
516 fn evaluate_17(&self, ctx: &EvaluationContext) -> ConditionResult {
517 resolved_sts_code_in_cluster(ctx, Cluster::is_zustimmung)
518 }
519
520 /// [18] Der hier angegebene Code des Prüfschritts muss im EBD dem Cluster Ablehnung zugeordnet sein
521 // HAND-EDITED: driven by per-EBD cluster data (mako_prozesse).
522 fn evaluate_18(&self, ctx: &EvaluationContext) -> ConditionResult {
523 resolved_sts_code_in_cluster(ctx, Cluster::is_ablehnung)
524 }
525
526 /// [21] Wenn IMD++Z01 vorhanden
527 fn evaluate_21(&self, ctx: &EvaluationContext) -> ConditionResult {
528 ctx.has_qualifier("IMD", 1, "Z01")
529 }
530
531 /// [22] Wenn IMD++Z02 vorhanden
532 fn evaluate_22(&self, ctx: &EvaluationContext) -> ConditionResult {
533 ctx.has_qualifier("IMD", 1, "Z02")
534 }
535
536 /// [23] Wenn IMD++Z03 vorhanden
537 fn evaluate_23(&self, ctx: &EvaluationContext) -> ConditionResult {
538 let segments = ctx.find_segments("IMD");
539 ConditionResult::from(segments.iter().any(|s| {
540 s.elements
541 .get(1)
542 .and_then(|e| e.first())
543 .is_some_and(|v| v == "Z03")
544 }))
545 }
546
547 /// [24] Wenn BGM+Z51 vorhanden
548 fn evaluate_24(&self, ctx: &EvaluationContext) -> ConditionResult {
549 ctx.has_qualifier("BGM", 0, "Z51")
550 }
551
552 /// [25] Wenn BGM+Z52 vorhanden
553 fn evaluate_25(&self, ctx: &EvaluationContext) -> ConditionResult {
554 ctx.has_qualifier("BGM", 0, "Z52")
555 }
556
557 /// [27] Wenn AJT+A05+E_0470 vorhanden
558 fn evaluate_27(&self, ctx: &EvaluationContext) -> ConditionResult {
559 let segments = ctx.find_segments_with_qualifier("AJT", 0, "A05");
560 ConditionResult::from(segments.iter().any(|s| {
561 s.elements
562 .get(1)
563 .and_then(|e| e.first())
564 .is_some_and(|v| v == "E_0470")
565 }))
566 }
567
568 /// [28] Wenn AJT+A99 vorhanden
569 fn evaluate_28(&self, ctx: &EvaluationContext) -> ConditionResult {
570 ctx.has_qualifier("AJT", 0, "A99")
571 }
572
573 /// [29] MP-ID nur aus Sparte Gas
574 /// EXTERNAL: Requires context from outside the message.
575 fn evaluate_29(&self, ctx: &EvaluationContext) -> ConditionResult {
576 ctx.external.evaluate("mp_id_is_gas")
577 }
578
579 /// [30] MP-ID nur aus Sparte Strom
580 /// EXTERNAL: Requires context from outside the message.
581 fn evaluate_30(&self, ctx: &EvaluationContext) -> ConditionResult {
582 ctx.external.evaluate("mp_id_is_strom")
583 }
584
585 /// [31] MP-ID mit Rolle MSB
586 /// EXTERNAL: Requires context from outside the message.
587 fn evaluate_31(&self, ctx: &EvaluationContext) -> ConditionResult {
588 ctx.external.evaluate("mp_id_role_is_msb")
589 }
590
591 /// [32] MP-ID mit Rolle NB
592 /// EXTERNAL: Requires context from outside the message.
593 fn evaluate_32(&self, ctx: &EvaluationContext) -> ConditionResult {
594 ctx.external.evaluate("mp_id_role_is_nb")
595 }
596
597 /// [33] Wenn AJT+A02/A03+E_0488 vorhanden
598 fn evaluate_33(&self, ctx: &EvaluationContext) -> ConditionResult {
599 let segments = ctx.find_segments("AJT");
600 ConditionResult::from(segments.iter().any(|s| {
601 let qual = s
602 .elements
603 .first()
604 .and_then(|e| e.first())
605 .map(|v| v.as_str());
606 let val = s
607 .elements
608 .get(1)
609 .and_then(|e| e.first())
610 .map(|v| v.as_str());
611 matches!(qual, Some("A02") | Some("A03")) && matches!(val, Some("E_0488"))
612 }))
613 }
614
615 /// [34] wenn vorhanden
616 // REVIEW: 'wenn vorhanden' is a generic conditional-use annotation meaning the element should be included whenever the relevant data is available. As a standalone condition without a specific segment target, it functions as a Hinweis-like unconditional True. (medium confidence)
617 fn evaluate_34(&self, _ctx: &EvaluationContext) -> ConditionResult {
618 // 'wenn vorhanden' — generic availability condition: element is conditional on presence of the data
619 // Without a specific segment reference this acts as an unconditional note
620 ConditionResult::True
621 }
622
623 /// [37] Wenn in dieser Nachricht das SG8 CUX+2 vorhanden
624 fn evaluate_37(&self, ctx: &EvaluationContext) -> ConditionResult {
625 ctx.has_qualifier("CUX", 0, "2")
626 }
627
628 /// [38] Möglicher Wert: ZB4 oder ZB5
629 fn evaluate_38(&self, ctx: &EvaluationContext) -> ConditionResult {
630 // HAND-EDITED: the condition names the only values the element may
631 // carry, so it holds for them alone — not a note that always holds.
632 match ctx.resolved_value {
633 Some(v) if !v.is_empty() => ConditionResult::from(matches!(v, "ZB4" | "ZB5")),
634 _ => ConditionResult::Unknown,
635 }
636 }
637
638 /// [39] Möglicher Wert: E17 oder Z07
639 fn evaluate_39(&self, ctx: &EvaluationContext) -> ConditionResult {
640 // HAND-EDITED: the condition names the only values the element may
641 // carry, so it holds for them alone — not a note that always holds.
642 match ctx.resolved_value {
643 Some(v) if !v.is_empty() => ConditionResult::from(matches!(v, "E17" | "Z07")),
644 _ => ConditionResult::Unknown,
645 }
646 }
647
648 /// [40] Wenn der Code im DE3207 in der "EDI@Energy Codeliste der europäischen Ländercodes" in der Spalte "PLZ vorhanden" ein "X" enthält
649 /// EXTERNAL: Requires context from outside the message.
650 fn evaluate_40(&self, ctx: &EvaluationContext) -> ConditionResult {
651 ctx.external.evaluate("country_has_postal_code")
652 }
653
654 /// [41] wenn SG2 AJT (Einzelheiten zu einer Anpassung/Änderung) DE4465 mit Wert ZB5 vorhanden
655 fn evaluate_41(&self, ctx: &EvaluationContext) -> ConditionResult {
656 ctx.has_qualifier("AJT", 0, "ZB5")
657 }
658
659 /// [42] Wenn SG2 AJT+Z07 (Antwortkategorie: Ablehnung (Keine Berechtigung)) vorhanden
660 fn evaluate_42(&self, ctx: &EvaluationContext) -> ConditionResult {
661 ctx.has_qualifier("AJT", 0, "Z07")
662 }
663
664 /// [43] Wenn AJT+A02/A03+E_1001 vorhanden
665 fn evaluate_43(&self, ctx: &EvaluationContext) -> ConditionResult {
666 let ajts = ctx.find_segments("AJT");
667 let found = ajts.iter().any(|s| {
668 let code = s
669 .elements
670 .first()
671 .and_then(|e| e.first())
672 .map(|v| v.as_str());
673 let pos = s
674 .elements
675 .get(1)
676 .and_then(|e| e.first())
677 .map(|v| v.as_str());
678 matches!(code, Some("A02") | Some("A03")) && matches!(pos, Some("E_1001"))
679 });
680 ConditionResult::from(found)
681 }
682
683 /// [44] Wenn AJT+A05+E_1000 vorhanden
684 fn evaluate_44(&self, ctx: &EvaluationContext) -> ConditionResult {
685 let ajts = ctx.find_segments("AJT");
686 let found = ajts.iter().any(|s| {
687 let code = s
688 .elements
689 .first()
690 .and_then(|e| e.first())
691 .map(|v| v.as_str());
692 let pos = s
693 .elements
694 .get(1)
695 .and_then(|e| e.first())
696 .map(|v| v.as_str());
697 matches!(code, Some("A05")) && matches!(pos, Some("E_1000"))
698 });
699 ConditionResult::from(found)
700 }
701
702 /// [45] Wenn AJT+A09+E_1000 vorhanden
703 fn evaluate_45(&self, ctx: &EvaluationContext) -> ConditionResult {
704 let ajts = ctx.find_segments("AJT");
705 let found = ajts.iter().any(|s| {
706 let code = s
707 .elements
708 .first()
709 .and_then(|e| e.first())
710 .map(|v| v.as_str());
711 let pos = s
712 .elements
713 .get(1)
714 .and_then(|e| e.first())
715 .map(|v| v.as_str());
716 matches!(code, Some("A09")) && matches!(pos, Some("E_1000"))
717 });
718 ConditionResult::from(found)
719 }
720
721 /// [46] Wenn AJT+A06+E_0552 vorhanden
722 fn evaluate_46(&self, ctx: &EvaluationContext) -> ConditionResult {
723 let ajts = ctx.find_segments("AJT");
724 let found = ajts.iter().any(|s| {
725 let code = s
726 .elements
727 .first()
728 .and_then(|e| e.first())
729 .map(|v| v.as_str());
730 let pos = s
731 .elements
732 .get(1)
733 .and_then(|e| e.first())
734 .map(|v| v.as_str());
735 matches!(code, Some("A06")) && matches!(pos, Some("E_0552"))
736 });
737 ConditionResult::from(found)
738 }
739
740 /// [47] Wenn AJT+A06+E_0553 vorhanden
741 fn evaluate_47(&self, ctx: &EvaluationContext) -> ConditionResult {
742 let ajts = ctx.find_segments("AJT");
743 let found = ajts.iter().any(|s| {
744 let code = s
745 .elements
746 .first()
747 .and_then(|e| e.first())
748 .map(|v| v.as_str());
749 let pos = s
750 .elements
751 .get(1)
752 .and_then(|e| e.first())
753 .map(|v| v.as_str());
754 matches!(code, Some("A06")) && matches!(pos, Some("E_0553"))
755 });
756 ConditionResult::from(found)
757 }
758
759 /// [48] Wenn AJT+A06+E_0554 vorhanden
760 fn evaluate_48(&self, ctx: &EvaluationContext) -> ConditionResult {
761 let ajts = ctx.find_segments("AJT");
762 let found = ajts.iter().any(|s| {
763 let code = s
764 .elements
765 .first()
766 .and_then(|e| e.first())
767 .map(|v| v.as_str());
768 let pos = s
769 .elements
770 .get(1)
771 .and_then(|e| e.first())
772 .map(|v| v.as_str());
773 matches!(code, Some("A06")) && matches!(pos, Some("E_0554"))
774 });
775 ConditionResult::from(found)
776 }
777
778 /// [49] nur, wenn in ursprünglicher Nachricht IMD++Z60 (Abbestellung Messprodukt mit Zählzeitdefinition des LF) vorhanden war
779 /// EXTERNAL: Requires context from outside the message.
780 fn evaluate_49(&self, ctx: &EvaluationContext) -> ConditionResult {
781 ctx.external.evaluate("original_order_had_imd_z60")
782 }
783
784 /// [50] wenn im DE3155 in demselben COM der Code EM vorhanden ist
785 fn evaluate_50(&self, ctx: &EvaluationContext) -> ConditionResult {
786 let coms = ctx.find_segments("COM");
787 ConditionResult::from(coms.iter().any(|s| {
788 s.elements
789 .first()
790 .and_then(|e| e.get(1))
791 .map(|v| v == "EM")
792 .unwrap_or(false)
793 }))
794 }
795
796 /// [51] wenn im DE3155 in demselben COM der Code TE / FX / AJ / AL vorhanden ist
797 fn evaluate_51(&self, ctx: &EvaluationContext) -> ConditionResult {
798 let coms = ctx.find_segments("COM");
799 ConditionResult::from(coms.iter().any(|s| {
800 matches!(
801 s.elements
802 .first()
803 .and_then(|e| e.get(1))
804 .map(|v| v.as_str()),
805 Some("TE") | Some("FX") | Some("AJ") | Some("AL")
806 )
807 }))
808 }
809
810 /// [53] Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z59
811 fn evaluate_53(&self, _ctx: &EvaluationContext) -> ConditionResult {
812 // Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z59 — informational note about value origin, always applies
813 ConditionResult::True
814 }
815
816 /// [54] Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z80
817 fn evaluate_54(&self, _ctx: &EvaluationContext) -> ConditionResult {
818 // Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z80 — informational note about value origin, always applies
819 ConditionResult::True
820 }
821
822 /// [55] Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z81
823 fn evaluate_55(&self, _ctx: &EvaluationContext) -> ConditionResult {
824 // Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z81 — informational note about value origin, always applies
825 ConditionResult::True
826 }
827
828 /// [56] wenn SG2 AJT+A02/A03/A06/A07/A10/A11+E_0548 vorhanden
829 fn evaluate_56(&self, ctx: &EvaluationContext) -> ConditionResult {
830 let ajts = ctx.find_segments("AJT");
831 ConditionResult::from(ajts.iter().any(|s| {
832 let de4465 = s
833 .elements
834 .first()
835 .and_then(|e| e.first())
836 .map(|s| s.as_str());
837 let de1082 = s
838 .elements
839 .get(1)
840 .and_then(|e| e.first())
841 .map(|s| s.as_str());
842 matches!(
843 de4465,
844 Some("A02") | Some("A03") | Some("A06") | Some("A07") | Some("A10") | Some("A11")
845 ) && de1082 == Some("E_0548")
846 }))
847 }
848
849 /// [57] wenn SG2 AJT+A02/A03/A06/A07/A10/A11+E_0549 vorhanden
850 fn evaluate_57(&self, ctx: &EvaluationContext) -> ConditionResult {
851 let ajts = ctx.find_segments("AJT");
852 ConditionResult::from(ajts.iter().any(|s| {
853 let de4465 = s
854 .elements
855 .first()
856 .and_then(|e| e.first())
857 .map(|s| s.as_str());
858 let de1082 = s
859 .elements
860 .get(1)
861 .and_then(|e| e.first())
862 .map(|s| s.as_str());
863 matches!(
864 de4465,
865 Some("A02") | Some("A03") | Some("A06") | Some("A07") | Some("A10") | Some("A11")
866 ) && de1082 == Some("E_0549")
867 }))
868 }
869
870 /// [58] wenn SG2 AJT+A02/A03/A06/A07+E_0550 vorhanden
871 fn evaluate_58(&self, ctx: &EvaluationContext) -> ConditionResult {
872 let ajts = ctx.find_segments("AJT");
873 ConditionResult::from(ajts.iter().any(|s| {
874 let de4465 = s
875 .elements
876 .first()
877 .and_then(|e| e.first())
878 .map(|s| s.as_str());
879 let de1082 = s
880 .elements
881 .get(1)
882 .and_then(|e| e.first())
883 .map(|s| s.as_str());
884 matches!(
885 de4465,
886 Some("A02") | Some("A03") | Some("A06") | Some("A07")
887 ) && de1082 == Some("E_0550")
888 }))
889 }
890
891 /// [59] wenn SG2 AJT+A02/A03/A06/A07/A10/A11+E_0551 vorhanden
892 fn evaluate_59(&self, ctx: &EvaluationContext) -> ConditionResult {
893 let ajts = ctx.find_segments("AJT");
894 ConditionResult::from(ajts.iter().any(|s| {
895 let de4465 = s
896 .elements
897 .first()
898 .and_then(|e| e.first())
899 .map(|s| s.as_str());
900 let de1082 = s
901 .elements
902 .get(1)
903 .and_then(|e| e.first())
904 .map(|s| s.as_str());
905 matches!(
906 de4465,
907 Some("A02") | Some("A03") | Some("A06") | Some("A07") | Some("A10") | Some("A11")
908 ) && de1082 == Some("E_0551")
909 }))
910 }
911
912 /// [61] wenn es sich bei der Reklamation um die Reklamation der Übersicht der Schaltzeitdefinitionen handelte
913 // REVIEW: The condition checks whether the complaint concerned the overview of switching time definitions (Schaltzeitdefinitionen). Condition 63 establishes that BGM+Z60 is the code for Schaltzeitdefinitionen in UTILTS, and the ORDRSP BGM code mirrors this type. Checking BGM elements[0][0] == 'Z60' identifies this complaint type. (medium confidence)
914 fn evaluate_61(&self, ctx: &EvaluationContext) -> ConditionResult {
915 // Reklamation der Übersicht der Schaltzeitdefinitionen → ORDRSP with BGM+Z60
916 ctx.has_qualifier("BGM", 0, "Z60")
917 }
918
919 /// [62] wenn es sich bei der Reklamation um die Reklamation der Übersicht der Leistungskurvendefinitionen handelte
920 // REVIEW: The condition checks whether the complaint concerned the overview of load curve definitions (Leistungskurvendefinitionen). Conditions 64 and 65 establish BGM+Z78 and BGM+Z79 as the two related UTILTS codes for Leistungskurven types, so both are checked. (medium confidence)
921 fn evaluate_62(&self, ctx: &EvaluationContext) -> ConditionResult {
922 // Reklamation der Übersicht der Leistungskurvendefinitionen → BGM+Z78 or BGM+Z79
923 let bgm_segs = ctx.find_segments("BGM");
924 match bgm_segs.first() {
925 Some(s) => {
926 let code = s
927 .elements
928 .first()
929 .and_then(|e| e.first())
930 .map(|v| v.as_str());
931 ConditionResult::from(matches!(code, Some("Z78") | Some("Z79")))
932 }
933 None => ConditionResult::False, // segment absent → condition not applicable
934 }
935 }
936
937 /// [63] Dokumentennummer aus BGM+Z60 DE1004 der UTILTS
938 fn evaluate_63(&self, _ctx: &EvaluationContext) -> ConditionResult {
939 // Hinweis: Dokumentennummer aus BGM+Z60 DE1004 der UTILTS — informational note, always applies
940 ConditionResult::True
941 }
942
943 /// [64] Dokumentennummer aus BGM+Z78 DE1004 der UTILTS
944 fn evaluate_64(&self, _ctx: &EvaluationContext) -> ConditionResult {
945 // Hinweis: Dokumentennummer aus BGM+Z78 DE1004 der UTILTS — informational note, always applies
946 ConditionResult::True
947 }
948
949 /// [65] Dokumentennummer aus BGM+Z79 DE1004 der UTILTS
950 fn evaluate_65(&self, _ctx: &EvaluationContext) -> ConditionResult {
951 // Hinweis: Dokumentennummer aus BGM+Z79 DE1004 der UTILTS — informational note, always applies
952 ConditionResult::True
953 }
954
955 /// [66] wenn SG2 AJT+A01/A02/A03+E_0544 vorhanden
956 fn evaluate_66(&self, ctx: &EvaluationContext) -> ConditionResult {
957 let ajts = ctx.find_segments("AJT");
958 ConditionResult::from(ajts.iter().any(|s| {
959 let de4465 = s
960 .elements
961 .first()
962 .and_then(|e| e.first())
963 .map(|s| s.as_str());
964 let de1082 = s
965 .elements
966 .get(1)
967 .and_then(|e| e.first())
968 .map(|s| s.as_str());
969 matches!(de4465, Some("A01") | Some("A02") | Some("A03")) && de1082 == Some("E_0544")
970 }))
971 }
972
973 /// [67] wenn SG2 AJT+A01/A02/A03+E_0545 vorhanden
974 fn evaluate_67(&self, ctx: &EvaluationContext) -> ConditionResult {
975 let ajts = ctx.find_segments("AJT");
976 ConditionResult::from(ajts.iter().any(|s| {
977 let de4465 = s
978 .elements
979 .first()
980 .and_then(|e| e.first())
981 .map(|s| s.as_str());
982 let de1082 = s
983 .elements
984 .get(1)
985 .and_then(|e| e.first())
986 .map(|s| s.as_str());
987 matches!(de4465, Some("A01") | Some("A02") | Some("A03")) && de1082 == Some("E_0545")
988 }))
989 }
990
991 /// [68] wenn SG2 AJT+A02/A03+E_0546 vorhanden
992 fn evaluate_68(&self, ctx: &EvaluationContext) -> ConditionResult {
993 let ajts = ctx.find_segments("AJT");
994 ConditionResult::from(ajts.iter().any(|s| {
995 let de4465 = s
996 .elements
997 .first()
998 .and_then(|e| e.first())
999 .map(|s| s.as_str());
1000 let de1082 = s
1001 .elements
1002 .get(1)
1003 .and_then(|e| e.first())
1004 .map(|s| s.as_str());
1005 matches!(de4465, Some("A02") | Some("A03")) && de1082 == Some("E_0546")
1006 }))
1007 }
1008
1009 /// [69] wenn SG2 AJT+A01/A02/A03+E_0547 vorhanden
1010 fn evaluate_69(&self, ctx: &EvaluationContext) -> ConditionResult {
1011 let ajts = ctx.find_segments("AJT");
1012 ConditionResult::from(ajts.iter().any(|s| {
1013 let de4465 = s
1014 .elements
1015 .first()
1016 .and_then(|e| e.first())
1017 .map(|s| s.as_str());
1018 let de1082 = s
1019 .elements
1020 .get(1)
1021 .and_then(|e| e.first())
1022 .map(|s| s.as_str());
1023 matches!(de4465, Some("A01") | Some("A02") | Some("A03")) && de1082 == Some("E_0547")
1024 }))
1025 }
1026
1027 /// [72] wenn AJT+A04+E_0552 vorhanden
1028 fn evaluate_72(&self, ctx: &EvaluationContext) -> ConditionResult {
1029 ctx.has_qualified_value("AJT", 0, "A04", 1, 0, &["E_0552"])
1030 }
1031
1032 /// [73] wenn AJT+A04+E_0553 vorhanden
1033 fn evaluate_73(&self, ctx: &EvaluationContext) -> ConditionResult {
1034 ctx.has_qualified_value("AJT", 0, "A04", 1, 0, &["E_0553"])
1035 }
1036
1037 /// [74] wenn AJT+A04+E_0554 vorhanden
1038 fn evaluate_74(&self, ctx: &EvaluationContext) -> ConditionResult {
1039 ctx.has_qualified_value("AJT", 0, "A04", 1, 0, &["E_0554"])
1040 }
1041
1042 /// [76] Wenn FTX+Z27 (IP-Adresse des Absenders) nicht vorhanden
1043 fn evaluate_76(&self, ctx: &EvaluationContext) -> ConditionResult {
1044 ctx.lacks_qualifier("FTX", 0, "Z27")
1045 }
1046
1047 /// [77] Wenn FTX+Z28 (IP-Range des Absenders) nicht vorhanden
1048 fn evaluate_77(&self, ctx: &EvaluationContext) -> ConditionResult {
1049 ctx.lacks_qualifier("FTX", 0, "Z28")
1050 }
1051
1052 /// [490] wenn Wert in diesem DE, an der Stelle CCYYMMDDHHMM ein Zeitpunkt aus dem angegeben Zeitraum der Tabelle Kapitel 3.5 „Übersicht gesetzliche deutsche Sommerzeit (MESZ)“ der Spalten: „Sommerzei...
1053 fn evaluate_490(&self, ctx: &EvaluationContext) -> ConditionResult {
1054 match ctx.resolved_value {
1055 Some(val) => is_mesz_utc(val),
1056 None => ConditionResult::False,
1057 }
1058 }
1059
1060 /// [491] wenn Wert in diesem DE, an der Stelle CCYYMMDDHHMM ein Zeitpunkt aus dem angegeben Zeitraum der Tabelle Kapitel 3.6 „Übersicht gesetzliche deutsche Zeit (MEZ)“ der Spalten: „Winterzeit (MEZ)...
1061 fn evaluate_491(&self, ctx: &EvaluationContext) -> ConditionResult {
1062 match ctx.resolved_value {
1063 Some(val) => is_mez_utc(val),
1064 None => ConditionResult::False,
1065 }
1066 }
1067
1068 /// [492] wenn MP-ID in NAD+MR aus Sparte Strom
1069 /// EXTERNAL: Requires context from outside the message.
1070 fn evaluate_492(&self, ctx: &EvaluationContext) -> ConditionResult {
1071 ctx.external.evaluate("recipient_is_strom")
1072 }
1073
1074 /// [493] wenn MP-ID in NAD+MR aus Sparte Gas
1075 /// EXTERNAL: Requires context from outside the message.
1076 fn evaluate_493(&self, ctx: &EvaluationContext) -> ConditionResult {
1077 ctx.external.evaluate("recipient_is_gas")
1078 }
1079
1080 /// [494] Das hier genannte Datum muss der Zeitpunkt sein, zu dem das Dokument erstellt wurde, oder ein Zeitpunkt, der davor liegt.
1081 // REVIEW: 'Das hier genannte Datum muss der Zeitpunkt sein, zu dem das Dokument erstellt wurde, oder ein Zeitpunkt, der davor liegt.' This is a constraint description stating the date must be the document creation time or earlier. It functions as an unconditional validation rule (always applies) rather than a conditional trigger. Without knowing which specific DTM qualifier 'here' refers to in the calling context, and since the constraint itself is always applicable, returning True is appropriate. (medium confidence)
1082 fn evaluate_494(&self, _ctx: &EvaluationContext) -> ConditionResult {
1083 ConditionResult::True
1084 }
1085
1086 /// [500] Hinweis: Angabe eines technischen Ansprechpartners für die Geräteübernahme
1087 fn evaluate_500(&self, _ctx: &EvaluationContext) -> ConditionResult {
1088 ConditionResult::True
1089 }
1090
1091 /// [503] Hinweis: Datum, bis zu dem der MSBA zur Fortführung verpflichtet wurde
1092 fn evaluate_503(&self, _ctx: &EvaluationContext) -> ConditionResult {
1093 ConditionResult::True
1094 }
1095
1096 /// [504] Hinweis: Ggf. korrigiert bei einer Zeitangabe in der ORDERS, die außerhalb des max. möglichen Weiterverpflichtungszeitraums ist. Als Antwort wird dann in SG2 AJT Zustimmung mit Terminänderung an...
1097 fn evaluate_504(&self, _ctx: &EvaluationContext) -> ConditionResult {
1098 // Hinweis: Ggf. korrigiert bei einer Zeitangabe in der ORDERS, die außerhalb des max. möglichen Weiterverpflichtungszeitraums ist. Als Antwort wird dann in SG2 AJT Zustimmung mit Terminänderung angegeben.
1099 ConditionResult::True
1100 }
1101
1102 /// [518] Hinweis: Wert aus BGM+Z10 DE1004 der ORDERS, mit der die Bestellung erfolgt ist
1103 fn evaluate_518(&self, _ctx: &EvaluationContext) -> ConditionResult {
1104 // Hinweis: Wert aus BGM+Z10 DE1004 der ORDERS, mit der die Bestellung erfolgt ist.
1105 ConditionResult::True
1106 }
1107
1108 /// [519] Hinweis: Wert aus BGM+7 DE1004 der ORDERS, mit der die Bestellung erfolgt ist.
1109 fn evaluate_519(&self, _ctx: &EvaluationContext) -> ConditionResult {
1110 // Hinweis: Wert aus BGM+7 DE1004 der ORDERS, mit der die Bestellung erfolgt ist.
1111 ConditionResult::True
1112 }
1113
1114 /// [520] Hinweis: Wert aus BGM+Z29 DE1004 der ORDERS, mit der die Anfrage zur Beendigung der Rechnungsabwicklung erfolgt ist.
1115 fn evaluate_520(&self, _ctx: &EvaluationContext) -> ConditionResult {
1116 // Hinweis: Wert aus BGM+Z29 DE1004 der ORDERS, mit der die Anfrage zur Beendigung der Rechnungsabwicklung erfolgt ist.
1117 ConditionResult::True
1118 }
1119
1120 /// [521] Hinweis: Wert aus BGM+Z14/Z61/Z62 DE1004 der ORDERS, mit der die Anforderung von Stammdaten erfolgt ist
1121 fn evaluate_521(&self, _ctx: &EvaluationContext) -> ConditionResult {
1122 // Hinweis: Wert aus BGM+Z14/Z61/Z62 DE1004 der ORDERS, mit der die Anforderung von Stammdaten erfolgt ist
1123 // Informational note — documents that the BGM DE1004 value originates from the original ORDERS request.
1124 ConditionResult::True
1125 }
1126
1127 /// [522] Hinweis: Wert aus BGM+7/Z28/Z48 DE1004 der ORDERS, mit der die Anforderung von Werten erfolgt ist.
1128 fn evaluate_522(&self, _ctx: &EvaluationContext) -> ConditionResult {
1129 // Hinweis: Wert aus BGM+7/Z28/Z48 DE1004 der ORDERS — informational note, always applies
1130 ConditionResult::True
1131 }
1132
1133 /// [523] Hinweis: Wert aus BGM+7 DE1004 der ORDERS, mit der die Anforderung Anforderung von Brennwert und Zustandszahl erfolgt ist.
1134 fn evaluate_523(&self, _ctx: &EvaluationContext) -> ConditionResult {
1135 // Hinweis: Wert aus BGM+7 DE1004 der ORDERS — informational note, always applies
1136 ConditionResult::True
1137 }
1138
1139 /// [524] Hinweis: Wert aus BGM+Z14 DE1004 der ORDERS, mit der die Anfrage vom MSB Gas erfolgt ist.
1140 fn evaluate_524(&self, _ctx: &EvaluationContext) -> ConditionResult {
1141 // Hinweis: Wert aus BGM+Z14 DE1004 der ORDERS — informational note, always applies
1142 ConditionResult::True
1143 }
1144
1145 /// [525] Hinweis: Wert aus BGM+Z24 DE1004 der ORDERS, mit der die Anforderung Allokationsliste erfolgt ist
1146 fn evaluate_525(&self, _ctx: &EvaluationContext) -> ConditionResult {
1147 // Hinweis: Wert aus BGM+Z24 DE1004 der ORDERS — informational note, always applies
1148 ConditionResult::True
1149 }
1150
1151 /// [526] Hinweis: Wert aus BGM+Z23 DE1004 der ORDERS, mit der die Anforderung bilanzierte Menge erfolgt ist
1152 fn evaluate_526(&self, _ctx: &EvaluationContext) -> ConditionResult {
1153 // Hinweis: Wert aus BGM+Z23 DE1004 der ORDERS — informational note, always applies
1154 ConditionResult::True
1155 }
1156
1157 /// [527] Hinweis: Wert aus BGM+Z34 DE1004 der ORDERS, mit der die Reklamation von Werten erfolgt ist.
1158 fn evaluate_527(&self, _ctx: &EvaluationContext) -> ConditionResult {
1159 // Hinweis: Wert aus BGM+Z34 DE1004 der ORDERS, mit der die Reklamation von Werten erfolgt ist. — informational note, always applies
1160 ConditionResult::True
1161 }
1162
1163 /// [529] Hinweis: Dokumentennummer aus BGM DE1004 der ORDERS
1164 fn evaluate_529(&self, _ctx: &EvaluationContext) -> ConditionResult {
1165 // Hinweis: Dokumentennummer aus BGM DE1004 der ORDERS — informational note, always applies
1166 ConditionResult::True
1167 }
1168
1169 /// [530] Hinweis: Dokumentennummer aus BGM DE1004 der ORDCHG
1170 fn evaluate_530(&self, _ctx: &EvaluationContext) -> ConditionResult {
1171 // Hinweis: Dokumentennummer aus BGM DE1004 der ORDCHG — informational note, always applies
1172 ConditionResult::True
1173 }
1174
1175 /// [533] Hinweis: Wert aus BGM+Z51 DE1004 der ORDCHG
1176 fn evaluate_533(&self, _ctx: &EvaluationContext) -> ConditionResult {
1177 // Hinweis: Wert aus BGM+Z51 DE1004 der ORDCHG — informational note, always applies
1178 ConditionResult::True
1179 }
1180
1181 /// [534] Hinweis: Wert aus BGM+Z52 DE1004 der ORDCHG
1182 fn evaluate_534(&self, _ctx: &EvaluationContext) -> ConditionResult {
1183 // Hinweis: Wert aus BGM+Z52 DE1004 der ORDCHG — informational note, always applies
1184 ConditionResult::True
1185 }
1186
1187 /// [535] Hinweis: Wert aus BGM+Z13 DE1004 der ORDERS, mit der die Ankündigung Gerätewechselabsicht erfolgt ist.
1188 fn evaluate_535(&self, _ctx: &EvaluationContext) -> ConditionResult {
1189 // Hinweis: Wert aus BGM+Z13 DE1004 der ORDERS — informational note, always applies
1190 ConditionResult::True
1191 }
1192
1193 /// [536] Hinweis: Es ist die MP-ID des Eigentümers (MSB) zur bilateralen Klärung anzugeben, wenn der angefragte MSB nicht selber der Eigentümer ist.
1194 fn evaluate_536(&self, _ctx: &EvaluationContext) -> ConditionResult {
1195 // Hinweis: MP-ID des Eigentümers (MSB) angeben — informational note, always applies
1196 ConditionResult::True
1197 }
1198
1199 /// [537] Hinweis: Wert aus BGM+Z72 DE1004 der ORDERS, mit der die Bestellung Beendigung der Konfiguration erfolgt ist.
1200 fn evaluate_537(&self, _ctx: &EvaluationContext) -> ConditionResult {
1201 // Hinweis: Wert aus BGM+Z72 DE1004 der ORDERS — informational note, always applies
1202 ConditionResult::True
1203 }
1204
1205 /// [538] Hinweis: Wert aus BGM+Z76 DE1004 der ORDERS, mit der die Reklamation der Konfiguration erfolgt ist.
1206 fn evaluate_538(&self, _ctx: &EvaluationContext) -> ConditionResult {
1207 // Hinweis: Wert aus BGM+Z76 DE1004 der ORDERS — informational note, always applies
1208 ConditionResult::True
1209 }
1210
1211 /// [539] Hinweis: Wert aus BGM+Z73/Z74 DE1004 der ORDERS, mit der die Bestellung der Konfiguration erfolgt ist.
1212 fn evaluate_539(&self, _ctx: &EvaluationContext) -> ConditionResult {
1213 // Hinweis: Wert aus BGM+Z73/Z74 DE1004 der ORDERS — informational note, always applies
1214 ConditionResult::True
1215 }
1216
1217 /// [540] Hinweis: Es darf nur eine Information im DE3148 übermittelt werden
1218 fn evaluate_540(&self, _ctx: &EvaluationContext) -> ConditionResult {
1219 // Hinweis: Es darf nur eine Information im DE3148 übermittelt werden — informational note, always applies
1220 ConditionResult::True
1221 }
1222
1223 /// [542] Hinweis: Wert aus BGM+Z91 DE1004 der ORDERS, mit der die Bestellung Änderung der Abrechnungsdaten erfolgt ist.
1224 fn evaluate_542(&self, _ctx: &EvaluationContext) -> ConditionResult {
1225 // Hinweis: Wert aus BGM+Z91 DE1004 der ORDERS — informational note about value origin, always applies
1226 ConditionResult::True
1227 }
1228
1229 /// [902] Format: Format: Möglicher Wert: ≥ 0
1230 // REVIEW: Format condition requiring numeric value >= 0. Applied to QTY segment value (elements[0][1]) by convention matching the example pattern. Medium confidence because the exact segment this applies to is not specified in the condition text, but QTY is the standard target for quantity format conditions. (medium confidence)
1231 fn evaluate_902(&self, ctx: &EvaluationContext) -> ConditionResult {
1232 ctx.format_check("QTY", 0, 1, |val| validate_numeric(val, ">=", 0.0))
1233 }
1234
1235 /// [903] Format: Möglicher Wert: 1
1236 // REVIEW: Format condition requiring the value to equal exactly 1. Applied to QTY segment value (elements[0][1]) by convention. Medium confidence as the exact target segment is not stated, but QTY quantity value is the standard target for this kind of format constraint. (medium confidence)
1237 fn evaluate_903(&self, ctx: &EvaluationContext) -> ConditionResult {
1238 ctx.format_check("QTY", 0, 1, |val| validate_numeric(val, "==", 1.0))
1239 }
1240
1241 /// [930] Format: max. 2 Nachkommastellen
1242 // REVIEW: Format condition requiring at most 2 decimal places. Applied to QTY segment value (elements[0][1]) following the standard pattern from example 19. Medium confidence as the exact target segment is not specified in the condition text, but QTY quantity value is the canonical target for decimal place constraints. (medium confidence)
1243 fn evaluate_930(&self, ctx: &EvaluationContext) -> ConditionResult {
1244 ctx.format_check("QTY", 0, 1, |val| validate_max_decimal_places(val, 2))
1245 }
1246
1247 /// [931] Format: ZZZ = +00
1248 fn evaluate_931(&self, ctx: &EvaluationContext) -> ConditionResult {
1249 ctx.format_check("DTM", 0, 1, validate_timezone_utc)
1250 }
1251
1252 /// [932] Format: HHMM = 2200
1253 fn evaluate_932(&self, ctx: &EvaluationContext) -> ConditionResult {
1254 ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "2200"))
1255 }
1256
1257 /// [933] Format: HHMM = 2300
1258 fn evaluate_933(&self, ctx: &EvaluationContext) -> ConditionResult {
1259 ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "2300"))
1260 }
1261
1262 /// [934] Format: HHMM = 0400
1263 fn evaluate_934(&self, ctx: &EvaluationContext) -> ConditionResult {
1264 ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "0400"))
1265 }
1266
1267 /// [935] Format: HHMM = 0500
1268 fn evaluate_935(&self, ctx: &EvaluationContext) -> ConditionResult {
1269 ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "0500"))
1270 }
1271
1272 /// [939] Format: Die Zeichenkette muss die Zeichen @ und . enthalten
1273 // REVIEW: Format condition checking that the string contains '@' and '.' — characteristic of an email address format requirement. Applied to COM segment with EM (Electronic Mail) qualifier where elements[0][0] is the address and elements[0][1] is the communication means type code. Returns Unknown when no COM+EM segment is found (condition not applicable). (medium confidence)
1274 fn evaluate_939(&self, ctx: &EvaluationContext) -> ConditionResult {
1275 // Format: string must contain '@' and '.' — email address format check
1276 // Applied to COM segment with EM (Electronic Mail) qualifier
1277 // COM+address:qualifier → elements[0] = ["address", "qualifier"]
1278 let com_segs = ctx.find_segments("COM");
1279 for seg in &com_segs {
1280 if let Some(elem0) = seg.elements.first() {
1281 if elem0.get(1).map(|q| q == "EM").unwrap_or(false) {
1282 let value = elem0.first().map(|s| s.as_str()).unwrap_or("");
1283 if value.is_empty() {
1284 return ConditionResult::Unknown;
1285 }
1286 return ConditionResult::from(value.contains('@') && value.contains('.'));
1287 }
1288 }
1289 }
1290 ConditionResult::Unknown
1291 }
1292
1293 /// [940] Format: Die Zeichenkette muss mit dem Zeichen + beginnen und danach dürfen nur noch Ziffern folgen
1294 // REVIEW: Format condition checking that the string starts with '+' and contains only digits afterwards — the international phone number format (e.g. +4912345678). Applied to COM segments with phone-type qualifiers (TE=Telephone, FX=Telefax, AH=After Hours). Returns Unknown when no COM segment with a phone qualifier is found. Requires at least one digit after '+' (len > 1) since a bare '+' is not a valid phone number. (medium confidence)
1295 fn evaluate_940(&self, ctx: &EvaluationContext) -> ConditionResult {
1296 // Format: string must start with '+' and be followed only by digits — international phone number format
1297 // Applied to COM segments with phone-type qualifiers: TE (Telephone), FX (Telefax), AH (After Hours)
1298 // COM+number:qualifier → elements[0] = ["number", "qualifier"]
1299 let com_segs = ctx.find_segments("COM");
1300 for seg in &com_segs {
1301 if let Some(elem0) = seg.elements.first() {
1302 let qualifier = elem0.get(1).map(|s| s.as_str()).unwrap_or("");
1303 if matches!(qualifier, "TE" | "FX" | "AH") {
1304 let value = elem0.first().map(|s| s.as_str()).unwrap_or("");
1305 if value.is_empty() {
1306 return ConditionResult::Unknown;
1307 }
1308 return ConditionResult::from(
1309 value.starts_with('+')
1310 && value.len() > 1
1311 && value[1..].chars().all(|c| c.is_ascii_digit()),
1312 );
1313 }
1314 }
1315 }
1316 ConditionResult::Unknown
1317 }
1318
1319 /// [2036] Pro Nachricht ist die SG27 genau einmal anzugeben
1320 // REVIEW: Cardinality condition requiring SG27 to appear exactly once per message. SG27 is the transaction group (tx_group) in ORDRSP FV2510. Uses the group navigator to count SG27 instances at the top level. Falls back to Unknown when no navigator is available (e.g., when context is used without a pre-assembled tree). This is a structural cardinality rule rather than a content condition. (medium confidence)
1321 fn evaluate_2036(&self, ctx: &EvaluationContext) -> ConditionResult {
1322 // SG27 must appear exactly once per message
1323 // SG27 is the transaction group (tx_group) in ORDRSP
1324 if let Some(nav) = ctx.navigator() {
1325 let count = nav.group_instance_count(&["SG27"]);
1326 ConditionResult::from(count == 1)
1327 } else {
1328 ConditionResult::Unknown
1329 }
1330 }
1331}