Skip to main content

automapper_validation/generated/fv2510/
comdis_conditions_fv2510.rs

1// <auto-generated>
2// Generated by automapper-generator generate-conditions
3// AHB: xml-migs-and-ahbs/FV2510/COMDIS_AHB_1_0g__20250401.xml
4// Generated: 2026-03-12T10:36:14Z
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 FV2510.
18pub struct ComdisConditionEvaluatorFV2510 {
19    // External condition IDs that require runtime context.
20    external_conditions: std::collections::HashSet<u32>,
21}
22
23impl Default for ComdisConditionEvaluatorFV2510 {
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 ComdisConditionEvaluatorFV2510 {
44    fn message_type(&self) -> &str {
45        "COMDIS"
46    }
47
48    fn format_version(&self) -> &str {
49        "FV2510"
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 ComdisConditionEvaluatorFV2510 {
150    /// [19] wenn SG3 AJT+A99+E_0265/E_0271/E_0274/E_0516/E_0520/E_0567 vorhanden
151    fn evaluate_19(&self, ctx: &EvaluationContext) -> ConditionResult {
152        sg3_ajt(
153            ctx,
154            &["A99"],
155            &["E_0265", "E_0271", "E_0274", "E_0516", "E_0520", "E_0567"],
156        )
157    }
158
159    /// [1] wenn SG3 AJT+Z61+S_0109 oder SG3 AJT+Z62+S_0109 vorhanden.
160    fn evaluate_1(&self, ctx: &EvaluationContext) -> ConditionResult {
161        sg3_ajt(ctx, &["Z61", "Z62"], &["S_0109"])
162    }
163
164    /// [2] wenn SG3 AJT+Z58+S_0109 oder SG3 AJT+Z59+S_0109 oder SG3 AJT+Z60+S_0109 vorhanden.
165    fn evaluate_2(&self, ctx: &EvaluationContext) -> ConditionResult {
166        sg3_ajt(ctx, &["Z58", "Z59", "Z60"], &["S_0109"])
167    }
168
169    /// [3] Nur MP-ID aus Sparte Strom
170    /// EXTERNAL: Requires context from outside the message.
171    fn evaluate_3(&self, ctx: &EvaluationContext) -> ConditionResult {
172        ctx.external.evaluate("mp_id_from_electricity_sector")
173    }
174
175    /// [4] wenn SG3 AJT+Z58/Z59/Z60/Z61/Z62+S_0109 vorhanden
176    fn evaluate_4(&self, ctx: &EvaluationContext) -> ConditionResult {
177        sg3_ajt(ctx, &["Z58", "Z59", "Z60", "Z61", "Z62"], &["S_0109"])
178    }
179
180    /// [5] wenn SG3 AJT+A01/A02/A03/A04/A06/A07/A09/A12/A15+E_0504 vorhanden
181    fn evaluate_5(&self, ctx: &EvaluationContext) -> ConditionResult {
182        sg3_ajt(
183            ctx,
184            &[
185                "A01", "A02", "A03", "A04", "A06", "A07", "A09", "A12", "A15",
186            ],
187            &["E_0504"],
188        )
189    }
190
191    /// [6] wenn SG3 AJT+A07+E_0504 vorhanden
192    fn evaluate_6(&self, ctx: &EvaluationContext) -> ConditionResult {
193        sg3_ajt(ctx, &["A07"], &["E_0504"])
194    }
195
196    /// [7] wenn SG3 AJT+A02+E_0504 vorhanden
197    fn evaluate_7(&self, ctx: &EvaluationContext) -> ConditionResult {
198        sg3_ajt(ctx, &["A02"], &["E_0504"])
199    }
200
201    /// [8] wenn SG3 AJT+A01/A04/A06/A09/A12+E_0504 vorhanden
202    fn evaluate_8(&self, ctx: &EvaluationContext) -> ConditionResult {
203        sg3_ajt(ctx, &["A01", "A04", "A06", "A09", "A12"], &["E_0504"])
204    }
205
206    /// [9] wenn SG3 AJT+A05/A10/A11/A14+E_0504 vorhanden
207    fn evaluate_9(&self, ctx: &EvaluationContext) -> ConditionResult {
208        sg3_ajt(ctx, &["A05", "A10", "A11", "A14"], &["E_0504"])
209    }
210
211    /// [10] wenn SG3 AJT+A03+E_0504 vorhanden
212    fn evaluate_10(&self, ctx: &EvaluationContext) -> ConditionResult {
213        sg3_ajt(ctx, &["A03"], &["E_0504"])
214    }
215
216    /// [11] wenn SG3 AJT+A15+E_0504 vorhanden
217    fn evaluate_11(&self, ctx: &EvaluationContext) -> ConditionResult {
218        sg3_ajt(ctx, &["A15"], &["E_0504"])
219    }
220
221    /// [12] wenn SG3 AJT+A99+S_0109 vorhanden
222    fn evaluate_12(&self, ctx: &EvaluationContext) -> ConditionResult {
223        sg3_ajt(ctx, &["A99"], &["S_0109"])
224    }
225
226    /// [13] wenn SG3 AJT+A07+E_1008 vorhanden
227    fn evaluate_13(&self, ctx: &EvaluationContext) -> ConditionResult {
228        sg3_ajt(ctx, &["A07"], &["E_1008"])
229    }
230
231    /// [14] wenn SG3 AJT+A02+E_1008 vorhanden
232    fn evaluate_14(&self, ctx: &EvaluationContext) -> ConditionResult {
233        sg3_ajt(ctx, &["A02"], &["E_1008"])
234    }
235
236    /// [15] wenn SG3 AJT+A01/A04/A06/A09+E_1008 vorhanden
237    fn evaluate_15(&self, ctx: &EvaluationContext) -> ConditionResult {
238        sg3_ajt(ctx, &["A01", "A04", "A06", "A09"], &["E_1008"])
239    }
240
241    /// [16] wenn SG3 AJT+A03+E_1008 vorhanden
242    fn evaluate_16(&self, ctx: &EvaluationContext) -> ConditionResult {
243        sg3_ajt(ctx, &["A03"], &["E_1008"])
244    }
245
246    /// [17] wenn SG3 AJT+A15+E_1008 vorhanden
247    fn evaluate_17(&self, ctx: &EvaluationContext) -> ConditionResult {
248        sg3_ajt(ctx, &["A15"], &["E_1008"])
249    }
250
251    /// [18] wenn SG3 AJT+A05/A10/A11+E_1008 vorhanden
252    fn evaluate_18(&self, ctx: &EvaluationContext) -> ConditionResult {
253        sg3_ajt(ctx, &["A05", "A10", "A11"], &["E_1008"])
254    }
255
256    /// [20] wenn SG3 AJT+A01/A02/A03/A04/A06/A07/A09/A15+E_1008 vorhanden
257    fn evaluate_20(&self, ctx: &EvaluationContext) -> ConditionResult {
258        sg3_ajt(
259            ctx,
260            &["A01", "A02", "A03", "A04", "A06", "A07", "A09", "A15"],
261            &["E_1008"],
262        )
263    }
264
265    /// [21] wenn im DE3155 in demselben COM der Code EM vorhanden ist
266    fn evaluate_21(&self, ctx: &EvaluationContext) -> ConditionResult {
267        let com_segments = ctx.find_segments("COM");
268        ConditionResult::from(com_segments.iter().any(|seg| {
269            seg.elements
270                .first()
271                .and_then(|e| e.get(1))
272                .map(|s| s.as_str())
273                == Some("EM")
274        }))
275    }
276
277    /// [22] wenn im DE3155 in demselben COM der Code TE / FX / AJ / AL vorhanden ist
278    fn evaluate_22(&self, ctx: &EvaluationContext) -> ConditionResult {
279        let com_segments = ctx.find_segments("COM");
280        ConditionResult::from(com_segments.iter().any(|seg| {
281            matches!(
282                seg.elements
283                    .first()
284                    .and_then(|e| e.get(1))
285                    .map(|s| s.as_str()),
286                Some("TE") | Some("FX") | Some("AJ") | Some("AL")
287            )
288        }))
289    }
290
291    /// [23] Wenn MP-ID in NAD+MS (Nachrichtensender) mit Rolle MSB vorhanden
292    /// EXTERNAL: Requires context from outside the message.
293    fn evaluate_23(&self, ctx: &EvaluationContext) -> ConditionResult {
294        ctx.external.evaluate("sender_is_msb")
295    }
296
297    /// [24] Wenn MP-ID in NAD+MR (Nachrichtenempfänger) mit Rolle ESA vorhanden
298    /// EXTERNAL: Requires context from outside the message.
299    fn evaluate_24(&self, ctx: &EvaluationContext) -> ConditionResult {
300        ctx.external.evaluate("recipient_is_esa")
301    }
302
303    /// [25] Wenn MP-ID in NAD+MR (Nachrichtenempfänger) mit Rolle LF vorhanden
304    /// EXTERNAL: Requires context from outside the message.
305    fn evaluate_25(&self, ctx: &EvaluationContext) -> ConditionResult {
306        ctx.external.evaluate("recipient_is_lf")
307    }
308
309    /// [26] Wenn MP-ID in NAD+MR (Nachrichtenempfänger) mit Rolle NB vorhanden
310    /// EXTERNAL: Requires context from outside the message.
311    fn evaluate_26(&self, ctx: &EvaluationContext) -> ConditionResult {
312        ctx.external.evaluate("recipient_is_nb")
313    }
314
315    /// [27] Wenn MP-ID in NAD+MS (Nachrichtensender) mit Rolle NB vorhanden
316    /// EXTERNAL: Requires context from outside the message.
317    fn evaluate_27(&self, ctx: &EvaluationContext) -> ConditionResult {
318        ctx.external.evaluate("sender_is_nb")
319    }
320
321    /// [28] Angabe der Datenaustauschreferenz aus der CONTRL
322    /// EXTERNAL: Requires context from outside the message.
323    // 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)
324    fn evaluate_28(&self, ctx: &EvaluationContext) -> ConditionResult {
325        ctx.external.evaluate("responding_to_contrl")
326    }
327
328    /// [29] Angabe der Datenaustauschreferenz aus der APERAK
329    /// EXTERNAL: Requires context from outside the message.
330    // 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)
331    fn evaluate_29(&self, ctx: &EvaluationContext) -> ConditionResult {
332        ctx.external.evaluate("responding_to_aperak")
333    }
334
335    /// [30] Angabe der Nachrichtennummer aus der APERAK
336    /// EXTERNAL: Requires context from outside the message.
337    // 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)
338    fn evaluate_30(&self, ctx: &EvaluationContext) -> ConditionResult {
339        ctx.external.evaluate("responding_to_aperak")
340    }
341
342    /// [492] Wenn MP-ID in NAD+MR (Nachrichtenempfänger) aus Sparte Strom
343    /// EXTERNAL: Requires context from outside the message.
344    // 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)
345    fn evaluate_492(&self, ctx: &EvaluationContext) -> ConditionResult {
346        ctx.external.evaluate("recipient_is_electricity_sector")
347    }
348
349    /// [493] Wenn MP-ID in NAD+MR (Nachrichtenempfänger) aus Sparte Gas
350    /// EXTERNAL: Requires context from outside the message.
351    // 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)
352    fn evaluate_493(&self, ctx: &EvaluationContext) -> ConditionResult {
353        ctx.external.evaluate("recipient_is_gas_sector")
354    }
355
356    /// [505] Hinweis: BGM DE1004 aus der vorher per REMADV abgelehnten INVOIC-Nachricht
357    fn evaluate_505(&self, _ctx: &EvaluationContext) -> ConditionResult {
358        ConditionResult::True
359    }
360
361    /// [506] Hinweis: BGM DE1004 aus der vorher per IFTSTA abgelehnten MSCONS-Nachricht
362    fn evaluate_506(&self, _ctx: &EvaluationContext) -> ConditionResult {
363        ConditionResult::True
364    }
365
366    /// [508] Hinweis: Es darf nur eine Information im DE3148 übermittelt werden
367    fn evaluate_508(&self, _ctx: &EvaluationContext) -> ConditionResult {
368        // Hinweis: Es darf nur eine Information im DE3148 übermittelt werden — informational note, always applies
369        ConditionResult::True
370    }
371
372    /// [509] Hinweis: Wenn Eingang der zugrundeliegenden Nachricht vor dem 06.06.2025, 00:00 Uhr bestätigt wurde
373    fn evaluate_509(&self, _ctx: &EvaluationContext) -> ConditionResult {
374        // Hinweis: Wenn Eingang der zugrundeliegenden Nachricht vor dem 06.06.2025, 00:00 Uhr bestätigt wurde — informational note, always applies
375        ConditionResult::True
376    }
377
378    /// [510] Hinweis: Wenn Eingang der zugrundeliegenden Nachricht nach dem 06.06.2025, 00:00 Uhr bestätigt wurde
379    fn evaluate_510(&self, _ctx: &EvaluationContext) -> ConditionResult {
380        // Hinweis: Wenn Eingang der zugrundeliegenden Nachricht nach dem 06.06.2025, 00:00 Uhr bestätigt wurde — informational note, always applies
381        ConditionResult::True
382    }
383
384    /// [930] Format: max. 2 Nachkommastellen
385    // 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)
386    fn evaluate_930(&self, ctx: &EvaluationContext) -> ConditionResult {
387        ctx.format_check("MOA", 0, 1, |val| validate_max_decimal_places(val, 2))
388    }
389
390    /// [931] Format: ZZZ = +00
391    fn evaluate_931(&self, ctx: &EvaluationContext) -> ConditionResult {
392        ctx.format_check("DTM", 0, 1, validate_timezone_utc)
393    }
394
395    /// [939] Format: Die Zeichenkette muss die Zeichen @ und . enthalten
396    fn evaluate_939(&self, ctx: &EvaluationContext) -> ConditionResult {
397        ctx.format_check("COM", 0, 0, validate_email)
398    }
399
400    /// [940] Format: Die Zeichenkette muss mit dem Zeichen + beginnen und danach dürfen nur noch Ziffern folgen
401    fn evaluate_940(&self, ctx: &EvaluationContext) -> ConditionResult {
402        ctx.format_check("COM", 0, 0, validate_phone)
403    }
404}
405
406/// HAND-EDITED (#334): "wenn SG3 AJT+<answer>+<list> vorhanden" reads the AJT of
407/// the SG3 the evaluated field sits in, message-wide only when the scope does
408/// not reach an SG3. SG3 repeats once per reason, and FTX+ACD/ACB combine these
409/// conditions with `⊻`, which holds only per SG3. Absence is `False`, not
410/// `Unknown`: the SG3 is fully known.
411fn sg3_ajt(ctx: &EvaluationContext, answers: &[&str], lists: &[&str]) -> ConditionResult {
412    fn component(seg: &OwnedSegment, elem: usize) -> Option<&str> {
413        seg.elements
414            .get(elem)
415            .and_then(|e| e.first())
416            .map(String::as_str)
417    }
418    ConditionResult::from(ctx.scoped_find_segments_in("SG3", "AJT").iter().any(|seg| {
419        component(seg, 0).is_some_and(|a| answers.contains(&a))
420            && component(seg, 1).is_some_and(|l| lists.contains(&l))
421    }))
422}