Skip to main content

automapper_validation/generated/fv2504/
ordrsp_conditions_fv2504.rs

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