automapper_validation/generated/fv2610/utilmd_strom_conditions_fv2610.rs
1// <auto-generated>
2// Generated by automapper-generator generate-conditions
3// AHB: xml-migs-and-ahbs/FV2610/UTILMD_AHB_Strom_2_2_Fehlerkorrektur_20260629_.xml
4// Generated: 2026-04-22T18:25:39Z
5// Delegates unchanged conditions to UtilmdStromConditionEvaluatorFV2604 (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::UtilmdStromConditionEvaluatorFV2604;
14
15/// Condition evaluator for UTILMD_Strom FV2610.
16///
17/// Delegates to [`UtilmdStromConditionEvaluatorFV2604`] for conditions whose AHB description is
18/// unchanged from that version. Local overrides: [23, 24, 41, 63, 67, 79, 80, 81, 82, 158, 159, 181, 185, 186, 187, 203, 263, 272, 274, 275, 276, 353, 354, 381, 382, 383, 422, 423, 424, 531, 555, 571, 701, 2002].
19pub struct UtilmdStromConditionEvaluatorFV2610 {
20 fallback: UtilmdStromConditionEvaluatorFV2604,
21}
22
23impl Default for UtilmdStromConditionEvaluatorFV2610 {
24 fn default() -> Self {
25 Self {
26 fallback: UtilmdStromConditionEvaluatorFV2604::default(),
27 }
28 }
29}
30
31/// Condition IDs whose implementation differs from the fallback.
32const FV2610_OVERRIDES: &[u32] = &[
33 23, 24, 41, 63, 67, 79, 80, 81, 82, 158, 159, 181, 185, 186, 187, 203, 263, 272, 274, 275, 276,
34 353, 354, 381, 382, 383, 422, 423, 424, 531, 555, 571, 701, 2002,
35];
36
37impl ConditionEvaluator for UtilmdStromConditionEvaluatorFV2610 {
38 fn message_type(&self) -> &str {
39 "UTILMD_Strom"
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 23 => self.evaluate_23(ctx),
49 24 => self.evaluate_24(ctx),
50 41 => self.evaluate_41(ctx),
51 63 => self.evaluate_63(ctx),
52 67 => self.evaluate_67(ctx),
53 79 => self.evaluate_79(ctx),
54 80 => self.evaluate_80(ctx),
55 81 => self.evaluate_81(ctx),
56 82 => self.evaluate_82(ctx),
57 158 => self.evaluate_158(ctx),
58 159 => self.evaluate_159(ctx),
59 181 => self.evaluate_181(ctx),
60 203 => self.evaluate_203(ctx),
61 263 => self.evaluate_263(ctx),
62 353 => self.evaluate_353(ctx),
63 354 => self.evaluate_354(ctx),
64 381 => self.evaluate_381(ctx),
65 382 => self.evaluate_382(ctx),
66 383 => self.evaluate_383(ctx),
67 422 => self.evaluate_422(ctx),
68 423 => self.evaluate_423(ctx),
69 424 => self.evaluate_424(ctx),
70 531 => self.evaluate_531(ctx),
71 555 => self.evaluate_555(ctx),
72 571 => self.evaluate_571(ctx),
73 701 => self.evaluate_701(ctx),
74 2002 => self.evaluate_2002(ctx),
75 185 => self.evaluate_185(ctx),
76 186 => self.evaluate_186(ctx),
77 187 => self.evaluate_187(ctx),
78 272 => self.evaluate_272(ctx),
79 274 => self.evaluate_274(ctx),
80 275 => self.evaluate_275(ctx),
81 276 => self.evaluate_276(ctx),
82 other => self.fallback.evaluate(other, ctx),
83 }
84 }
85
86 fn is_external(&self, condition: u32) -> bool {
87 matches!(
88 condition,
89 181 | 185 | 186 | 187 | 274 | 275 | 276 | 353 | 354 | 381 | 382 | 383 | 422 | 423 | 424
90 ) || (!FV2610_OVERRIDES.contains(&condition) && self.fallback.is_external(condition))
91 }
92
93 fn is_known(&self, condition: u32) -> bool {
94 FV2610_OVERRIDES.contains(&condition) || self.fallback.is_known(condition)
95 }
96}
97
98impl UtilmdStromConditionEvaluatorFV2610 {
99 /// [23] Wenn in dieser SG4 das STS+E01++A05 (Status der Antwort) vorhanden
100 fn evaluate_23(&self, ctx: &EvaluationContext) -> ConditionResult {
101 // HAND-EDITED: "in dieser/derselben SG4" — the enclosing SG4 only, when the
102 // scope reaches one; the message as before otherwise.
103 if let Some(scope) = ctx.enclosing_scope("SG4") {
104 return ConditionResult::from(
105 ctx.find_segments_at(scope, "STS")
106 .iter()
107 .any(|s| s.get_element(0) == "E01" && s.get_component(2, 0) == "A05"),
108 );
109 }
110 ctx.has_segment_matching_in_group("STS", &[(0, 0, "E01"), (2, 0, "A05")], &["SG4"])
111 }
112
113 /// [24] Wenn in dieser SG4 das STS+E01++A25 (Status der Antwort) vorhanden
114 fn evaluate_24(&self, ctx: &EvaluationContext) -> ConditionResult {
115 // HAND-EDITED: "in dieser/derselben SG4" — the enclosing SG4 only, when the
116 // scope reaches one; the message as before otherwise.
117 if let Some(scope) = ctx.enclosing_scope("SG4") {
118 return ConditionResult::from(
119 ctx.find_segments_at(scope, "STS")
120 .iter()
121 .any(|s| s.get_element(0) == "E01" && s.get_component(2, 0) == "A25"),
122 );
123 }
124 ctx.has_segment_matching_in_group("STS", &[(0, 0, "E01"), (2, 0, "A25")], &["SG4"])
125 }
126
127 /// [41] Es ist eine Produktpaket-ID aus dem DE1050 von einem SG8 SEQ+Z79 (Bestandteil eines Produktpakets) zu nennen
128 // REVIEW: Cross-reference validation: the current field must contain a Produktpaket-ID from DE1050 (elements[1][0]) of some SG8 SEQ+Z79. Collects all valid Produktpaket-IDs across SG8 instances and checks the resolved field value is among them. Medium confidence: 'zu nennen' interpreted as a cross-reference constraint; if it is purely informational the body should return True unconditionally. (medium confidence)
129 fn evaluate_41(&self, ctx: &EvaluationContext) -> ConditionResult {
130 let nav = match ctx.navigator() {
131 Some(n) => n,
132 None => return ConditionResult::Unknown,
133 };
134 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
135 let mut valid_ids: std::collections::HashSet<String> = std::collections::HashSet::new();
136 for i in 0..sg8_count {
137 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
138 for seq in &seq_segs {
139 if seq
140 .elements
141 .first()
142 .and_then(|e| e.first())
143 .is_some_and(|v| v == "Z79")
144 {
145 if let Some(val) = seq.elements.get(1).and_then(|e| e.first()) {
146 if !val.is_empty() {
147 valid_ids.insert(val.clone());
148 }
149 }
150 }
151 }
152 }
153 if valid_ids.is_empty() {
154 return ConditionResult::Unknown;
155 }
156 if let Some(current_val) = ctx.resolved_value {
157 return ConditionResult::from(valid_ids.contains(current_val));
158 }
159 ConditionResult::Unknown
160 }
161
162 /// [63] Wenn in dieser SG4 das STS+E01++A15 (Status der Antwort) vorhanden
163 fn evaluate_63(&self, ctx: &EvaluationContext) -> ConditionResult {
164 // HAND-EDITED: "in dieser/derselben SG4" — the enclosing SG4 only, when the
165 // scope reaches one; the message as before otherwise.
166 if let Some(scope) = ctx.enclosing_scope("SG4") {
167 return ConditionResult::from(
168 ctx.find_segments_at(scope, "STS")
169 .iter()
170 .any(|s| s.get_element(0) == "E01" && s.get_component(2, 0) == "A15"),
171 );
172 }
173 ctx.has_segment_matching_in_group("STS", &[(0, 0, "E01"), (2, 0, "A15")], &["SG4"])
174 }
175
176 /// [67] Wenn in keinem SG8 SEQ+Z79 (Bestandteil eine Produktpakets) CCI+Z66/CAV+ZH9 (Produkteigenschaft/ Code der Produkteigenschaft) der Code 9991000002933 (Ruhende Marktlokation ausprägen) vorhanden ist.
177 // REVIEW: Absence check: returns True when NO SG8 with SEQ+Z79 has an SG10 child containing CCI+Z66 (Produkteigenschaft) co-occurring with CAV bearing value 9991000002933 (Ruhende Marktlokation ausprägen). Returns False as soon as the disqualifying combination is found. Medium confidence: CAV element layout for ZH9/9991000002933 is ambiguous without the MIG XML — implementation checks both ZH9+9991000002933 as a composite and 9991000002933 as a bare first component. (medium confidence)
178 fn evaluate_67(&self, ctx: &EvaluationContext) -> ConditionResult {
179 let nav = match ctx.navigator() {
180 Some(n) => n,
181 None => return ConditionResult::Unknown,
182 };
183 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
184 for i in 0..sg8_count {
185 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
186 let has_z79 = seq_segs.iter().any(|s| {
187 s.elements
188 .first()
189 .and_then(|e| e.first())
190 .is_some_and(|v| v == "Z79")
191 });
192 if !has_z79 {
193 continue;
194 }
195 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
196 for j in 0..sg10_count {
197 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
198 let has_cci_z66 = ccis.iter().any(|s| {
199 s.elements
200 .first()
201 .and_then(|e| e.first())
202 .is_some_and(|v| v == "Z66")
203 });
204 if has_cci_z66 {
205 let cavs =
206 nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
207 let has_target = cavs.iter().any(|s| {
208 let first_elem = s.elements.first();
209 let qualifier = first_elem.and_then(|e| e.first()).map(|v| v.as_str());
210 let value = first_elem.and_then(|e| e.get(1)).map(|v| v.as_str());
211 (qualifier == Some("ZH9") && value == Some("9991000002933"))
212 || qualifier == Some("9991000002933")
213 });
214 if has_target {
215 return ConditionResult::False;
216 }
217 }
218 }
219 }
220 ConditionResult::True
221 }
222
223 /// [79] Wenn SG4 STS+7++Z33 (Auszug wegen Stilllegung) vorhanden
224 fn evaluate_79(&self, ctx: &EvaluationContext) -> ConditionResult {
225 ctx.has_segment_matching_in_group("STS", &[(0, 0, "7"), (2, 0, "Z33")], &["SG4"])
226 }
227
228 /// [80] Wenn in derselben SG8 SEQ+Z61 (Produkt-Daten der Steuerbaren Ressource) das PIA+5 (Produkt-Daten der Steuerbaren Ressource) nicht vorhanden
229 fn evaluate_80(&self, ctx: &EvaluationContext) -> ConditionResult {
230 // HAND-EDITED: "in dieser/derselben SG8" — the enclosing SG8 only, when the
231 // scope reaches one; the message as before otherwise.
232 if let Some(scope) = ctx.enclosing_scope("SG8") {
233 return ConditionResult::from(
234 ctx.find_segments_at(scope, "SEQ")
235 .iter()
236 .any(|s| matches!(s.get_element(0), "Z61"))
237 && !ctx
238 .find_segments_at(scope, "PIA")
239 .iter()
240 .any(|s| s.get_element(0) == "5"),
241 );
242 }
243 ctx.any_group_has_qualifier_without("SEQ", 0, "Z61", "PIA", 0, "5", &["SG4", "SG8"])
244 }
245
246 /// [81] Wenn in derselben SG8 SEQ+Z61/ ZB3/ ZB4 (Produkt-Daten der Steuerbaren Ressource) das SG10 CCI+11 (Details zum Produkt der Steuerbaren Ressource) nicht vorhanden
247 // REVIEW: Multi-qualifier SEQ check (Z61/ZB3/ZB4) combined with SG10 child absence requires the navigator. Returns True when any SG8 with a qualifying SEQ has no SG10 child with CCI+11. Medium confidence: three-way qualifier match and SG10 absence via child group iteration. (medium confidence)
248 fn evaluate_81(&self, ctx: &EvaluationContext) -> ConditionResult {
249 // HAND-EDITED: "in dieser/derselben SG8" — the enclosing SG8 only, when the
250 // scope reaches one; the message as before otherwise.
251 if let Some(scope) = ctx.enclosing_scope("SG8") {
252 return ConditionResult::from(
253 ctx.find_segments_at(scope, "SEQ")
254 .iter()
255 .any(|s| matches!(s.get_element(0), "Z61" | "ZB3" | "ZB4"))
256 && !ctx
257 .find_segments_at(scope, "CCI")
258 .iter()
259 .any(|s| s.get_element(0) == "11"),
260 );
261 }
262 let nav = match ctx.navigator() {
263 Some(n) => n,
264 None => return ConditionResult::Unknown,
265 };
266 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
267 for i in 0..sg8_count {
268 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
269 let has_qualifying_seq = seq_segs.iter().any(|s| {
270 s.elements
271 .first()
272 .and_then(|e| e.first())
273 .is_some_and(|v| matches!(v.as_str(), "Z61" | "ZB3" | "ZB4"))
274 });
275 if !has_qualifying_seq {
276 continue;
277 }
278 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
279 let has_cci_11 = (0..sg10_count).any(|j| {
280 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
281 ccis.iter().any(|s| {
282 s.elements
283 .first()
284 .and_then(|e| e.first())
285 .is_some_and(|v| v == "11")
286 })
287 });
288 if !has_cci_11 {
289 return ConditionResult::True;
290 }
291 }
292 ConditionResult::False
293 }
294
295 /// [82] Wenn in der selben SG8 (Daten der technischen Einrichtungen) das SG10 CCI+Z63 (Information zu technischen Einrichtungen) CAV+ZH7 (Technische Einrichtungen vorhanden) vorhanden
296 // REVIEW: Checks if any SG10 child of any SG8 contains both CCI+Z63 (Information zu technischen Einrichtungen) and CAV+ZH7 (Technische Einrichtungen vorhanden) in the same SG10 instance. Both qualifiers checked at elements[0][0] following the CAV+qualifier pattern from Example 10. Medium confidence: no parent SG8 qualifier filter specified; CCI element position assumed from established pattern. (medium confidence)
297 fn evaluate_82(&self, ctx: &EvaluationContext) -> ConditionResult {
298 let nav = match ctx.navigator() {
299 Some(n) => n,
300 None => return ctx.has_qualifier("CAV", 0, "ZH7"),
301 };
302 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
303 for i in 0..sg8_count {
304 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
305 for j in 0..sg10_count {
306 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
307 let has_cci_z63 = ccis.iter().any(|s| {
308 s.elements
309 .first()
310 .and_then(|e| e.first())
311 .is_some_and(|v| v == "Z63")
312 });
313 if has_cci_z63 {
314 let cavs =
315 nav.find_segments_in_child_group("CAV", &["SG4", "SG8"], i, "SG10", j);
316 if cavs.iter().any(|s| {
317 s.elements
318 .first()
319 .and_then(|e| e.first())
320 .is_some_and(|v| v == "ZH7")
321 }) {
322 return ConditionResult::True;
323 }
324 }
325 }
326 }
327 ConditionResult::False
328 }
329
330 /// [158] Wenn in derselben SG8 SEQ+Z57/ ZD9 (OBIS-Daten der Netzlokation) das PIA+5 (OBIS-Daten der Netzlokation) nicht vorhanden
331 fn evaluate_158(&self, ctx: &EvaluationContext) -> ConditionResult {
332 // HAND-EDITED: "in dieser/derselben SG8" — the enclosing SG8 only, when the
333 // scope reaches one; the message as before otherwise.
334 if let Some(scope) = ctx.enclosing_scope("SG8") {
335 return ConditionResult::from(
336 ctx.find_segments_at(scope, "SEQ")
337 .iter()
338 .any(|s| matches!(s.get_element(0), "Z57" | "ZD9"))
339 && !ctx
340 .find_segments_at(scope, "PIA")
341 .iter()
342 .any(|s| s.get_element(0) == "5"),
343 );
344 }
345 ctx.any_group_has_qualifier_without("SEQ", 0, "Z57", "PIA", 0, "5", &["SG4", "SG8"])
346 .or(ctx.any_group_has_qualifier_without(
347 "SEQ",
348 0,
349 "ZD9",
350 "PIA",
351 0,
352 "5",
353 &["SG4", "SG8"],
354 ))
355 }
356
357 /// [159] Wenn in derselben SG8 SEQ+Z57/ ZD9 (OBIS-Daten der Netzlokation) das SG10 CCI+11 (OBIS-Daten der Netzlokation) nicht vor...
358 fn evaluate_159(&self, ctx: &EvaluationContext) -> ConditionResult {
359 // HAND-EDITED: "in dieser/derselben SG8" — the enclosing SG8 only, when the
360 // scope reaches one; the message as before otherwise.
361 if let Some(scope) = ctx.enclosing_scope("SG8") {
362 return ConditionResult::from(
363 ctx.find_segments_at(scope, "SEQ")
364 .iter()
365 .any(|s| matches!(s.get_element(0), "Z57" | "ZD9"))
366 && !ctx
367 .find_segments_at(scope, "CCI")
368 .iter()
369 .any(|s| s.get_element(0) == "11"),
370 );
371 }
372 let with_cci = |seq: &str| {
373 ctx.filtered_parent_child_has_qualifier(
374 &["SG4", "SG8"],
375 "SEQ",
376 0,
377 seq,
378 "SG10",
379 "CCI",
380 0,
381 "11",
382 )
383 };
384 with_cci("Z57").or(with_cci("ZD9")).negate()
385 }
386
387 /// [181] Wenn der Versender datenschutzrechtliche Voraussetzungen geschaffen hat, um die Daten bereitstellen zu dürfen
388 /// EXTERNAL: Requires context from outside the message.
389 fn evaluate_181(&self, ctx: &EvaluationContext) -> ConditionResult {
390 ctx.external
391 .evaluate("sender_has_data_protection_prerequisites")
392 }
393
394 /// [203] Wenn STS+7++E06 / Z39 / ZC6 / ZC7/ ZT6/ ZT7 / Z02 / ZZD vorhanden
395 fn evaluate_203(&self, ctx: &EvaluationContext) -> ConditionResult {
396 ctx.has_qualified_value(
397 "STS",
398 0,
399 "7",
400 2,
401 0,
402 &["E06", "Z39", "ZC6", "ZC7", "ZT6", "ZT7", "Z02", "ZZD"],
403 )
404 }
405
406 /// [263] Wenn SG8 SEQ+Z01 (Daten der Marktlokation) SG10 CCI+Z30++Z07 (Verbrauch) vorhanden
407 fn evaluate_263(&self, ctx: &EvaluationContext) -> ConditionResult {
408 let nav = match ctx.navigator() {
409 Some(n) => n,
410 None => return ctx.has_qualified_value("CCI", 0, "Z30", 2, 0, &["Z07"]),
411 };
412 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
413 for i in 0..sg8_count {
414 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
415 let has_z01 = seq_segs.iter().any(|s| {
416 s.elements
417 .first()
418 .and_then(|e| e.first())
419 .is_some_and(|v| v == "Z01")
420 });
421 if !has_z01 {
422 continue;
423 }
424 let sg10_count = nav.child_group_instance_count(&["SG4", "SG8"], i, "SG10");
425 for j in 0..sg10_count {
426 let ccis = nav.find_segments_in_child_group("CCI", &["SG4", "SG8"], i, "SG10", j);
427 for cci in &ccis {
428 let elem0 = cci
429 .elements
430 .first()
431 .and_then(|e| e.first())
432 .map(|s| s.as_str());
433 let elem2 = cci
434 .elements
435 .get(2)
436 .and_then(|e| e.first())
437 .map(|s| s.as_str());
438 if elem0 == Some("Z30") && elem2 == Some("Z07") {
439 return ConditionResult::True;
440 }
441 }
442 }
443 }
444 ConditionResult::False
445 }
446
447 /// [353] 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 ...
448 /// EXTERNAL: Requires context from outside the message.
449 fn evaluate_353(&self, ctx: &EvaluationContext) -> ConditionResult {
450 ctx.external
451 .evaluate("verwendungszweck_code_valid_nelocation_nb")
452 }
453
454 /// [354] 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 ...
455 /// EXTERNAL: Requires context from outside the message.
456 fn evaluate_354(&self, ctx: &EvaluationContext) -> ConditionResult {
457 ctx.external
458 .evaluate("verwendungszweck_code_valid_nelocation_lf")
459 }
460
461 /// [381] 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 ...
462 /// EXTERNAL: Requires context from outside the message.
463 fn evaluate_381(&self, ctx: &EvaluationContext) -> ConditionResult {
464 ctx.external
465 .evaluate("verwendungszweck_code_valid_malocation_nb")
466 }
467
468 /// [382] 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 ...
469 /// EXTERNAL: Requires context from outside the message.
470 fn evaluate_382(&self, ctx: &EvaluationContext) -> ConditionResult {
471 ctx.external
472 .evaluate("verwendungszweck_code_valid_malocation_lf")
473 }
474
475 /// [383] 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 ...
476 /// EXTERNAL: Requires context from outside the message.
477 fn evaluate_383(&self, ctx: &EvaluationContext) -> ConditionResult {
478 ctx.external
479 .evaluate("verwendungszweck_code_valid_malocation_uenb")
480 }
481
482 /// [422] 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...
483 /// EXTERNAL: Requires context from outside the message.
484 fn evaluate_422(&self, ctx: &EvaluationContext) -> ConditionResult {
485 ctx.external
486 .evaluate("verwendungszweck_code_valid_tranche_nb")
487 }
488
489 /// [423] 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...
490 /// EXTERNAL: Requires context from outside the message.
491 // REVIEW: References external code list from Kapitel 2 (Codeliste der Verwendungszwecke) filtered by 'Lokation/Tranche' and 'Verwendbar für Marktrolle/LF' columns, plus OBIS-Kennzahl matching — all three criteria require external business context unavailable in the EDIFACT message alone (medium confidence)
492 fn evaluate_423(&self, ctx: &EvaluationContext) -> ConditionResult {
493 ctx.external.evaluate("verwendungszweck_valid_for_lf")
494 }
495
496 /// [424] 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...
497 /// EXTERNAL: Requires context from outside the message.
498 // REVIEW: References external code list from Kapitel 2 (Codeliste der Verwendungszwecke) filtered by 'Lokation/Tranche' and 'Verwendbar für Marktrolle/ÜNB' columns, plus OBIS-Kennzahl matching — all three criteria require external business context unavailable in the EDIFACT message alone (medium confidence)
499 fn evaluate_424(&self, ctx: &EvaluationContext) -> ConditionResult {
500 ctx.external.evaluate("verwendungszweck_valid_for_uenb")
501 }
502
503 /// [531] Hinweis: Es ist das Jahr anzugeben in dem die nächste Netznutzungsabrechnung erfolgt. Diese Information ist zu der Zeitraum-ID anzugeben, welche SG6 RFF+Z49 (Verwendungszeitraum der Daten: Gültig...
504 fn evaluate_531(&self, _ctx: &EvaluationContext) -> ConditionResult {
505 // Hinweis: year of next Netznutzungsabrechnung to be stated for the Zeitraum-ID in SG6 RFF+Z49 — informational note, always applies
506 ConditionResult::True
507 }
508
509 /// [555] Hinweis: Es sind die Produktpaket-ID aus der Anmeldung zu nennen, welche nicht umgesetzt werden konnten
510 fn evaluate_555(&self, _ctx: &EvaluationContext) -> ConditionResult {
511 // Hinweis: Produktpaket-IDs from the Anmeldung that could not be implemented — informational note, always applies
512 ConditionResult::True
513 }
514
515 /// [571] Hinweis: Es sind alle erforderlichen Produkte aus der Anmeldung des LF des im selben SG8 genannten Produktpaket-ID zu nennen welche nicht umgesetzt werden konnten
516 fn evaluate_571(&self, _ctx: &EvaluationContext) -> ConditionResult {
517 // Hinweis: all required products from LF Anmeldung for the Produktpaket-ID in the same SG8 that could not be implemented — informational note, always applies
518 ConditionResult::True
519 }
520
521 /// [701] Hinweis: Es ist die Malo-ID der Tranche zu nennen, der die Technische Ressource zugeordnet ist
522 fn evaluate_701(&self, _ctx: &EvaluationContext) -> ConditionResult {
523 // Hinweis: MaLo-ID of the Tranche to which the Technische Ressource is assigned — informational note, always applies
524 ConditionResult::True
525 }
526
527 /// [2002] Für jede Produktpaket-ID im SG8 SEQ+Z79 (Bestandteil eines Produktpakets) DE1050 genau einmal anzugeben
528 fn evaluate_2002(&self, ctx: &EvaluationContext) -> ConditionResult {
529 let nav = match ctx.navigator() {
530 Some(n) => n,
531 None => return ConditionResult::Unknown,
532 };
533 let sg8_count = nav.group_instance_count(&["SG4", "SG8"]);
534 let mut seen = std::collections::HashSet::new();
535 for i in 0..sg8_count {
536 let seq_segs = nav.find_segments_in_group("SEQ", &["SG4", "SG8"], i);
537 for seq in &seq_segs {
538 if seq
539 .elements
540 .first()
541 .and_then(|e| e.first())
542 .is_some_and(|v| v == "Z79")
543 {
544 if let Some(val) = seq.elements.get(1).and_then(|e| e.first()) {
545 if !val.is_empty() && !seen.insert(val.clone()) {
546 return ConditionResult::False;
547 }
548 }
549 }
550 }
551 }
552 if seen.is_empty() {
553 ConditionResult::Unknown
554 } else {
555 ConditionResult::True
556 }
557 }
558
559 /// [185] Zulässig sind ausschließlich Codes aus der Spalte „Code“ der Codeliste der Verwendungszwecke (Kapitel 2), sofern in ders...
560 /// EXTERNAL: Requires context from outside the message.
561 fn evaluate_185(&self, ctx: &EvaluationContext) -> ConditionResult {
562 ctx.external
563 .evaluate("verwendungszweck_code_valid_malocation_nb_produkt")
564 }
565
566 /// [186] Zulässig sind ausschließlich Codes aus der Spalte „Code“ der Codeliste der Verwendungszwecke (Kapitel 2), sofern in ders...
567 /// EXTERNAL: Requires context from outside the message.
568 fn evaluate_186(&self, ctx: &EvaluationContext) -> ConditionResult {
569 ctx.external
570 .evaluate("verwendungszweck_code_valid_malocation_lf_produkt")
571 }
572
573 /// [187] Zulässig sind ausschließlich Codes aus der Spalte „Code“ der Codeliste der Verwendungszwecke (Kapitel 2), sofern in ders...
574 /// EXTERNAL: Requires context from outside the message.
575 fn evaluate_187(&self, ctx: &EvaluationContext) -> ConditionResult {
576 ctx.external
577 .evaluate("verwendungszweck_code_valid_malocation_uenb_produkt")
578 }
579
580 /// [274] Zulässig sind ausschließlich Codes aus der Spalte „Code“ der Codeliste der Verwendungszwecke (Kapitel 2), sofern in ders...
581 /// EXTERNAL: Requires context from outside the message.
582 fn evaluate_274(&self, ctx: &EvaluationContext) -> ConditionResult {
583 ctx.external
584 .evaluate("verwendungszweck_code_valid_tranche_nb_produkt")
585 }
586
587 /// [275] Zulässig sind ausschließlich Codes aus der Spalte „Code“ der Codeliste der Verwendungszwecke (Kapitel 2), sofern in ders...
588 /// EXTERNAL: Requires context from outside the message.
589 fn evaluate_275(&self, ctx: &EvaluationContext) -> ConditionResult {
590 ctx.external
591 .evaluate("verwendungszweck_code_valid_tranche_lf_produkt")
592 }
593
594 /// [276] Zulässig sind ausschließlich Codes aus der Spalte „Code“ der Codeliste der Verwendungszwecke (Kapitel 2), sofern in ders...
595 /// EXTERNAL: Requires context from outside the message.
596 fn evaluate_276(&self, ctx: &EvaluationContext) -> ConditionResult {
597 ctx.external
598 .evaluate("verwendungszweck_code_valid_tranche_uenb_produkt")
599 }
600
601 /// [272] Wenn im selben Segment im DE2379 der Code 106 vorhanden ist
602 fn evaluate_272(&self, ctx: &EvaluationContext) -> ConditionResult {
603 ConditionResult::from(ctx.self_segment_value_equals("DTM", 0, 2, "106"))
604 }
605}