Skip to main content

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}