swift_mt_message/messages/
mt202.rs1use crate::fields::*;
2use serde::{Deserialize, Serialize};
3use swift_mt_message_macros::{SwiftMessage, serde_swift_fields};
4
5#[serde_swift_fields]
10#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, SwiftMessage)]
11#[validation_rules(MT202_VALIDATION_RULES)]
12pub struct MT202 {
13 #[field("20", mandatory)]
15 pub field_20: GenericReferenceField,
16
17 #[field("21", mandatory)]
18 pub field_21: GenericReferenceField,
19
20 #[field("32A", mandatory)]
21 pub field_32a: Field32A,
22
23 #[field("58A", mandatory)]
24 pub field_58a: GenericBicField,
25
26 #[field("13C", optional)]
28 pub field_13c: Option<Vec<Field13C>>,
29
30 #[field("52A", optional)]
31 pub field_52a: Option<GenericBicField>,
32
33 #[field("52D", optional)]
34 pub field_52d: Option<GenericNameAddressField>,
35
36 #[field("53A", optional)]
37 pub field_53a: Option<GenericBicField>,
38
39 #[field("53B", optional)]
40 pub field_53b: Option<GenericPartyField>,
41
42 #[field("53D", optional)]
43 pub field_53d: Option<GenericNameAddressField>,
44
45 #[field("54A", optional)]
46 pub field_54a: Option<GenericBicField>,
47
48 #[field("54B", optional)]
49 pub field_54b: Option<GenericPartyField>,
50
51 #[field("54D", optional)]
52 pub field_54d: Option<GenericNameAddressField>,
53
54 #[field("56A", optional)]
55 pub field_56a: Option<GenericBicField>,
56
57 #[field("56C", optional)]
58 pub field_56c: Option<GenericAccountField>,
59
60 #[field("56D", optional)]
61 pub field_56d: Option<GenericNameAddressField>,
62
63 #[field("57A", optional)]
64 pub field_57a: Option<GenericBicField>,
65
66 #[field("57B", optional)]
67 pub field_57b: Option<GenericPartyField>,
68
69 #[field("57C", optional)]
70 pub field_57c: Option<GenericAccountField>,
71
72 #[field("57D", optional)]
73 pub field_57d: Option<GenericNameAddressField>,
74
75 #[field("72", optional)]
76 pub field_72: Option<GenericMultiLine6x35>,
77
78 #[field("50A", optional)]
81 pub field_50a: Option<Field50>,
82
83 #[field("50", optional)]
84 pub field_50: Option<Field50>,
85
86 #[field("59A", optional)]
87 pub field_59a: Option<Field59>,
88
89 #[field("59", optional)]
90 pub field_59: Option<Field59>,
91
92 #[field("70", optional)]
93 pub field_70: Option<GenericMultiLine4x35>,
94
95 #[field("33B", optional)]
96 pub field_33b: Option<GenericCurrencyAmountField>,
97}
98
99impl MT202 {
100 pub fn has_reject_codes(&self) -> bool {
107 if self.field_20.value.to_uppercase().contains("REJT") {
109 return true;
110 }
111
112 if let Some(field_72) = &self.field_72 {
114 let content = field_72.lines.join(" ").to_uppercase();
115 if content.contains("/REJT/") || content.contains("REJT") {
116 return true;
117 }
118 }
119
120 false
121 }
122
123 pub fn has_return_codes(&self) -> bool {
130 if self.field_20.value.to_uppercase().contains("RETN") {
132 return true;
133 }
134
135 if let Some(field_72) = &self.field_72 {
137 let content = field_72.lines.join(" ").to_uppercase();
138 if content.contains("/RETN/") || content.contains("RETN") {
139 return true;
140 }
141 }
142
143 false
144 }
145
146 pub fn is_cover_message(&self) -> bool {
152 (self.field_50a.is_some() || self.field_50.is_some())
154 && (self.field_59a.is_some() || self.field_59.is_some())
155 }
156}
157
158const MT202_VALIDATION_RULES: &str = r#"{
159 "rules": [
160 {
161 "id": "C1",
162 "description": "If 56a is present, 57a becomes mandatory",
163 "condition": {
164 "if": [
165 {"or": [
166 {"var": "field_56a.is_some"},
167 {"var": "field_56d.is_some"}
168 ]},
169 {"or": [
170 {"var": "field_57a.is_some"},
171 {"var": "field_57b.is_some"},
172 {"var": "field_57d.is_some"}
173 ]},
174 true
175 ]
176 }
177 }
178 ],
179 "constants": {
180 "VALID_TIME_CODES": ["CLS", "RNC", "SND"],
181 "VALID_INSTRUCTION_CODES": ["/INT/", "/COV/", "/REIMBURSEMENT/", "/SETTLEMENT/", "/SDVA/", "/RETN/", "/REJT/"]
182 }
183}"#;