1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
// <auto-generated>
// Generated by automapper-generator generate-conditions
// AHB: xml-migs-and-ahbs/FV2610/ORDERS_AHB_1_1b_20260401.xml
// Generated: 2026-04-22T18:13:18Z
// Delegates unchanged conditions to OrdersConditionEvaluatorFV2604 (FV2604).
// </auto-generated>
#![allow(clippy::style, clippy::complexity)]
#[allow(unused_imports)]
use crate::eval::format_validators::*;
use crate::eval::{ConditionEvaluator, ConditionResult, EvaluationContext};
use crate::generated::fv2604::OrdersConditionEvaluatorFV2604;
/// Condition evaluator for ORDERS FV2610.
///
/// Delegates to [`OrdersConditionEvaluatorFV2604`] for conditions whose AHB description is
/// unchanged from that version. Local overrides: [75, 106, 110, 147, 148, 169, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 490, 491, 492, 493, 593, 594, 595].
pub struct OrdersConditionEvaluatorFV2610 {
fallback: OrdersConditionEvaluatorFV2604,
}
impl Default for OrdersConditionEvaluatorFV2610 {
fn default() -> Self {
Self {
fallback: OrdersConditionEvaluatorFV2604::default(),
}
}
}
/// Condition IDs whose implementation differs from the fallback.
const FV2610_OVERRIDES: &[u32] = &[
75, 106, 110, 147, 148, 169, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 490, 491, 492,
493, 593, 594, 595,
];
impl ConditionEvaluator for OrdersConditionEvaluatorFV2610 {
fn message_type(&self) -> &str {
"ORDERS"
}
fn format_version(&self) -> &str {
"FV2610"
}
fn evaluate(&self, condition: u32, ctx: &EvaluationContext) -> ConditionResult {
match condition {
75 => self.evaluate_75(ctx),
106 => self.evaluate_106(ctx),
110 => self.evaluate_110(ctx),
147 => self.evaluate_147(ctx),
148 => self.evaluate_148(ctx),
169 => self.evaluate_169(ctx),
184 => self.evaluate_184(ctx),
185 => self.evaluate_185(ctx),
196 => self.evaluate_196(ctx),
197 => self.evaluate_197(ctx),
198 => self.evaluate_198(ctx),
199 => self.evaluate_199(ctx),
200 => self.evaluate_200(ctx),
201 => self.evaluate_201(ctx),
202 => self.evaluate_202(ctx),
203 => self.evaluate_203(ctx),
490 => self.evaluate_490(ctx),
491 => self.evaluate_491(ctx),
492 => self.evaluate_492(ctx),
493 => self.evaluate_493(ctx),
593 => self.evaluate_593(ctx),
594 => self.evaluate_594(ctx),
595 => self.evaluate_595(ctx),
other => self.fallback.evaluate(other, ctx),
}
}
fn is_external(&self, condition: u32) -> bool {
matches!(
condition,
75 | 184 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 492 | 493
) || self.fallback.is_external(condition)
}
fn is_known(&self, condition: u32) -> bool {
FV2610_OVERRIDES.contains(&condition) || self.fallback.is_known(condition)
}
}
impl OrdersConditionEvaluatorFV2610 {
/// [75] Wenn für den erforderlichen Wert keine Zählzeit benötigt wird
/// EXTERNAL: Requires context from outside the message.
fn evaluate_75(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.external.evaluate("no_zaehlerzeit_required")
}
/// [106] Wenn IMD++Z60 (Abbestellung Messprodukt mit Zählzeitdefinition des LF) nicht vorhanden
fn evaluate_106(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.lacks_qualifier("IMD", 1, "Z60")
}
/// [110] Wenn DTM+163 (Beginn Zeitraum für Wertanfrage) vorhanden
fn evaluate_110(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.has_qualifier("DTM", 0, "163")
}
/// [147] Wenn im DE3155 in demselben COM der Code EM vorhanden ist
fn evaluate_147(&self, ctx: &EvaluationContext) -> ConditionResult {
ConditionResult::from(ctx.self_segment_value_equals("COM", 0, 1, "EM"))
}
/// [148] Wenn im DE3155 in demselben COM der Code TE / FX / AJ / AL vorhanden ist
fn evaluate_148(&self, ctx: &EvaluationContext) -> ConditionResult {
ConditionResult::from(
ctx.self_segment_value_equals("COM", 0, 1, "TE")
|| ctx.self_segment_value_equals("COM", 0, 1, "FX")
|| ctx.self_segment_value_equals("COM", 0, 1, "AJ")
|| ctx.self_segment_value_equals("COM", 0, 1, "AL"),
)
}
/// [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
// 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)
fn evaluate_169(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.filtered_parent_child_has_qualifier(&["SG29"], "LIN", 1, "Z19", "SG30", "CCI", 0, "Z39")
}
/// [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.
/// EXTERNAL: Requires context from outside the message.
fn evaluate_184(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.external.evaluate("is_smgw_takeover_offer_order")
}
/// [185] Wenn FTX+Z29 (Endpunkt-Adresse (IP:Port)) vorhanden
fn evaluate_185(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.has_qualifier("FTX", 0, "Z29")
}
/// [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 ...
/// EXTERNAL: Requires context from outside the message.
fn evaluate_196(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.external.evaluate("valid_verwendungszweck_nb_lokation")
}
/// [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 ...
/// EXTERNAL: Requires context from outside the message.
fn evaluate_197(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.external.evaluate("valid_verwendungszweck_lf_lokation")
}
/// [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 ...
/// EXTERNAL: Requires context from outside the message.
fn evaluate_198(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.external.evaluate("verwendungszweck_malo_nb_valid")
}
/// [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 ...
/// EXTERNAL: Requires context from outside the message.
fn evaluate_199(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.external.evaluate("verwendungszweck_malo_lf_valid")
}
/// [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 ...
/// EXTERNAL: Requires context from outside the message.
fn evaluate_200(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.external.evaluate("verwendungszweck_malo_uenb_valid")
}
/// [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...
/// EXTERNAL: Requires context from outside the message.
fn evaluate_201(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.external.evaluate("verwendungszweck_tranche_nb_valid")
}
/// [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...
/// EXTERNAL: Requires context from outside the message.
fn evaluate_202(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.external.evaluate("verwendungszweck_tranche_lf_valid")
}
/// [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...
/// EXTERNAL: Requires context from outside the message.
fn evaluate_203(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.external.evaluate("verwendungszweck_tranche_uenb_valid")
}
/// [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...
fn evaluate_490(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.format_check("DTM", 0, 1, is_mesz_utc)
}
/// [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)...
fn evaluate_491(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.format_check("DTM", 0, 1, is_mez_utc)
}
/// [492] Wenn MP-ID in NAD+MR aus Sparte Strom
/// EXTERNAL: Requires context from outside the message.
fn evaluate_492(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.external.evaluate("nad_mr_is_strom_sector")
}
/// [493] Wenn MP-ID in NAD+MR aus Sparte Gas
/// EXTERNAL: Requires context from outside the message.
fn evaluate_493(&self, ctx: &EvaluationContext) -> ConditionResult {
ctx.external.evaluate("nad_mr_is_gas_sector")
}
/// [593] Hinweis: Daten des MSBN
fn evaluate_593(&self, _ctx: &EvaluationContext) -> ConditionResult {
// Hinweis: Daten des MSBN — informational note, always applies
ConditionResult::True
}
/// [594] Hinweis: Wenn die Aufteilung der Tranche prozentual erfolgt.
fn evaluate_594(&self, _ctx: &EvaluationContext) -> ConditionResult {
// Hinweis: Wenn die Aufteilung der Tranche prozentual erfolgt — informational note, always applies
ConditionResult::True
}
/// [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 ...
fn evaluate_595(&self, _ctx: &EvaluationContext) -> ConditionResult {
// Hinweis: Aufteilung auf Basis eines Aufteilungsfaktors (installierte Leistung, Technische Ressourcen) — informational note, always applies
ConditionResult::True
}
}