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