1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Default, Serialize, Deserialize)]
5#[serde(rename_all = "camelCase")]
6pub struct Interchangedaten {
7 pub syntax_kennung: Option<String>,
8 pub absender_code: Option<String>,
9 pub empfaenger_code: Option<String>,
10 pub datum: Option<String>,
11 pub zeit: Option<String>,
12 pub interchange_ref: Option<String>,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
23#[serde(rename_all = "camelCase")]
24pub struct Nachrichtendaten {
25 pub unh_referenz: String,
26 pub nachrichten_typ: String,
27
28 #[serde(flatten, default)]
37 pub nachricht: serde_json::Map<String, serde_json::Value>,
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
42#[serde(rename_all = "camelCase")]
43pub struct Interchange<M, T> {
44 pub interchangedaten: Interchangedaten,
45 pub nachrichten: Vec<Nachricht<M, T>>,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
50#[serde(rename_all = "camelCase")]
51pub struct Nachricht<M, T> {
52 pub nachrichtendaten: Nachrichtendaten,
53 pub stammdaten: M,
54 pub transaktionen: Vec<T>,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize)]
65#[serde(rename_all = "camelCase")]
66pub struct Transaktion<D, S> {
67 #[serde(default)]
71 pub transaktionsdaten: D,
72 pub stammdaten: S,
73}
74
75pub type DynamicTransaktion = Transaktion<serde_json::Value, serde_json::Value>;
77pub type DynamicInterchange = Interchange<serde_json::Value, DynamicTransaktion>;
79pub type DynamicNachricht = Nachricht<serde_json::Value, DynamicTransaktion>;
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use serde_json::json;
86
87 #[test]
88 fn test_dynamic_interchange_serde_roundtrip() {
89 let interchange: DynamicInterchange = Interchange {
90 interchangedaten: Interchangedaten {
91 syntax_kennung: Some("UNOC".to_string()),
92 absender_code: Some("1234567890123".to_string()),
93 empfaenger_code: Some("9876543210987".to_string()),
94 datum: Some("260326".to_string()),
95 zeit: Some("1430".to_string()),
96 interchange_ref: Some("00001".to_string()),
97 },
98 nachrichten: vec![Nachricht {
99 nachrichtendaten: Nachrichtendaten {
100 unh_referenz: "00001".to_string(),
101 nachrichten_typ: "UTILMD".to_string(),
102 nachricht: Default::default(),
103 },
104 stammdaten: json!({"key": "value"}),
105 transaktionen: vec![
106 Transaktion {
107 transaktionsdaten: json!({"vorgangId": "1"}),
108 stammdaten: json!({"tx": 1}),
109 },
110 Transaktion {
111 transaktionsdaten: json!({"vorgangId": "2"}),
112 stammdaten: json!({"tx": 2}),
113 },
114 ],
115 }],
116 };
117
118 let json_str = serde_json::to_string(&interchange).unwrap();
119 let deserialized: DynamicInterchange = serde_json::from_str(&json_str).unwrap();
120
121 assert_eq!(
122 deserialized.interchangedaten.syntax_kennung,
123 Some("UNOC".to_string())
124 );
125 assert_eq!(
126 deserialized.interchangedaten.absender_code,
127 Some("1234567890123".to_string())
128 );
129 assert_eq!(
130 deserialized.interchangedaten.empfaenger_code,
131 Some("9876543210987".to_string())
132 );
133 assert_eq!(deserialized.nachrichten.len(), 1);
134 assert_eq!(
135 deserialized.nachrichten[0].nachrichtendaten.unh_referenz,
136 "00001"
137 );
138 assert_eq!(
139 deserialized.nachrichten[0].nachrichtendaten.nachrichten_typ,
140 "UTILMD"
141 );
142 assert_eq!(
143 deserialized.nachrichten[0].stammdaten,
144 json!({"key": "value"})
145 );
146 assert_eq!(deserialized.nachrichten[0].transaktionen.len(), 2);
147 }
148
149 #[test]
150 fn test_typed_interchange_serde_roundtrip() {
151 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
152 struct TestStamm {
153 name: String,
154 }
155
156 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
157 struct TestTx {
158 id: u32,
159 }
160
161 let interchange: Interchange<TestStamm, TestTx> = Interchange {
162 interchangedaten: Interchangedaten::default(),
163 nachrichten: vec![Nachricht {
164 nachrichtendaten: Nachrichtendaten {
165 unh_referenz: "REF1".to_string(),
166 nachrichten_typ: "ORDERS".to_string(),
167 nachricht: Default::default(),
168 },
169 stammdaten: TestStamm {
170 name: "test".to_string(),
171 },
172 transaktionen: vec![TestTx { id: 1 }, TestTx { id: 2 }],
173 }],
174 };
175
176 let json_str = serde_json::to_string(&interchange).unwrap();
177 let deserialized: Interchange<TestStamm, TestTx> = serde_json::from_str(&json_str).unwrap();
178
179 assert_eq!(deserialized.nachrichten.len(), 1);
180 assert_eq!(
181 deserialized.nachrichten[0].stammdaten,
182 TestStamm {
183 name: "test".to_string()
184 }
185 );
186 assert_eq!(deserialized.nachrichten[0].transaktionen.len(), 2);
187 assert_eq!(
188 deserialized.nachrichten[0].transaktionen[0],
189 TestTx { id: 1 }
190 );
191 assert_eq!(
192 deserialized.nachrichten[0].transaktionen[1],
193 TestTx { id: 2 }
194 );
195 }
196
197 #[test]
198 fn test_interchangedaten_camel_case_serialization() {
199 let data = Interchangedaten {
200 syntax_kennung: Some("UNOC".to_string()),
201 absender_code: Some("SENDER".to_string()),
202 empfaenger_code: None,
203 datum: None,
204 zeit: None,
205 interchange_ref: Some("REF".to_string()),
206 };
207
208 let json_value: serde_json::Value = serde_json::to_value(&data).unwrap();
209 let obj = json_value.as_object().unwrap();
210
211 assert!(obj.contains_key("syntaxKennung"));
213 assert!(obj.contains_key("absenderCode"));
214 assert!(obj.contains_key("empfaengerCode"));
215 assert!(obj.contains_key("datum"));
216 assert!(obj.contains_key("zeit"));
217 assert!(obj.contains_key("interchangeRef"));
218
219 assert!(!obj.contains_key("syntax_kennung"));
221 assert!(!obj.contains_key("absender_code"));
222 assert!(!obj.contains_key("empfaenger_code"));
223 assert!(!obj.contains_key("interchange_ref"));
224 }
225}