swift_mt_message/messages/
mt202.rs1use crate::errors::{ParseError, SwiftValidationError};
2use crate::fields::*;
3use crate::parser::MessageParser;
4use crate::parser::utils::*;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
9pub struct MT202SequenceB {
10 #[serde(flatten, skip_serializing_if = "Option::is_none")]
12 pub ordering_customer: Option<Field50OrderingCustomerAFK>,
13
14 #[serde(flatten, skip_serializing_if = "Option::is_none")]
16 pub ordering_institution: Option<Field52OrderingInstitution>,
17
18 #[serde(flatten, skip_serializing_if = "Option::is_none")]
20 pub intermediary: Option<Field56Intermediary>,
21
22 #[serde(flatten, skip_serializing_if = "Option::is_none")]
24 pub account_with_institution: Option<Field57AccountWithInstitution>,
25
26 #[serde(flatten, skip_serializing_if = "Option::is_none")]
28 pub beneficiary_customer: Option<Field59>,
29
30 #[serde(rename = "70", skip_serializing_if = "Option::is_none")]
32 pub remittance_information: Option<Field70>,
33
34 #[serde(rename = "72", skip_serializing_if = "Option::is_none")]
36 pub sender_to_receiver_information: Option<Field72>,
37
38 #[serde(rename = "33B", skip_serializing_if = "Option::is_none")]
40 pub currency_amount: Option<Field33B>,
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
51pub struct MT202 {
52 #[serde(rename = "20")]
54 pub field_20: Field20,
55
56 #[serde(rename = "21")]
58 pub field_21: Field21NoOption,
59
60 #[serde(rename = "13C", skip_serializing_if = "Option::is_none")]
62 pub field_13c: Option<Vec<Field13C>>,
63
64 #[serde(rename = "32A")]
66 pub field_32a: Field32A,
67
68 #[serde(flatten, skip_serializing_if = "Option::is_none")]
70 pub field_52: Option<Field52OrderingInstitution>,
71
72 #[serde(flatten, skip_serializing_if = "Option::is_none")]
74 pub field_53: Option<Field53SenderCorrespondent>,
75
76 #[serde(flatten, skip_serializing_if = "Option::is_none")]
78 pub field_54: Option<Field54ReceiverCorrespondent>,
79
80 #[serde(flatten, skip_serializing_if = "Option::is_none")]
82 pub field_56: Option<Field56Intermediary>,
83
84 #[serde(flatten, skip_serializing_if = "Option::is_none")]
86 pub field_57: Option<Field57AccountWithInstitution>,
87
88 #[serde(flatten)]
90 pub field_58: Field58,
91
92 #[serde(rename = "72", skip_serializing_if = "Option::is_none")]
94 pub field_72: Option<Field72>,
95
96 #[serde(rename = "#", skip_serializing_if = "Option::is_none")]
98 pub sequence_b: Option<MT202SequenceB>,
99}
100
101impl MT202 {
102 pub fn parse_from_block4(block4: &str) -> Result<Self, ParseError> {
104 let mut parser = MessageParser::new(block4, "202");
105
106 let field_20 = parser.parse_field::<Field20>("20")?;
108 let field_21 = parser.parse_field::<Field21NoOption>("21")?;
109
110 parser = parser.with_duplicates(true);
112 let mut time_indications = Vec::new();
113 while let Ok(field) = parser.parse_field::<Field13C>("13C") {
114 time_indications.push(field);
115 }
116 parser = parser.with_duplicates(false);
117
118 let field_13c = if time_indications.is_empty() {
119 None
120 } else {
121 Some(time_indications)
122 };
123
124 let field_32a = parser.parse_field::<Field32A>("32A")?;
126
127 let field_52 = parser.parse_optional_variant_field::<Field52OrderingInstitution>("52")?;
129 let field_53 = parser.parse_optional_variant_field::<Field53SenderCorrespondent>("53")?;
130 let field_54 = parser.parse_optional_variant_field::<Field54ReceiverCorrespondent>("54")?;
131 let field_56 = parser.parse_optional_variant_field::<Field56Intermediary>("56")?;
132 let field_57 =
133 parser.parse_optional_variant_field::<Field57AccountWithInstitution>("57")?;
134
135 let field_58 = parser.parse_variant_field::<Field58>("58")?;
137
138 let field_72 = parser.parse_optional_field::<Field72>("72")?;
140
141 parser = parser.with_duplicates(true);
144
145 let ordering_customer =
146 parser.parse_optional_variant_field::<Field50OrderingCustomerAFK>("50")?;
147 let ordering_institution =
148 parser.parse_optional_variant_field::<Field52OrderingInstitution>("52")?;
149 let intermediary = parser.parse_optional_variant_field::<Field56Intermediary>("56")?;
150 let account_with_institution =
151 parser.parse_optional_variant_field::<Field57AccountWithInstitution>("57")?;
152 let beneficiary_customer = parser.parse_optional_variant_field::<Field59>("59")?;
153 let remittance_information = parser.parse_optional_field::<Field70>("70")?;
154 let sender_to_receiver_information = parser.parse_optional_field::<Field72>("72")?;
155 let currency_amount = parser.parse_optional_field::<Field33B>("33B")?;
156
157 let sequence_b = if ordering_customer.is_some()
159 || ordering_institution.is_some()
160 || intermediary.is_some()
161 || account_with_institution.is_some()
162 || beneficiary_customer.is_some()
163 || remittance_information.is_some()
164 || sender_to_receiver_information.is_some()
165 || currency_amount.is_some()
166 {
167 Some(MT202SequenceB {
168 ordering_customer,
169 ordering_institution,
170 intermediary,
171 account_with_institution,
172 beneficiary_customer,
173 remittance_information,
174 sender_to_receiver_information,
175 currency_amount,
176 })
177 } else {
178 None
179 };
180
181 Ok(MT202 {
182 field_20,
183 field_21,
184 field_13c,
185 field_32a,
186 field_52,
187 field_53,
188 field_54,
189 field_56,
190 field_57,
191 field_58,
192 field_72,
193 sequence_b,
194 })
195 }
196
197 fn has_intermediary_in_seq_a(&self) -> bool {
207 self.field_56.is_some()
208 }
209
210 fn has_account_with_in_seq_a(&self) -> bool {
212 self.field_57.is_some()
213 }
214
215 fn has_intermediary_in_seq_b(&self) -> bool {
217 self.sequence_b
218 .as_ref()
219 .map(|seq_b| seq_b.intermediary.is_some())
220 .unwrap_or(false)
221 }
222
223 fn has_account_with_in_seq_b(&self) -> bool {
225 self.sequence_b
226 .as_ref()
227 .map(|seq_b| seq_b.account_with_institution.is_some())
228 .unwrap_or(false)
229 }
230
231 fn validate_c1_intermediary_seq_a(&self) -> Option<SwiftValidationError> {
238 if self.has_intermediary_in_seq_a() && !self.has_account_with_in_seq_a() {
239 return Some(SwiftValidationError::business_error(
240 "C81",
241 "57a",
242 vec!["56a".to_string()],
243 "Field 57a (Account With Institution) is mandatory when field 56a (Intermediary) is present in Sequence A",
244 "If field 56a is present in sequence A, then field 57a must also be present in sequence A",
245 ));
246 }
247 None
248 }
249
250 fn validate_c2_intermediary_seq_b(&self) -> Option<SwiftValidationError> {
253 if self.has_intermediary_in_seq_b() && !self.has_account_with_in_seq_b() {
254 return Some(SwiftValidationError::business_error(
255 "C68",
256 "57a",
257 vec!["56a".to_string()],
258 "Field 57a (Account With Institution) is mandatory when field 56a (Intermediary) is present in Sequence B",
259 "If field 56a is present in sequence B, then field 57a must also be present in sequence B",
260 ));
261 }
262 None
263 }
264
265 pub fn validate_network_rules(&self, stop_on_first_error: bool) -> Vec<SwiftValidationError> {
268 let mut all_errors = Vec::new();
269
270 if let Some(error) = self.validate_c1_intermediary_seq_a() {
272 all_errors.push(error);
273 if stop_on_first_error {
274 return all_errors;
275 }
276 }
277
278 if let Some(error) = self.validate_c2_intermediary_seq_b() {
280 all_errors.push(error);
281 if stop_on_first_error {
282 return all_errors;
283 }
284 }
285
286 all_errors
287 }
288
289 pub fn has_reject_codes(&self) -> bool {
291 if let Some(ref info) = self.field_72 {
292 info.information
293 .iter()
294 .any(|line| line.contains("/REJT/") || line.contains("/RJT/"))
295 } else {
296 false
297 }
298 }
299
300 pub fn has_return_codes(&self) -> bool {
302 if let Some(ref info) = self.field_72 {
303 info.information
304 .iter()
305 .any(|line| line.contains("/RETN/") || line.contains("/RET/"))
306 } else {
307 false
308 }
309 }
310
311 pub fn is_cover_message(&self) -> bool {
313 self.sequence_b
315 .as_ref()
316 .map(|seq_b| seq_b.ordering_customer.is_some() || seq_b.beneficiary_customer.is_some())
317 .unwrap_or(false)
318 }
319}
320
321impl crate::traits::SwiftMessageBody for MT202 {
322 fn message_type() -> &'static str {
323 "202"
324 }
325
326 fn parse_from_block4(block4: &str) -> Result<Self, crate::errors::ParseError> {
327 Self::parse_from_block4(block4)
328 }
329
330 fn to_mt_string(&self) -> String {
331 let mut result = String::new();
332
333 append_field(&mut result, &self.field_20);
335 append_field(&mut result, &self.field_21);
336 append_vec_field(&mut result, &self.field_13c);
337 append_field(&mut result, &self.field_32a);
338 append_optional_field(&mut result, &self.field_52);
339 append_optional_field(&mut result, &self.field_53);
340 append_optional_field(&mut result, &self.field_54);
341 append_optional_field(&mut result, &self.field_56);
342 append_optional_field(&mut result, &self.field_57);
343 append_field(&mut result, &self.field_58);
344 append_optional_field(&mut result, &self.field_72);
345
346 if let Some(ref seq_b) = self.sequence_b {
348 append_optional_field(&mut result, &seq_b.ordering_customer);
349 append_optional_field(&mut result, &seq_b.ordering_institution);
350 append_optional_field(&mut result, &seq_b.intermediary);
351 append_optional_field(&mut result, &seq_b.account_with_institution);
352 append_optional_field(&mut result, &seq_b.beneficiary_customer);
353 append_optional_field(&mut result, &seq_b.remittance_information);
354 append_optional_field(&mut result, &seq_b.sender_to_receiver_information);
355 append_optional_field(&mut result, &seq_b.currency_amount);
356 }
357
358 finalize_mt_string(result, false)
359 }
360
361 fn validate_network_rules(&self, stop_on_first_error: bool) -> Vec<SwiftValidationError> {
362 MT202::validate_network_rules(self, stop_on_first_error)
364 }
365}