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        // Hinweis: Möglicher Wert: ZB4 oder ZB5 — informational note documenting permitted values
535        ConditionResult::True
536    }
537
538    /// [39] Möglicher Wert: E17 oder Z07
539    fn evaluate_39(&self, _ctx: &EvaluationContext) -> ConditionResult {
540        // Hinweis: Möglicher Wert: E17 oder Z07 — informational note documenting permitted values
541        ConditionResult::True
542    }
543
544    /// [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
545    /// EXTERNAL: Requires context from outside the message.
546    fn evaluate_40(&self, ctx: &EvaluationContext) -> ConditionResult {
547        ctx.external.evaluate("country_has_postal_code")
548    }
549
550    /// [41] wenn SG2 AJT (Einzelheiten zu einer Anpassung/Änderung) DE4465 mit Wert ZB5 vorhanden
551    fn evaluate_41(&self, ctx: &EvaluationContext) -> ConditionResult {
552        ctx.has_qualifier("AJT", 0, "ZB5")
553    }
554
555    /// [42] Wenn SG2 AJT+Z07 (Antwortkategorie: Ablehnung (Keine Berechtigung)) vorhanden
556    fn evaluate_42(&self, ctx: &EvaluationContext) -> ConditionResult {
557        ctx.has_qualifier("AJT", 0, "Z07")
558    }
559
560    /// [43] Wenn AJT+A02/A03+E_1001 vorhanden
561    fn evaluate_43(&self, ctx: &EvaluationContext) -> ConditionResult {
562        let ajts = ctx.find_segments("AJT");
563        let found = ajts.iter().any(|s| {
564            let code = s
565                .elements
566                .first()
567                .and_then(|e| e.first())
568                .map(|v| v.as_str());
569            let pos = s
570                .elements
571                .get(1)
572                .and_then(|e| e.first())
573                .map(|v| v.as_str());
574            matches!(code, Some("A02") | Some("A03")) && matches!(pos, Some("E_1001"))
575        });
576        ConditionResult::from(found)
577    }
578
579    /// [44] Wenn AJT+A05+E_1000 vorhanden
580    fn evaluate_44(&self, ctx: &EvaluationContext) -> ConditionResult {
581        let ajts = ctx.find_segments("AJT");
582        let found = ajts.iter().any(|s| {
583            let code = s
584                .elements
585                .first()
586                .and_then(|e| e.first())
587                .map(|v| v.as_str());
588            let pos = s
589                .elements
590                .get(1)
591                .and_then(|e| e.first())
592                .map(|v| v.as_str());
593            matches!(code, Some("A05")) && matches!(pos, Some("E_1000"))
594        });
595        ConditionResult::from(found)
596    }
597
598    /// [45] Wenn AJT+A09+E_1000 vorhanden
599    fn evaluate_45(&self, ctx: &EvaluationContext) -> ConditionResult {
600        let ajts = ctx.find_segments("AJT");
601        let found = ajts.iter().any(|s| {
602            let code = s
603                .elements
604                .first()
605                .and_then(|e| e.first())
606                .map(|v| v.as_str());
607            let pos = s
608                .elements
609                .get(1)
610                .and_then(|e| e.first())
611                .map(|v| v.as_str());
612            matches!(code, Some("A09")) && matches!(pos, Some("E_1000"))
613        });
614        ConditionResult::from(found)
615    }
616
617    /// [46] Wenn AJT+A06+E_0552 vorhanden
618    fn evaluate_46(&self, ctx: &EvaluationContext) -> ConditionResult {
619        let ajts = ctx.find_segments("AJT");
620        let found = ajts.iter().any(|s| {
621            let code = s
622                .elements
623                .first()
624                .and_then(|e| e.first())
625                .map(|v| v.as_str());
626            let pos = s
627                .elements
628                .get(1)
629                .and_then(|e| e.first())
630                .map(|v| v.as_str());
631            matches!(code, Some("A06")) && matches!(pos, Some("E_0552"))
632        });
633        ConditionResult::from(found)
634    }
635
636    /// [47] Wenn AJT+A06+E_0553 vorhanden
637    fn evaluate_47(&self, ctx: &EvaluationContext) -> ConditionResult {
638        let ajts = ctx.find_segments("AJT");
639        let found = ajts.iter().any(|s| {
640            let code = s
641                .elements
642                .first()
643                .and_then(|e| e.first())
644                .map(|v| v.as_str());
645            let pos = s
646                .elements
647                .get(1)
648                .and_then(|e| e.first())
649                .map(|v| v.as_str());
650            matches!(code, Some("A06")) && matches!(pos, Some("E_0553"))
651        });
652        ConditionResult::from(found)
653    }
654
655    /// [48] Wenn AJT+A06+E_0554 vorhanden
656    fn evaluate_48(&self, ctx: &EvaluationContext) -> ConditionResult {
657        let ajts = ctx.find_segments("AJT");
658        let found = ajts.iter().any(|s| {
659            let code = s
660                .elements
661                .first()
662                .and_then(|e| e.first())
663                .map(|v| v.as_str());
664            let pos = s
665                .elements
666                .get(1)
667                .and_then(|e| e.first())
668                .map(|v| v.as_str());
669            matches!(code, Some("A06")) && matches!(pos, Some("E_0554"))
670        });
671        ConditionResult::from(found)
672    }
673
674    /// [49] nur, wenn in ursprünglicher Nachricht IMD++Z60 (Abbestellung Messprodukt mit Zählzeitdefinition des LF) vorhanden war
675    /// EXTERNAL: Requires context from outside the message.
676    fn evaluate_49(&self, ctx: &EvaluationContext) -> ConditionResult {
677        ctx.external.evaluate("original_order_had_imd_z60")
678    }
679
680    /// [50] wenn im DE3155 in demselben COM der Code EM vorhanden ist
681    fn evaluate_50(&self, ctx: &EvaluationContext) -> ConditionResult {
682        let coms = ctx.find_segments("COM");
683        ConditionResult::from(coms.iter().any(|s| {
684            s.elements
685                .first()
686                .and_then(|e| e.get(1))
687                .map(|v| v == "EM")
688                .unwrap_or(false)
689        }))
690    }
691
692    /// [51] wenn im DE3155 in demselben COM der Code TE / FX / AJ / AL vorhanden ist
693    fn evaluate_51(&self, ctx: &EvaluationContext) -> ConditionResult {
694        let coms = ctx.find_segments("COM");
695        ConditionResult::from(coms.iter().any(|s| {
696            matches!(
697                s.elements
698                    .first()
699                    .and_then(|e| e.get(1))
700                    .map(|v| v.as_str()),
701                Some("TE") | Some("FX") | Some("AJ") | Some("AL")
702            )
703        }))
704    }
705
706    /// [53] Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z59
707    fn evaluate_53(&self, _ctx: &EvaluationContext) -> ConditionResult {
708        // Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z59 — informational note about value origin, always applies
709        ConditionResult::True
710    }
711
712    /// [54] Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z80
713    fn evaluate_54(&self, _ctx: &EvaluationContext) -> ConditionResult {
714        // Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z80 — informational note about value origin, always applies
715        ConditionResult::True
716    }
717
718    /// [55] Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z81
719    fn evaluate_55(&self, _ctx: &EvaluationContext) -> ConditionResult {
720        // Hinweis: Vorgangsnummer aus IDE DE7402 der UTILTS mit BGM+Z81 — informational note about value origin, always applies
721        ConditionResult::True
722    }
723
724    /// [56] wenn SG2 AJT+A02/A03/A06/A07/A10/A11+E_0548 vorhanden
725    fn evaluate_56(&self, ctx: &EvaluationContext) -> ConditionResult {
726        let ajts = ctx.find_segments("AJT");
727        ConditionResult::from(ajts.iter().any(|s| {
728            let de4465 = s
729                .elements
730                .first()
731                .and_then(|e| e.first())
732                .map(|s| s.as_str());
733            let de1082 = s
734                .elements
735                .get(1)
736                .and_then(|e| e.first())
737                .map(|s| s.as_str());
738            matches!(
739                de4465,
740                Some("A02") | Some("A03") | Some("A06") | Some("A07") | Some("A10") | Some("A11")
741            ) && de1082 == Some("E_0548")
742        }))
743    }
744
745    /// [57] wenn SG2 AJT+A02/A03/A06/A07/A10/A11+E_0549 vorhanden
746    fn evaluate_57(&self, ctx: &EvaluationContext) -> ConditionResult {
747        let ajts = ctx.find_segments("AJT");
748        ConditionResult::from(ajts.iter().any(|s| {
749            let de4465 = s
750                .elements
751                .first()
752                .and_then(|e| e.first())
753                .map(|s| s.as_str());
754            let de1082 = s
755                .elements
756                .get(1)
757                .and_then(|e| e.first())
758                .map(|s| s.as_str());
759            matches!(
760                de4465,
761                Some("A02") | Some("A03") | Some("A06") | Some("A07") | Some("A10") | Some("A11")
762            ) && de1082 == Some("E_0549")
763        }))
764    }
765
766    /// [58] wenn SG2 AJT+A02/A03/A06/A07+E_0550 vorhanden
767    fn evaluate_58(&self, ctx: &EvaluationContext) -> ConditionResult {
768        let ajts = ctx.find_segments("AJT");
769        ConditionResult::from(ajts.iter().any(|s| {
770            let de4465 = s
771                .elements
772                .first()
773                .and_then(|e| e.first())
774                .map(|s| s.as_str());
775            let de1082 = s
776                .elements
777                .get(1)
778                .and_then(|e| e.first())
779                .map(|s| s.as_str());
780            matches!(
781                de4465,
782                Some("A02") | Some("A03") | Some("A06") | Some("A07")
783            ) && de1082 == Some("E_0550")
784        }))
785    }
786
787    /// [59] wenn SG2 AJT+A02/A03/A06/A07/A10/A11+E_0551 vorhanden
788    fn evaluate_59(&self, ctx: &EvaluationContext) -> ConditionResult {
789        let ajts = ctx.find_segments("AJT");
790        ConditionResult::from(ajts.iter().any(|s| {
791            let de4465 = s
792                .elements
793                .first()
794                .and_then(|e| e.first())
795                .map(|s| s.as_str());
796            let de1082 = s
797                .elements
798                .get(1)
799                .and_then(|e| e.first())
800                .map(|s| s.as_str());
801            matches!(
802                de4465,
803                Some("A02") | Some("A03") | Some("A06") | Some("A07") | Some("A10") | Some("A11")
804            ) && de1082 == Some("E_0551")
805        }))
806    }
807
808    /// [61] wenn es sich bei der Reklamation um die Reklamation der Übersicht der Schaltzeitdefinitionen handelte
809    // 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)
810    fn evaluate_61(&self, ctx: &EvaluationContext) -> ConditionResult {
811        // Reklamation der Übersicht der Schaltzeitdefinitionen → ORDRSP with BGM+Z60
812        ctx.has_qualifier("BGM", 0, "Z60")
813    }
814
815    /// [62] wenn es sich bei der Reklamation um die Reklamation der Übersicht der Leistungskurvendefinitionen handelte
816    // 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)
817    fn evaluate_62(&self, ctx: &EvaluationContext) -> ConditionResult {
818        // Reklamation der Übersicht der Leistungskurvendefinitionen → BGM+Z78 or BGM+Z79
819        let bgm_segs = ctx.find_segments("BGM");
820        match bgm_segs.first() {
821            Some(s) => {
822                let code = s
823                    .elements
824                    .first()
825                    .and_then(|e| e.first())
826                    .map(|v| v.as_str());
827                ConditionResult::from(matches!(code, Some("Z78") | Some("Z79")))
828            }
829            None => ConditionResult::False, // segment absent → condition not applicable
830        }
831    }
832
833    /// [63] Dokumentennummer aus BGM+Z60 DE1004 der UTILTS
834    fn evaluate_63(&self, _ctx: &EvaluationContext) -> ConditionResult {
835        // Hinweis: Dokumentennummer aus BGM+Z60 DE1004 der UTILTS — informational note, always applies
836        ConditionResult::True
837    }
838
839    /// [64] Dokumentennummer aus BGM+Z78 DE1004 der UTILTS
840    fn evaluate_64(&self, _ctx: &EvaluationContext) -> ConditionResult {
841        // Hinweis: Dokumentennummer aus BGM+Z78 DE1004 der UTILTS — informational note, always applies
842        ConditionResult::True
843    }
844
845    /// [65] Dokumentennummer aus BGM+Z79 DE1004 der UTILTS
846    fn evaluate_65(&self, _ctx: &EvaluationContext) -> ConditionResult {
847        // Hinweis: Dokumentennummer aus BGM+Z79 DE1004 der UTILTS — informational note, always applies
848        ConditionResult::True
849    }
850
851    /// [66] wenn SG2 AJT+A01/A02/A03+E_0544 vorhanden
852    fn evaluate_66(&self, ctx: &EvaluationContext) -> ConditionResult {
853        let ajts = ctx.find_segments("AJT");
854        ConditionResult::from(ajts.iter().any(|s| {
855            let de4465 = s
856                .elements
857                .first()
858                .and_then(|e| e.first())
859                .map(|s| s.as_str());
860            let de1082 = s
861                .elements
862                .get(1)
863                .and_then(|e| e.first())
864                .map(|s| s.as_str());
865            matches!(de4465, Some("A01") | Some("A02") | Some("A03")) && de1082 == Some("E_0544")
866        }))
867    }
868
869    /// [67] wenn SG2 AJT+A01/A02/A03+E_0545 vorhanden
870    fn evaluate_67(&self, ctx: &EvaluationContext) -> ConditionResult {
871        let ajts = ctx.find_segments("AJT");
872        ConditionResult::from(ajts.iter().any(|s| {
873            let de4465 = s
874                .elements
875                .first()
876                .and_then(|e| e.first())
877                .map(|s| s.as_str());
878            let de1082 = s
879                .elements
880                .get(1)
881                .and_then(|e| e.first())
882                .map(|s| s.as_str());
883            matches!(de4465, Some("A01") | Some("A02") | Some("A03")) && de1082 == Some("E_0545")
884        }))
885    }
886
887    /// [68] wenn SG2 AJT+A02/A03+E_0546 vorhanden
888    fn evaluate_68(&self, ctx: &EvaluationContext) -> ConditionResult {
889        let ajts = ctx.find_segments("AJT");
890        ConditionResult::from(ajts.iter().any(|s| {
891            let de4465 = s
892                .elements
893                .first()
894                .and_then(|e| e.first())
895                .map(|s| s.as_str());
896            let de1082 = s
897                .elements
898                .get(1)
899                .and_then(|e| e.first())
900                .map(|s| s.as_str());
901            matches!(de4465, Some("A02") | Some("A03")) && de1082 == Some("E_0546")
902        }))
903    }
904
905    /// [69] wenn SG2 AJT+A01/A02/A03+E_0547 vorhanden
906    fn evaluate_69(&self, ctx: &EvaluationContext) -> ConditionResult {
907        let ajts = ctx.find_segments("AJT");
908        ConditionResult::from(ajts.iter().any(|s| {
909            let de4465 = s
910                .elements
911                .first()
912                .and_then(|e| e.first())
913                .map(|s| s.as_str());
914            let de1082 = s
915                .elements
916                .get(1)
917                .and_then(|e| e.first())
918                .map(|s| s.as_str());
919            matches!(de4465, Some("A01") | Some("A02") | Some("A03")) && de1082 == Some("E_0547")
920        }))
921    }
922
923    /// [72] wenn AJT+A04+E_0552 vorhanden
924    fn evaluate_72(&self, ctx: &EvaluationContext) -> ConditionResult {
925        ctx.has_qualified_value("AJT", 0, "A04", 1, 0, &["E_0552"])
926    }
927
928    /// [73] wenn AJT+A04+E_0553 vorhanden
929    fn evaluate_73(&self, ctx: &EvaluationContext) -> ConditionResult {
930        ctx.has_qualified_value("AJT", 0, "A04", 1, 0, &["E_0553"])
931    }
932
933    /// [74] wenn AJT+A04+E_0554 vorhanden
934    fn evaluate_74(&self, ctx: &EvaluationContext) -> ConditionResult {
935        ctx.has_qualified_value("AJT", 0, "A04", 1, 0, &["E_0554"])
936    }
937
938    /// [76] Wenn FTX+Z27 (IP-Adresse des Absenders) nicht vorhanden
939    fn evaluate_76(&self, ctx: &EvaluationContext) -> ConditionResult {
940        ctx.lacks_qualifier("FTX", 0, "Z27")
941    }
942
943    /// [77] Wenn FTX+Z28 (IP-Range des Absenders) nicht vorhanden
944    fn evaluate_77(&self, ctx: &EvaluationContext) -> ConditionResult {
945        ctx.lacks_qualifier("FTX", 0, "Z28")
946    }
947
948    /// [492] wenn MP-ID in NAD+MR aus Sparte Strom
949    /// EXTERNAL: Requires context from outside the message.
950    fn evaluate_492(&self, ctx: &EvaluationContext) -> ConditionResult {
951        ctx.external.evaluate("recipient_is_strom")
952    }
953
954    /// [493] wenn MP-ID in NAD+MR aus Sparte Gas
955    /// EXTERNAL: Requires context from outside the message.
956    fn evaluate_493(&self, ctx: &EvaluationContext) -> ConditionResult {
957        ctx.external.evaluate("recipient_is_gas")
958    }
959
960    /// [494] Das hier genannte Datum muss der Zeitpunkt sein, zu dem das Dokument erstellt wurde, oder ein Zeitpunkt, der davor liegt.
961    // 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)
962    fn evaluate_494(&self, _ctx: &EvaluationContext) -> ConditionResult {
963        ConditionResult::True
964    }
965
966    /// [500] Hinweis: Angabe eines technischen Ansprechpartners für die Geräteübernahme
967    fn evaluate_500(&self, _ctx: &EvaluationContext) -> ConditionResult {
968        ConditionResult::True
969    }
970
971    /// [503] Hinweis: Datum, bis zu dem der MSBA zur Fortführung verpflichtet wurde
972    fn evaluate_503(&self, _ctx: &EvaluationContext) -> ConditionResult {
973        ConditionResult::True
974    }
975
976    /// [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...
977    fn evaluate_504(&self, _ctx: &EvaluationContext) -> ConditionResult {
978        // 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.
979        ConditionResult::True
980    }
981
982    /// [513] Hinweis: Wert aus BGM+Z12 DE1004 der ORDERS, mit der die Bestellung erfolgt ist.
983    fn evaluate_513(&self, _ctx: &EvaluationContext) -> ConditionResult {
984        // Hinweis: Wert aus BGM+Z12 DE1004 der ORDERS, mit der die Bestellung erfolgt ist.
985        ConditionResult::True
986    }
987
988    /// [518] Hinweis: Wert aus BGM+Z10 DE1004 der ORDERS, mit der die Bestellung erfolgt ist
989    fn evaluate_518(&self, _ctx: &EvaluationContext) -> ConditionResult {
990        // Hinweis: Wert aus BGM+Z10 DE1004 der ORDERS, mit der die Bestellung erfolgt ist.
991        ConditionResult::True
992    }
993
994    /// [519] Hinweis: Wert aus BGM+7 DE1004 der ORDERS, mit der die Bestellung erfolgt ist.
995    fn evaluate_519(&self, _ctx: &EvaluationContext) -> ConditionResult {
996        // Hinweis: Wert aus BGM+7 DE1004 der ORDERS, mit der die Bestellung erfolgt ist.
997        ConditionResult::True
998    }
999
1000    /// [520] Hinweis: Wert aus BGM+Z29 DE1004 der ORDERS, mit der die Anfrage zur Beendigung der Rechnungsabwicklung erfolgt ist.
1001    fn evaluate_520(&self, _ctx: &EvaluationContext) -> ConditionResult {
1002        // Hinweis: Wert aus BGM+Z29 DE1004 der ORDERS, mit der die Anfrage zur Beendigung der Rechnungsabwicklung erfolgt ist.
1003        ConditionResult::True
1004    }
1005
1006    /// [521] Hinweis: Wert aus BGM+Z14/Z61/Z62 DE1004 der ORDERS, mit der die Anforderung von Stammdaten erfolgt ist
1007    fn evaluate_521(&self, _ctx: &EvaluationContext) -> ConditionResult {
1008        // Hinweis: Wert aus BGM+Z14/Z61/Z62 DE1004 der ORDERS, mit der die Anforderung von Stammdaten erfolgt ist
1009        // Informational note — documents that the BGM DE1004 value originates from the original ORDERS request.
1010        ConditionResult::True
1011    }
1012
1013    /// [522] Hinweis: Wert aus BGM+7/Z28/Z48 DE1004 der ORDERS, mit der die Anforderung von Werten erfolgt ist.
1014    fn evaluate_522(&self, _ctx: &EvaluationContext) -> ConditionResult {
1015        // Hinweis: Wert aus BGM+7/Z28/Z48 DE1004 der ORDERS — informational note, always applies
1016        ConditionResult::True
1017    }
1018
1019    /// [523] Hinweis: Wert aus BGM+7 DE1004 der ORDERS, mit der die Anforderung Anforderung von Brennwert und Zustandszahl erfolgt ist.
1020    fn evaluate_523(&self, _ctx: &EvaluationContext) -> ConditionResult {
1021        // Hinweis: Wert aus BGM+7 DE1004 der ORDERS — informational note, always applies
1022        ConditionResult::True
1023    }
1024
1025    /// [524] Hinweis: Wert aus BGM+Z14 DE1004 der ORDERS, mit der die Anfrage vom MSB Gas erfolgt ist.
1026    fn evaluate_524(&self, _ctx: &EvaluationContext) -> ConditionResult {
1027        // Hinweis: Wert aus BGM+Z14 DE1004 der ORDERS — informational note, always applies
1028        ConditionResult::True
1029    }
1030
1031    /// [525] Hinweis: Wert aus BGM+Z24 DE1004 der ORDERS, mit der die Anforderung Allokationsliste erfolgt ist
1032    fn evaluate_525(&self, _ctx: &EvaluationContext) -> ConditionResult {
1033        // Hinweis: Wert aus BGM+Z24 DE1004 der ORDERS — informational note, always applies
1034        ConditionResult::True
1035    }
1036
1037    /// [526] Hinweis: Wert aus BGM+Z23 DE1004 der ORDERS, mit der die Anforderung bilanzierte Menge erfolgt ist
1038    fn evaluate_526(&self, _ctx: &EvaluationContext) -> ConditionResult {
1039        // Hinweis: Wert aus BGM+Z23 DE1004 der ORDERS — informational note, always applies
1040        ConditionResult::True
1041    }
1042
1043    /// [527] Hinweis: Wert aus BGM+Z34 DE1004 der ORDERS, mit der die Reklamation von Werten erfolgt ist.
1044    fn evaluate_527(&self, _ctx: &EvaluationContext) -> ConditionResult {
1045        // Hinweis: Wert aus BGM+Z34 DE1004 der ORDERS, mit der die Reklamation von Werten erfolgt ist. — informational note, always applies
1046        ConditionResult::True
1047    }
1048
1049    /// [529] Hinweis: Dokumentennummer aus BGM DE1004 der ORDERS
1050    fn evaluate_529(&self, _ctx: &EvaluationContext) -> ConditionResult {
1051        // Hinweis: Dokumentennummer aus BGM DE1004 der ORDERS — informational note, always applies
1052        ConditionResult::True
1053    }
1054
1055    /// [530] Hinweis: Dokumentennummer aus BGM DE1004 der ORDCHG
1056    fn evaluate_530(&self, _ctx: &EvaluationContext) -> ConditionResult {
1057        // Hinweis: Dokumentennummer aus BGM DE1004 der ORDCHG — informational note, always applies
1058        ConditionResult::True
1059    }
1060
1061    /// [533] Hinweis: Wert aus BGM+Z51 DE1004 der ORDCHG
1062    fn evaluate_533(&self, _ctx: &EvaluationContext) -> ConditionResult {
1063        // Hinweis: Wert aus BGM+Z51 DE1004 der ORDCHG — informational note, always applies
1064        ConditionResult::True
1065    }
1066
1067    /// [534] Hinweis: Wert aus BGM+Z52 DE1004 der ORDCHG
1068    fn evaluate_534(&self, _ctx: &EvaluationContext) -> ConditionResult {
1069        // Hinweis: Wert aus BGM+Z52 DE1004 der ORDCHG — informational note, always applies
1070        ConditionResult::True
1071    }
1072
1073    /// [535] Hinweis: Wert aus BGM+Z13 DE1004 der ORDERS, mit der die Ankündigung Gerätewechselabsicht erfolgt ist.
1074    fn evaluate_535(&self, _ctx: &EvaluationContext) -> ConditionResult {
1075        // Hinweis: Wert aus BGM+Z13 DE1004 der ORDERS — informational note, always applies
1076        ConditionResult::True
1077    }
1078
1079    /// [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.
1080    fn evaluate_536(&self, _ctx: &EvaluationContext) -> ConditionResult {
1081        // Hinweis: MP-ID des Eigentümers (MSB) angeben — informational note, always applies
1082        ConditionResult::True
1083    }
1084
1085    /// [537] Hinweis: Wert aus BGM+Z72 DE1004 der ORDERS, mit der die Bestellung Beendigung der Konfiguration erfolgt ist.
1086    fn evaluate_537(&self, _ctx: &EvaluationContext) -> ConditionResult {
1087        // Hinweis: Wert aus BGM+Z72 DE1004 der ORDERS — informational note, always applies
1088        ConditionResult::True
1089    }
1090
1091    /// [538] Hinweis: Wert aus BGM+Z76 DE1004 der ORDERS, mit der die Reklamation der Konfiguration erfolgt ist.
1092    fn evaluate_538(&self, _ctx: &EvaluationContext) -> ConditionResult {
1093        // Hinweis: Wert aus BGM+Z76 DE1004 der ORDERS — informational note, always applies
1094        ConditionResult::True
1095    }
1096
1097    /// [539] Hinweis: Wert aus BGM+Z73/Z74 DE1004 der ORDERS, mit der die Bestellung der Konfiguration erfolgt ist.
1098    fn evaluate_539(&self, _ctx: &EvaluationContext) -> ConditionResult {
1099        // Hinweis: Wert aus BGM+Z73/Z74 DE1004 der ORDERS — informational note, always applies
1100        ConditionResult::True
1101    }
1102
1103    /// [540] Hinweis: Es darf nur eine Information im DE3148 übermittelt werden
1104    fn evaluate_540(&self, _ctx: &EvaluationContext) -> ConditionResult {
1105        // Hinweis: Es darf nur eine Information im DE3148 übermittelt werden — informational note, always applies
1106        ConditionResult::True
1107    }
1108
1109    /// [542] Hinweis: Wert aus BGM+Z91 DE1004 der ORDERS, mit der die Bestellung Änderung der Abrechnungsdaten erfolgt ist.
1110    fn evaluate_542(&self, _ctx: &EvaluationContext) -> ConditionResult {
1111        // Hinweis: Wert aus BGM+Z91 DE1004 der ORDERS — informational note about value origin, always applies
1112        ConditionResult::True
1113    }
1114
1115    /// [902] Format: Format: Möglicher Wert: ≥ 0
1116    // 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)
1117    fn evaluate_902(&self, ctx: &EvaluationContext) -> ConditionResult {
1118        ctx.format_check("QTY", 0, 1, |val| validate_numeric(val, ">=", 0.0))
1119    }
1120
1121    /// [903] Format: Möglicher Wert: 1
1122    // 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)
1123    fn evaluate_903(&self, ctx: &EvaluationContext) -> ConditionResult {
1124        ctx.format_check("QTY", 0, 1, |val| validate_numeric(val, "==", 1.0))
1125    }
1126
1127    /// [930] Format: max. 2 Nachkommastellen
1128    // 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)
1129    fn evaluate_930(&self, ctx: &EvaluationContext) -> ConditionResult {
1130        ctx.format_check("QTY", 0, 1, |val| validate_max_decimal_places(val, 2))
1131    }
1132
1133    /// [931] Format: ZZZ = +00
1134    fn evaluate_931(&self, ctx: &EvaluationContext) -> ConditionResult {
1135        ctx.format_check("DTM", 0, 1, validate_timezone_utc)
1136    }
1137
1138    /// [932] Format: HHMM = 2200
1139    fn evaluate_932(&self, ctx: &EvaluationContext) -> ConditionResult {
1140        ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "2200"))
1141    }
1142
1143    /// [933] Format: HHMM = 2300
1144    fn evaluate_933(&self, ctx: &EvaluationContext) -> ConditionResult {
1145        ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "2300"))
1146    }
1147
1148    /// [934] Format: HHMM = 0400
1149    fn evaluate_934(&self, ctx: &EvaluationContext) -> ConditionResult {
1150        ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "0400"))
1151    }
1152
1153    /// [935] Format: HHMM = 0500
1154    fn evaluate_935(&self, ctx: &EvaluationContext) -> ConditionResult {
1155        ctx.format_check("DTM", 0, 1, |val| validate_hhmm_equals(val, "0500"))
1156    }
1157
1158    /// [939] Format: Die Zeichenkette muss die Zeichen @ und . enthalten
1159    // 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)
1160    fn evaluate_939(&self, ctx: &EvaluationContext) -> ConditionResult {
1161        // Format: string must contain '@' and '.' — email address format check
1162        // Applied to COM segment with EM (Electronic Mail) qualifier
1163        // COM+address:qualifier → elements[0] = ["address", "qualifier"]
1164        let com_segs = ctx.find_segments("COM");
1165        for seg in &com_segs {
1166            if let Some(elem0) = seg.elements.first() {
1167                if elem0.get(1).map(|q| q == "EM").unwrap_or(false) {
1168                    let value = elem0.first().map(|s| s.as_str()).unwrap_or("");
1169                    if value.is_empty() {
1170                        return ConditionResult::Unknown;
1171                    }
1172                    return ConditionResult::from(value.contains('@') && value.contains('.'));
1173                }
1174            }
1175        }
1176        ConditionResult::Unknown
1177    }
1178
1179    /// [940] Format: Die Zeichenkette muss mit dem Zeichen + beginnen und danach dürfen nur noch Ziffern folgen
1180    // 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)
1181    fn evaluate_940(&self, ctx: &EvaluationContext) -> ConditionResult {
1182        // Format: string must start with '+' and be followed only by digits — international phone number format
1183        // Applied to COM segments with phone-type qualifiers: TE (Telephone), FX (Telefax), AH (After Hours)
1184        // COM+number:qualifier → elements[0] = ["number", "qualifier"]
1185        let com_segs = ctx.find_segments("COM");
1186        for seg in &com_segs {
1187            if let Some(elem0) = seg.elements.first() {
1188                let qualifier = elem0.get(1).map(|s| s.as_str()).unwrap_or("");
1189                if matches!(qualifier, "TE" | "FX" | "AH") {
1190                    let value = elem0.first().map(|s| s.as_str()).unwrap_or("");
1191                    if value.is_empty() {
1192                        return ConditionResult::Unknown;
1193                    }
1194                    return ConditionResult::from(
1195                        value.starts_with('+')
1196                            && value.len() > 1
1197                            && value[1..].chars().all(|c| c.is_ascii_digit()),
1198                    );
1199                }
1200            }
1201        }
1202        ConditionResult::Unknown
1203    }
1204
1205    /// [2036] Pro Nachricht ist die SG27 genau einmal anzugeben
1206    // 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)
1207    fn evaluate_2036(&self, ctx: &EvaluationContext) -> ConditionResult {
1208        // SG27 must appear exactly once per message
1209        // SG27 is the transaction group (tx_group) in ORDRSP
1210        if let Some(nav) = ctx.navigator() {
1211            let count = nav.group_instance_count(&["SG27"]);
1212            ConditionResult::from(count == 1)
1213        } else {
1214            ConditionResult::Unknown
1215        }
1216    }
1217}