1use crate::EricError;
2use anyhow::anyhow;
3use quick_xml::de::from_str;
4use serde::Deserialize;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct ValidationIssue {
9 pub data_ticket: Option<String>,
10 pub field_identifier: Option<String>,
11 pub multi_line_index: Option<u32>,
12 pub form_sequence_number: Option<u32>,
13 pub rule_name: Option<String>,
14 pub error_code: Option<String>,
15 pub text: Option<String>,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct ValidationReport {
21 pub issues: Vec<ValidationIssue>,
23}
24
25impl ValidationReport {
26 pub fn parse(xml: &str) -> Result<Self, EricError> {
27 let xml_report = from_str::<XmlValidationReport>(xml).map_err(|err| anyhow!("{err}"))?;
28
29 let issues = xml_report
30 .issues
31 .into_iter()
32 .map(|issue| ValidationIssue {
33 data_ticket: issue.data_ticket,
34 field_identifier: issue.field_identifier,
35 multi_line_index: issue.multi_line_index,
36 form_sequence_number: issue.form_sequence_number,
37 rule_name: issue.rule_name,
38 error_code: issue.error_code,
39 text: issue.text,
40 })
41 .collect();
42
43 Ok(Self { issues })
44 }
45}
46
47#[derive(Debug, Deserialize)]
50struct XmlValidationReport {
51 #[serde(rename = "FehlerRegelpruefung", default)]
52 issues: Vec<XmlValidationIssue>,
53}
54
55#[derive(Debug, Deserialize)]
57struct XmlValidationIssue {
58 #[serde(rename = "Nutzdatenticket")]
59 data_ticket: Option<String>,
60 #[serde(rename = "Feldidentifikator")]
61 field_identifier: Option<String>,
62 #[serde(rename = "Mehrfachzeilenindex")]
63 multi_line_index: Option<u32>,
64 #[serde(rename = "LfdNrVordruck")]
65 form_sequence_number: Option<u32>,
66 #[serde(rename = "RegelName")]
67 rule_name: Option<String>,
68 #[serde(rename = "FachlicheFehlerId")]
69 error_code: Option<String>,
70 #[serde(rename = "Text")]
71 text: Option<String>,
72}
73
74#[cfg(test)]
75mod tests {
76 use crate::{EricApiPayload, EricError};
77
78 #[test]
79 fn parse_validation_report_from_api_error() {
80 let err = EricError::ApiError {
81 code: 610001002,
82 message: "Fehler waehrend der Plausibilitaetspruefung".to_string(),
83 payload: EricApiPayload::new(
84 r#"<?xml version="1.0" encoding="UTF-8"?>
85<EricBearbeiteVorgang xmlns="http://www.elster.de/EricXML/1.1/EricBearbeiteVorgang">
86 <FehlerRegelpruefung>
87 <Nutzdatenticket>-</Nutzdatenticket>
88 <Feldidentifikator>gcd:genInfo.report.id.accountingStandard</Feldidentifikator>
89 <Mehrfachzeilenindex>1</Mehrfachzeilenindex>
90 <LfdNrVordruck>1</LfdNrVordruck>
91 <FachlicheFehlerId>170105000</FachlicheFehlerId>
92 <Text>missing required attribute 'unitRef'</Text>
93 </FehlerRegelpruefung>
94</EricBearbeiteVorgang>"#
95 .to_string(),
96 String::new(),
97 ),
98 };
99
100 let report = err
101 .validation_report()
102 .expect("report should parse")
103 .unwrap();
104 assert_eq!(report.issues.len(), 1);
105
106 let issue = &report.issues[0];
107 assert_eq!(
108 issue.field_identifier.as_deref(),
109 Some("gcd:genInfo.report.id.accountingStandard")
110 );
111 assert_eq!(issue.multi_line_index, Some(1));
112 assert_eq!(issue.form_sequence_number, Some(1));
113 assert_eq!(issue.rule_name, None);
114 assert_eq!(issue.error_code.as_deref(), Some("170105000"));
115 assert!(issue
116 .text
117 .as_deref()
118 .unwrap_or_default()
119 .contains("unitRef"));
120 }
121}