automapper_validation/generated/fv2610/orders_conditions_fv2610.rs
1// <auto-generated>
2// Generated by automapper-generator generate-conditions
3// AHB: xml-migs-and-ahbs/FV2610/ORDERS_AHB_1_1b_Fehlerkorrektur_20260629.xml
4// Generated: 2026-04-22T18:13:18Z
5// Delegates unchanged conditions to OrdersConditionEvaluatorFV2604 (FV2604).
6// </auto-generated>
7
8#![allow(clippy::style, clippy::complexity)]
9
10#[allow(unused_imports)]
11use crate::eval::format_validators::*;
12use crate::eval::{ConditionEvaluator, ConditionResult, EvaluationContext};
13use crate::generated::fv2604::OrdersConditionEvaluatorFV2604;
14
15/// Condition evaluator for ORDERS FV2610.
16///
17/// Delegates to [`OrdersConditionEvaluatorFV2604`] for conditions whose AHB description is
18/// unchanged from that version. Local overrides: [75, 106, 110, 147, 148, 163, 169, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 490, 491, 492, 493, 593, 594, 595].
19pub struct OrdersConditionEvaluatorFV2610 {
20 fallback: OrdersConditionEvaluatorFV2604,
21}
22
23impl Default for OrdersConditionEvaluatorFV2610 {
24 fn default() -> Self {
25 Self {
26 fallback: OrdersConditionEvaluatorFV2604::default(),
27 }
28 }
29}
30
31/// Condition IDs whose implementation differs from the fallback.
32const FV2610_OVERRIDES: &[u32] = &[
33 75, 106, 110, 147, 148, 163, 169, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 490, 491,
34 492, 493, 593, 594, 595,
35];
36
37impl ConditionEvaluator for OrdersConditionEvaluatorFV2610 {
38 fn message_type(&self) -> &str {
39 "ORDERS"
40 }
41
42 fn format_version(&self) -> &str {
43 "FV2610"
44 }
45
46 fn evaluate(&self, condition: u32, ctx: &EvaluationContext) -> ConditionResult {
47 match condition {
48 75 => self.evaluate_75(ctx),
49 106 => self.evaluate_106(ctx),
50 110 => self.evaluate_110(ctx),
51 147 => self.evaluate_147(ctx),
52 148 => self.evaluate_148(ctx),
53 169 => self.evaluate_169(ctx),
54 184 => self.evaluate_184(ctx),
55 185 => self.evaluate_185(ctx),
56 196 => self.evaluate_196(ctx),
57 197 => self.evaluate_197(ctx),
58 198 => self.evaluate_198(ctx),
59 199 => self.evaluate_199(ctx),
60 200 => self.evaluate_200(ctx),
61 201 => self.evaluate_201(ctx),
62 202 => self.evaluate_202(ctx),
63 203 => self.evaluate_203(ctx),
64 490 => self.evaluate_490(ctx),
65 491 => self.evaluate_491(ctx),
66 492 => self.evaluate_492(ctx),
67 493 => self.evaluate_493(ctx),
68 593 => self.evaluate_593(ctx),
69 594 => self.evaluate_594(ctx),
70 595 => self.evaluate_595(ctx),
71 163 => self.evaluate_163(ctx),
72 other => self.fallback.evaluate(other, ctx),
73 }
74 }
75
76 fn is_external(&self, condition: u32) -> bool {
77 matches!(
78 condition,
79 75 | 184 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 492 | 493
80 ) || self.fallback.is_external(condition)
81 }
82
83 fn is_known(&self, condition: u32) -> bool {
84 FV2610_OVERRIDES.contains(&condition) || self.fallback.is_known(condition)
85 }
86}
87
88impl OrdersConditionEvaluatorFV2610 {
89 /// [75] Wenn für den erforderlichen Wert keine Zählzeit benötigt wird
90 /// EXTERNAL: Requires context from outside the message.
91 fn evaluate_75(&self, ctx: &EvaluationContext) -> ConditionResult {
92 ctx.external.evaluate("no_zaehlerzeit_required")
93 }
94
95 /// [106] Wenn IMD++Z60 (Abbestellung Messprodukt mit Zählzeitdefinition des LF) nicht vorhanden
96 fn evaluate_106(&self, ctx: &EvaluationContext) -> ConditionResult {
97 ctx.lacks_qualifier("IMD", 1, "Z60")
98 }
99
100 /// [110] Wenn DTM+163 (Beginn Zeitraum für Wertanfrage) vorhanden
101 fn evaluate_110(&self, ctx: &EvaluationContext) -> ConditionResult {
102 ctx.has_qualifier("DTM", 0, "163")
103 }
104
105 /// [147] Wenn im DE3155 in demselben COM der Code EM vorhanden ist
106 fn evaluate_147(&self, ctx: &EvaluationContext) -> ConditionResult {
107 ConditionResult::from(ctx.self_segment_value_equals("COM", 0, 1, "EM"))
108 }
109
110 /// [148] Wenn im DE3155 in demselben COM der Code TE / FX / AJ / AL vorhanden ist
111 fn evaluate_148(&self, ctx: &EvaluationContext) -> ConditionResult {
112 ConditionResult::from(
113 ctx.self_segment_value_equals("COM", 0, 1, "TE")
114 || ctx.self_segment_value_equals("COM", 0, 1, "FX")
115 || ctx.self_segment_value_equals("COM", 0, 1, "AJ")
116 || ctx.self_segment_value_equals("COM", 0, 1, "AL"),
117 )
118 }
119
120 /// [169] Wenn in SG29 LIN++Z19 (Erforderliches Produkt der Messlokation) in SG30 CCI (Zugeordnete Zählzeitdefinition) im DE7059 der Code Z39 (Code der Zählzeitdefinition) vorhanden ist
121 // REVIEW: SG29 is parent group with LIN entry where elements[1][0]=="Z19" (notation LIN++Z19 → elements[1]=Z19). SG30 is child group; CCI DE7059 (Property class code qualifier) is at elements[0][0]. Z39 = Code der Zählzeitdefinition. Confidence medium because exact nesting depth of SG29 within ORDERS hierarchy is not confirmed without MIG XML. (medium confidence)
122 fn evaluate_169(&self, ctx: &EvaluationContext) -> ConditionResult {
123 ctx.filtered_parent_child_has_qualifier(&["SG29"], "LIN", 1, "Z19", "SG30", "CCI", 0, "Z39")
124 }
125
126 /// [184] Wenn es sich in der Position (SG34 RFF+Z03 DE1154) die innerhalb dieser SG29 LIN bestellt wird, um die Bestellung des Geräteübernahmeangebotes eines Smartmeter-Gateways handelt.
127 /// EXTERNAL: Requires context from outside the message.
128 fn evaluate_184(&self, ctx: &EvaluationContext) -> ConditionResult {
129 ctx.external.evaluate("is_smgw_takeover_offer_order")
130 }
131
132 /// [185] Wenn FTX+Z29 (Endpunkt-Adresse (IP:Port)) vorhanden
133 fn evaluate_185(&self, ctx: &EvaluationContext) -> ConditionResult {
134 // HAND-EDITED: the SMGW's own FTX+Z29 — the certificate, WakeUp and
135 // APN FTX of its position (SG29) only, not of every position.
136 ctx.this_group_has_qualifier("FTX", 0, "Z29", &["SG29"])
137 }
138
139 /// [196] Zulässig sind ausschließlich Codes aus der Spalte „Code“ der Codeliste der Verwendungszwecke (Kapitel 2), sofern in derselben Zeile sowohl in der Spalte „Lokation/NeLo“ als auch in der ...
140 /// EXTERNAL: Requires context from outside the message.
141 fn evaluate_196(&self, ctx: &EvaluationContext) -> ConditionResult {
142 ctx.external.evaluate("valid_verwendungszweck_nb_lokation")
143 }
144
145 /// [197] Zulässig sind ausschließlich Codes aus der Spalte „Code“ der Codeliste der Verwendungszwecke (Kapitel 2), sofern in derselben Zeile sowohl in der Spalte „Lokation/NeLo“ als auch in der ...
146 /// EXTERNAL: Requires context from outside the message.
147 fn evaluate_197(&self, ctx: &EvaluationContext) -> ConditionResult {
148 ctx.external.evaluate("valid_verwendungszweck_lf_lokation")
149 }
150
151 /// [198] Zulässig sind ausschließlich Codes aus der Spalte „Code“ der Codeliste der Verwendungszwecke (Kapitel 2), sofern in derselben Zeile sowohl in der Spalte „Lokation/MaLo“ als auch in der ...
152 /// EXTERNAL: Requires context from outside the message.
153 fn evaluate_198(&self, ctx: &EvaluationContext) -> ConditionResult {
154 ctx.external.evaluate("verwendungszweck_malo_nb_valid")
155 }
156
157 /// [199] Zulässig sind ausschließlich Codes aus der Spalte „Code“ der Codeliste der Verwendungszwecke (Kapitel 2), sofern in derselben Zeile sowohl in der Spalte „Lokation/MaLo“ als auch in der ...
158 /// EXTERNAL: Requires context from outside the message.
159 fn evaluate_199(&self, ctx: &EvaluationContext) -> ConditionResult {
160 ctx.external.evaluate("verwendungszweck_malo_lf_valid")
161 }
162
163 /// [200] Zulässig sind ausschließlich Codes aus der Spalte „Code“ der Codeliste der Verwendungszwecke (Kapitel 2), sofern in derselben Zeile sowohl in der Spalte „Lokation/MaLo“ als auch in der ...
164 /// EXTERNAL: Requires context from outside the message.
165 fn evaluate_200(&self, ctx: &EvaluationContext) -> ConditionResult {
166 ctx.external.evaluate("verwendungszweck_malo_uenb_valid")
167 }
168
169 /// [201] Zulässig sind ausschließlich Codes aus der Spalte „Code“ der Codeliste der Verwendungszwecke (Kapitel 2), sofern in derselben Zeile sowohl in der Spalte „Lokation/Tranche“ als auch in d...
170 /// EXTERNAL: Requires context from outside the message.
171 fn evaluate_201(&self, ctx: &EvaluationContext) -> ConditionResult {
172 ctx.external.evaluate("verwendungszweck_tranche_nb_valid")
173 }
174
175 /// [202] Zulässig sind ausschließlich Codes aus der Spalte „Code“ der Codeliste der Verwendungszwecke (Kapitel 2), sofern in derselben Zeile sowohl in der Spalte „Lokation/Tranche“ als auch in d...
176 /// EXTERNAL: Requires context from outside the message.
177 fn evaluate_202(&self, ctx: &EvaluationContext) -> ConditionResult {
178 ctx.external.evaluate("verwendungszweck_tranche_lf_valid")
179 }
180
181 /// [203] Zulässig sind ausschließlich Codes aus der Spalte „Code“ der Codeliste der Verwendungszwecke (Kapitel 2), sofern in derselben Zeile sowohl in der Spalte „Lokation/Tranche“ als auch in d...
182 /// EXTERNAL: Requires context from outside the message.
183 fn evaluate_203(&self, ctx: &EvaluationContext) -> ConditionResult {
184 ctx.external.evaluate("verwendungszweck_tranche_uenb_valid")
185 }
186
187 /// [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...
188 fn evaluate_490(&self, ctx: &EvaluationContext) -> ConditionResult {
189 ctx.format_check("DTM", 0, 1, is_mesz_utc)
190 }
191
192 /// [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)...
193 fn evaluate_491(&self, ctx: &EvaluationContext) -> ConditionResult {
194 ctx.format_check("DTM", 0, 1, is_mez_utc)
195 }
196
197 /// [492] Wenn MP-ID in NAD+MR aus Sparte Strom
198 /// EXTERNAL: Requires context from outside the message.
199 fn evaluate_492(&self, ctx: &EvaluationContext) -> ConditionResult {
200 ctx.external.evaluate("nad_mr_is_strom_sector")
201 }
202
203 /// [493] Wenn MP-ID in NAD+MR aus Sparte Gas
204 /// EXTERNAL: Requires context from outside the message.
205 fn evaluate_493(&self, ctx: &EvaluationContext) -> ConditionResult {
206 ctx.external.evaluate("nad_mr_is_gas_sector")
207 }
208
209 /// [593] Hinweis: Daten des MSBN
210 fn evaluate_593(&self, _ctx: &EvaluationContext) -> ConditionResult {
211 // Hinweis: Daten des MSBN — informational note, always applies
212 ConditionResult::True
213 }
214
215 /// [594] Hinweis: Wenn die Aufteilung der Tranche prozentual erfolgt.
216 fn evaluate_594(&self, _ctx: &EvaluationContext) -> ConditionResult {
217 // Hinweis: Wenn die Aufteilung der Tranche prozentual erfolgt — informational note, always applies
218 ConditionResult::True
219 }
220
221 /// [595] Hinweis: Wenn die Aufteilung auf Basis eines Aufteilungsfaktors wie z.B. der installierten Leistung auf Basis der Technischen Ressourcen erfolgt. Da die Berechnungsformel (UTILTS) derzeit nur für ...
222 fn evaluate_595(&self, _ctx: &EvaluationContext) -> ConditionResult {
223 // Hinweis: Aufteilung auf Basis eines Aufteilungsfaktors (installierte Leistung, Technische Ressourcen) — informational note, always applies
224 ConditionResult::True
225 }
226
227 /// [163] Wenn innerhalb der Nachricht in einem PIA+5 (Erforderliches Produkt der Marktlokation / Erforderliches Produkt der Tranc...
228 // PIA: element 0 is 4347, elements 1–5 are the C212 composites; DE7143 is component 1.
229 fn evaluate_163(&self, ctx: &EvaluationContext) -> ConditionResult {
230 let found = ctx
231 .find_segments_with_qualifier("PIA", 0, "5")
232 .iter()
233 .any(|s| {
234 s.elements
235 .get(4)
236 .and_then(|c212| c212.get(1))
237 .is_some_and(|code| !code.is_empty() && code != "V15")
238 });
239 ConditionResult::from(found)
240 }
241}