Skip to main content

automapper_validation/generated/fv2504/
comdis_conditions_fv2504.rs

1// <auto-generated>
2// Generated by automapper-generator generate-conditions
3// AHB: xml-migs-and-ahbs/FV2504/COMDIS_AHB_1_0f_außerordentliche_20250131.xml
4// Generated: 2026-03-12T07:43:10Z
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::{ConditionEvaluator, ConditionResult, EvaluationContext};
15use mig_types::segment::OwnedSegment;
16
17/// Generated condition evaluator for COMDIS FV2504.
18pub struct ComdisConditionEvaluatorFV2504 {
19    // External condition IDs that require runtime context.
20    external_conditions: std::collections::HashSet<u32>,
21}
22
23impl Default for ComdisConditionEvaluatorFV2504 {
24    fn default() -> Self {
25        let mut external_conditions = std::collections::HashSet::new();
26        external_conditions.insert(3);
27        external_conditions.insert(23);
28        external_conditions.insert(24);
29        external_conditions.insert(25);
30        external_conditions.insert(26);
31        external_conditions.insert(27);
32        external_conditions.insert(28);
33        external_conditions.insert(29);
34        external_conditions.insert(30);
35        external_conditions.insert(492);
36        external_conditions.insert(493);
37        Self {
38            external_conditions,
39        }
40    }
41}
42
43impl ConditionEvaluator for ComdisConditionEvaluatorFV2504 {
44    fn message_type(&self) -> &str {
45        "COMDIS"
46    }
47
48    fn format_version(&self) -> &str {
49        "FV2504"
50    }
51
52    fn evaluate(&self, condition: u32, ctx: &EvaluationContext) -> ConditionResult {
53        match condition {
54            1 => self.evaluate_1(ctx),
55            2 => self.evaluate_2(ctx),
56            3 => self.evaluate_3(ctx),
57            4 => self.evaluate_4(ctx),
58            5 => self.evaluate_5(ctx),
59            6 => self.evaluate_6(ctx),
60            7 => self.evaluate_7(ctx),
61            8 => self.evaluate_8(ctx),
62            9 => self.evaluate_9(ctx),
63            10 => self.evaluate_10(ctx),
64            11 => self.evaluate_11(ctx),
65            12 => self.evaluate_12(ctx),
66            13 => self.evaluate_13(ctx),
67            14 => self.evaluate_14(ctx),
68            15 => self.evaluate_15(ctx),
69            16 => self.evaluate_16(ctx),
70            17 => self.evaluate_17(ctx),
71            18 => self.evaluate_18(ctx),
72            19 => self.evaluate_19(ctx),
73            20 => self.evaluate_20(ctx),
74            21 => self.evaluate_21(ctx),
75            22 => self.evaluate_22(ctx),
76            23 => self.evaluate_23(ctx),
77            24 => self.evaluate_24(ctx),
78            25 => self.evaluate_25(ctx),
79            26 => self.evaluate_26(ctx),
80            27 => self.evaluate_27(ctx),
81            28 => self.evaluate_28(ctx),
82            29 => self.evaluate_29(ctx),
83            30 => self.evaluate_30(ctx),
84            492 => self.evaluate_492(ctx),
85            493 => self.evaluate_493(ctx),
86            505 => self.evaluate_505(ctx),
87            506 => self.evaluate_506(ctx),
88            508 => self.evaluate_508(ctx),
89            509 => self.evaluate_509(ctx),
90            510 => self.evaluate_510(ctx),
91            930 => self.evaluate_930(ctx),
92            931 => self.evaluate_931(ctx),
93            939 => self.evaluate_939(ctx),
94            940 => self.evaluate_940(ctx),
95            _ => ConditionResult::Unknown,
96        }
97    }
98
99    fn is_external(&self, condition: u32) -> bool {
100        self.external_conditions.contains(&condition)
101    }
102    fn is_known(&self, condition: u32) -> bool {
103        matches!(
104            condition,
105            1 | 2
106                | 3
107                | 4
108                | 5
109                | 6
110                | 7
111                | 8
112                | 9
113                | 10
114                | 11
115                | 12
116                | 13
117                | 14
118                | 15
119                | 16
120                | 17
121                | 18
122                | 19
123                | 20
124                | 21
125                | 22
126                | 23
127                | 24
128                | 25
129                | 26
130                | 27
131                | 28
132                | 29
133                | 30
134                | 492
135                | 493
136                | 505
137                | 506
138                | 508
139                | 509
140                | 510
141                | 930
142                | 931
143                | 939
144                | 940
145        )
146    }
147}
148
149impl ComdisConditionEvaluatorFV2504 {
150    /// [23] Wenn MP-ID in NAD+MS (Nachrichtensender) mit Rolle MSB vorhanden
151    /// EXTERNAL: Requires context from outside the message.
152    fn evaluate_23(&self, ctx: &EvaluationContext) -> ConditionResult {
153        ctx.external.evaluate("sender_is_msb")
154    }
155
156    /// [24] Wenn MP-ID in NAD+MR (Nachrichtenempfänger) mit Rolle ESA vorhanden
157    /// EXTERNAL: Requires context from outside the message.
158    fn evaluate_24(&self, ctx: &EvaluationContext) -> ConditionResult {
159        ctx.external.evaluate("recipient_is_esa")
160    }
161
162    /// [25] Wenn MP-ID in NAD+MR (Nachrichtenempfänger) mit Rolle LF vorhanden
163    /// EXTERNAL: Requires context from outside the message.
164    fn evaluate_25(&self, ctx: &EvaluationContext) -> ConditionResult {
165        ctx.external.evaluate("recipient_is_lf")
166    }
167
168    /// [26] Wenn MP-ID in NAD+MR (Nachrichtenempfänger) mit Rolle NB vorhanden
169    /// EXTERNAL: Requires context from outside the message.
170    fn evaluate_26(&self, ctx: &EvaluationContext) -> ConditionResult {
171        ctx.external.evaluate("recipient_is_nb")
172    }
173
174    /// [27] Wenn MP-ID in NAD+MS (Nachrichtensender) mit Rolle NB vorhanden
175    /// EXTERNAL: Requires context from outside the message.
176    fn evaluate_27(&self, ctx: &EvaluationContext) -> ConditionResult {
177        ctx.external.evaluate("sender_is_nb")
178    }
179
180    /// [1] wenn SG3 AJT+Z61+S_0109 oder SG3 AJT+Z62+S_0109 vorhanden.
181    fn evaluate_1(&self, ctx: &EvaluationContext) -> ConditionResult {
182        sg3_ajt(ctx, &["Z61", "Z62"], &["S_0109"])
183    }
184
185    /// [2] wenn SG3 AJT+Z58+S_0109 oder SG3 AJT+Z59+S_0109 oder SG3 AJT+Z60+S_0109 vorhanden.
186    fn evaluate_2(&self, ctx: &EvaluationContext) -> ConditionResult {
187        sg3_ajt(ctx, &["Z58", "Z59", "Z60"], &["S_0109"])
188    }
189
190    /// [3] Nur MP-ID aus Sparte Strom
191    /// EXTERNAL: Requires context from outside the message.
192    fn evaluate_3(&self, ctx: &EvaluationContext) -> ConditionResult {
193        ctx.external.evaluate("mp_id_from_electricity_sector")
194    }
195
196    /// [4] wenn SG3 AJT+Z58/Z59/Z60/Z61/Z62+S_0109 vorhanden
197    fn evaluate_4(&self, ctx: &EvaluationContext) -> ConditionResult {
198        sg3_ajt(ctx, &["Z58", "Z59", "Z60", "Z61", "Z62"], &["S_0109"])
199    }
200
201    /// [5] wenn SG3 AJT+A01/A02/A03/A04/A06/A07/A09/A12/A15+E_0504 vorhanden
202    fn evaluate_5(&self, ctx: &EvaluationContext) -> ConditionResult {
203        sg3_ajt(
204            ctx,
205            &[
206                "A01", "A02", "A03", "A04", "A06", "A07", "A09", "A12", "A15",
207            ],
208            &["E_0504"],
209        )
210    }
211
212    /// [6] wenn SG3 AJT+A07+E_0504 vorhanden
213    fn evaluate_6(&self, ctx: &EvaluationContext) -> ConditionResult {
214        sg3_ajt(ctx, &["A07"], &["E_0504"])
215    }
216
217    /// [7] wenn SG3 AJT+A02+E_0504 vorhanden
218    fn evaluate_7(&self, ctx: &EvaluationContext) -> ConditionResult {
219        sg3_ajt(ctx, &["A02"], &["E_0504"])
220    }
221
222    /// [8] wenn SG3 AJT+A01/A04/A06/A09/A12+E_0504 vorhanden
223    fn evaluate_8(&self, ctx: &EvaluationContext) -> ConditionResult {
224        sg3_ajt(ctx, &["A01", "A04", "A06", "A09", "A12"], &["E_0504"])
225    }
226
227    /// [9] wenn SG3 AJT+A05/A10/A11/A14+E_0504 vorhanden
228    fn evaluate_9(&self, ctx: &EvaluationContext) -> ConditionResult {
229        sg3_ajt(ctx, &["A05", "A10", "A11", "A14"], &["E_0504"])
230    }
231
232    /// [10] wenn SG3 AJT+A03+E_0504 vorhanden
233    fn evaluate_10(&self, ctx: &EvaluationContext) -> ConditionResult {
234        sg3_ajt(ctx, &["A03"], &["E_0504"])
235    }
236
237    /// [11] wenn SG3 AJT+A15+E_0504 vorhanden
238    fn evaluate_11(&self, ctx: &EvaluationContext) -> ConditionResult {
239        sg3_ajt(ctx, &["A15"], &["E_0504"])
240    }
241
242    /// [12] wenn SG3 AJT+A99+S_0109 vorhanden
243    fn evaluate_12(&self, ctx: &EvaluationContext) -> ConditionResult {
244        sg3_ajt(ctx, &["A99"], &["S_0109"])
245    }
246
247    /// [13] wenn SG3 AJT+A07+E_1008 vorhanden
248    fn evaluate_13(&self, ctx: &EvaluationContext) -> ConditionResult {
249        sg3_ajt(ctx, &["A07"], &["E_1008"])
250    }
251
252    /// [14] wenn SG3 AJT+A02+E_1008 vorhanden
253    fn evaluate_14(&self, ctx: &EvaluationContext) -> ConditionResult {
254        sg3_ajt(ctx, &["A02"], &["E_1008"])
255    }
256
257    /// [15] wenn SG3 AJT+A01/A04/A06/A09+E_1008 vorhanden
258    fn evaluate_15(&self, ctx: &EvaluationContext) -> ConditionResult {
259        sg3_ajt(ctx, &["A01", "A04", "A06", "A09"], &["E_1008"])
260    }
261
262    /// [16] wenn SG3 AJT+A03+E_1008 vorhanden
263    fn evaluate_16(&self, ctx: &EvaluationContext) -> ConditionResult {
264        sg3_ajt(ctx, &["A03"], &["E_1008"])
265    }
266
267    /// [17] wenn SG3 AJT+A15+E_1008 vorhanden
268    fn evaluate_17(&self, ctx: &EvaluationContext) -> ConditionResult {
269        sg3_ajt(ctx, &["A15"], &["E_1008"])
270    }
271
272    /// [18] wenn SG3 AJT+A05/A10/A11+E_1008 vorhanden
273    fn evaluate_18(&self, ctx: &EvaluationContext) -> ConditionResult {
274        sg3_ajt(ctx, &["A05", "A10", "A11"], &["E_1008"])
275    }
276
277    /// [19] wenn SG3 AJT+A99+E_0265/E_0516/E_0520/E_0567 vorhanden
278    fn evaluate_19(&self, ctx: &EvaluationContext) -> ConditionResult {
279        sg3_ajt(ctx, &["A99"], &["E_0265", "E_0516", "E_0520", "E_0567"])
280    }
281
282    /// [20] wenn SG3 AJT+A01/A02/A03/A04/A06/A07/A09/A15+E_1008 vorhanden
283    fn evaluate_20(&self, ctx: &EvaluationContext) -> ConditionResult {
284        sg3_ajt(
285            ctx,
286            &["A01", "A02", "A03", "A04", "A06", "A07", "A09", "A15"],
287            &["E_1008"],
288        )
289    }
290
291    /// [21] wenn im DE3155 in demselben COM der Code EM vorhanden ist
292    fn evaluate_21(&self, ctx: &EvaluationContext) -> ConditionResult {
293        let com_segments = ctx.find_segments("COM");
294        ConditionResult::from(com_segments.iter().any(|seg| {
295            seg.elements
296                .first()
297                .and_then(|e| e.get(1))
298                .map(|s| s.as_str())
299                == Some("EM")
300        }))
301    }
302
303    /// [22] wenn im DE3155 in demselben COM der Code TE / FX / AJ / AL vorhanden ist
304    fn evaluate_22(&self, ctx: &EvaluationContext) -> ConditionResult {
305        let com_segments = ctx.find_segments("COM");
306        ConditionResult::from(com_segments.iter().any(|seg| {
307            matches!(
308                seg.elements
309                    .first()
310                    .and_then(|e| e.get(1))
311                    .map(|s| s.as_str()),
312                Some("TE") | Some("FX") | Some("AJ") | Some("AL")
313            )
314        }))
315    }
316
317    /// [28] Angabe der Datenaustauschreferenz aus der CONTRL
318    /// EXTERNAL: Requires context from outside the message.
319    // REVIEW: Condition states the field contains the data exchange reference from a prior CONTRL message. Whether the COMDIS is responding to a CONTRL cannot be determined from the EDIFACT message content alone — it depends on external business context about which prior message triggered this dispute. (medium confidence)
320    fn evaluate_28(&self, ctx: &EvaluationContext) -> ConditionResult {
321        ctx.external.evaluate("responding_to_contrl")
322    }
323
324    /// [29] Angabe der Datenaustauschreferenz aus der APERAK
325    /// EXTERNAL: Requires context from outside the message.
326    // REVIEW: Condition states the field contains the data exchange reference from a prior APERAK message. Whether the COMDIS is responding to an APERAK cannot be determined from the EDIFACT message content alone — it depends on external business context about which prior message triggered this dispute. (medium confidence)
327    fn evaluate_29(&self, ctx: &EvaluationContext) -> ConditionResult {
328        ctx.external.evaluate("responding_to_aperak")
329    }
330
331    /// [30] Angabe der Nachrichtennummer aus der APERAK
332    /// EXTERNAL: Requires context from outside the message.
333    // REVIEW: Condition states the field contains the message number from a prior APERAK. Like condition 29, whether the COMDIS is responding to an APERAK is external business context, not determinable from message content. Shares the same external predicate as condition 29. (medium confidence)
334    fn evaluate_30(&self, ctx: &EvaluationContext) -> ConditionResult {
335        ctx.external.evaluate("responding_to_aperak")
336    }
337
338    /// [492] Wenn MP-ID in NAD+MR (Nachrichtenempfänger) aus Sparte Strom
339    /// EXTERNAL: Requires context from outside the message.
340    // REVIEW: Whether NAD+MR MP-ID belongs to Sparte Strom cannot be determined from the EDIFACT message content alone — it requires external business context (market participant registry or configuration). (medium confidence)
341    fn evaluate_492(&self, ctx: &EvaluationContext) -> ConditionResult {
342        ctx.external.evaluate("recipient_is_electricity_sector")
343    }
344
345    /// [493] Wenn MP-ID in NAD+MR (Nachrichtenempfänger) aus Sparte Gas
346    /// EXTERNAL: Requires context from outside the message.
347    // REVIEW: Whether NAD+MR MP-ID belongs to Sparte Gas cannot be determined from the EDIFACT message content alone — it requires external business context (market participant registry or configuration). (medium confidence)
348    fn evaluate_493(&self, ctx: &EvaluationContext) -> ConditionResult {
349        ctx.external.evaluate("recipient_is_gas_sector")
350    }
351
352    /// [505] Hinweis: BGM DE1004 aus der vorher per REMADV abgelehnten INVOIC-Nachricht
353    fn evaluate_505(&self, _ctx: &EvaluationContext) -> ConditionResult {
354        ConditionResult::True
355    }
356
357    /// [506] Hinweis: BGM DE1004 aus der vorher per IFTSTA abgelehnten MSCONS-Nachricht
358    fn evaluate_506(&self, _ctx: &EvaluationContext) -> ConditionResult {
359        ConditionResult::True
360    }
361
362    /// [508] Hinweis: Es darf nur eine Information im DE3148 übermittelt werden
363    fn evaluate_508(&self, _ctx: &EvaluationContext) -> ConditionResult {
364        // Hinweis: Es darf nur eine Information im DE3148 übermittelt werden — informational note, always applies
365        ConditionResult::True
366    }
367
368    /// [509] Hinweis: Wenn Eingang der zugrundeliegenden Nachricht vor dem 06.06.2025, 00:00 Uhr bestätigt wurde
369    fn evaluate_509(&self, _ctx: &EvaluationContext) -> ConditionResult {
370        // Hinweis: Wenn Eingang der zugrundeliegenden Nachricht vor dem 06.06.2025, 00:00 Uhr bestätigt wurde — informational note, always applies
371        ConditionResult::True
372    }
373
374    /// [510] Hinweis: Wenn Eingang der zugrundeliegenden Nachricht nach dem 06.06.2025, 00:00 Uhr bestätigt wurde
375    fn evaluate_510(&self, _ctx: &EvaluationContext) -> ConditionResult {
376        // Hinweis: Wenn Eingang der zugrundeliegenden Nachricht nach dem 06.06.2025, 00:00 Uhr bestätigt wurde — informational note, always applies
377        ConditionResult::True
378    }
379
380    /// [930] Format: max. 2 Nachkommastellen
381    // REVIEW: Format condition for max 2 decimal places. COMDIS carries monetary amounts (MOA) as the primary numeric value segment. Using MOA elements[0][1] for the amount value. (medium confidence)
382    fn evaluate_930(&self, ctx: &EvaluationContext) -> ConditionResult {
383        ctx.format_check("MOA", 0, 1, |val| validate_max_decimal_places(val, 2))
384    }
385
386    /// [931] Format: ZZZ = +00
387    fn evaluate_931(&self, ctx: &EvaluationContext) -> ConditionResult {
388        ctx.format_check("DTM", 0, 1, validate_timezone_utc)
389    }
390
391    /// [939] Format: Die Zeichenkette muss die Zeichen @ und . enthalten
392    fn evaluate_939(&self, ctx: &EvaluationContext) -> ConditionResult {
393        ctx.format_check("COM", 0, 0, validate_email)
394    }
395
396    /// [940] Format: Die Zeichenkette muss mit dem Zeichen + beginnen und danach dürfen nur noch Ziffern folgen
397    fn evaluate_940(&self, ctx: &EvaluationContext) -> ConditionResult {
398        ctx.format_check("COM", 0, 0, validate_phone)
399    }
400}
401
402/// HAND-EDITED (#334): "wenn SG3 AJT+<answer>+<list> vorhanden" reads the AJT of
403/// the SG3 the evaluated field sits in, message-wide only when the scope does
404/// not reach an SG3. SG3 repeats once per reason, and FTX+ACD/ACB combine these
405/// conditions with `⊻`, which holds only per SG3. Absence is `False`, not
406/// `Unknown`: the SG3 is fully known.
407fn sg3_ajt(ctx: &EvaluationContext, answers: &[&str], lists: &[&str]) -> ConditionResult {
408    fn component(seg: &OwnedSegment, elem: usize) -> Option<&str> {
409        seg.elements
410            .get(elem)
411            .and_then(|e| e.first())
412            .map(String::as_str)
413    }
414    ConditionResult::from(ctx.scoped_find_segments_in("SG3", "AJT").iter().any(|seg| {
415        component(seg, 0).is_some_and(|a| answers.contains(&a))
416            && component(seg, 1).is_some_and(|l| lists.contains(&l))
417    }))
418}