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_SEQUENCE_B_VALIDATION_RULES)]
12pub struct MT202SequenceB {
13 #[field("50A", mandatory)]
15 pub field_50a: Field50,
16
17 #[field("59A", mandatory)]
18 pub field_59a: Field59,
19
20 #[field("52A", optional)]
22 pub field_52a: Option<GenericBicField>,
23
24 #[field("52D", optional)]
25 pub field_52d: Option<GenericNameAddressField>,
26
27 #[field("56A", optional)]
28 pub field_56a: Option<GenericBicField>,
29
30 #[field("56C", optional)]
31 pub field_56c: Option<GenericAccountField>,
32
33 #[field("56D", optional)]
34 pub field_56d: Option<GenericNameAddressField>,
35
36 #[field("57A", optional)]
37 pub field_57a: Option<GenericBicField>,
38
39 #[field("57B", optional)]
40 pub field_57b: Option<GenericPartyField>,
41
42 #[field("57C", optional)]
43 pub field_57c: Option<GenericAccountField>,
44
45 #[field("57D", optional)]
46 pub field_57d: Option<GenericNameAddressField>,
47
48 #[field("70", optional)]
49 pub field_70: Option<GenericMultiLine4x35>,
50
51 #[field("72", optional)]
52 pub field_72: Option<GenericMultiLine6x35>,
53
54 #[field("33B", optional)]
55 pub field_33b: Option<GenericCurrencyAmountField>,
56}
57
58const MT202_SEQUENCE_B_VALIDATION_RULES: &str = r#"{
59 "rules": [
60 {
61 "id": "C1",
62 "description": "If 56a is present, 57a becomes mandatory",
63 "condition": true
64 }
65 ]
66}"#;
67
68#[serde_swift_fields]
73#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, SwiftMessage)]
74#[validation_rules(MT202_VALIDATION_RULES)]
75pub struct MT202 {
76 #[field("20", mandatory)]
78 pub field_20: GenericReferenceField,
79
80 #[field("21", mandatory)]
81 pub field_21: GenericReferenceField,
82
83 #[field("32A", mandatory)]
84 pub field_32a: Field32A,
85
86 #[field("58A", mandatory)]
87 pub field_58a: GenericBicField,
88
89 #[field("13C", optional)]
91 pub field_13c: Option<Vec<Field13C>>,
92
93 #[field("52A", optional)]
94 pub field_52a: Option<GenericBicField>,
95
96 #[field("52D", optional)]
97 pub field_52d: Option<GenericNameAddressField>,
98
99 #[field("53A", optional)]
100 pub field_53a: Option<GenericBicField>,
101
102 #[field("53B", optional)]
103 pub field_53b: Option<GenericPartyField>,
104
105 #[field("53D", optional)]
106 pub field_53d: Option<GenericNameAddressField>,
107
108 #[field("54A", optional)]
109 pub field_54a: Option<GenericBicField>,
110
111 #[field("54B", optional)]
112 pub field_54b: Option<GenericPartyField>,
113
114 #[field("54D", optional)]
115 pub field_54d: Option<GenericNameAddressField>,
116
117 #[field("56A", optional)]
118 pub field_56a: Option<GenericBicField>,
119
120 #[field("56D", optional)]
121 pub field_56d: Option<GenericNameAddressField>,
122
123 #[field("57A", optional)]
124 pub field_57a: Option<GenericBicField>,
125
126 #[field("57B", optional)]
127 pub field_57b: Option<GenericPartyField>,
128
129 #[field("57D", optional)]
130 pub field_57d: Option<GenericNameAddressField>,
131
132 #[field("72", optional)]
133 pub field_72: Option<GenericMultiLine6x35>,
134
135 #[field("SEQUENCE_B", optional)]
138 pub sequence_b: Option<MT202SequenceB>,
139}
140
141impl MT202 {
142 pub fn has_reject_codes(&self) -> bool {
149 if self.field_20.value.to_uppercase().contains("REJT") {
151 return true;
152 }
153
154 if let Some(field_72) = &self.field_72 {
156 let content = field_72.lines.join(" ").to_uppercase();
157 if content.contains("/REJT/") || content.contains("REJT") {
158 return true;
159 }
160 }
161
162 false
163 }
164
165 pub fn has_return_codes(&self) -> bool {
172 if self.field_20.value.to_uppercase().contains("RETN") {
174 return true;
175 }
176
177 if let Some(field_72) = &self.field_72 {
179 let content = field_72.lines.join(" ").to_uppercase();
180 if content.contains("/RETN/") || content.contains("RETN") {
181 return true;
182 }
183 }
184
185 false
186 }
187
188 pub fn is_cover_message(&self) -> bool {
194 self.sequence_b.is_some()
196 }
197}
198
199const MT202_VALIDATION_RULES: &str = r#"{
200 "rules": [
201 {
202 "id": "C1",
203 "description": "If 56a is present, 57a becomes mandatory",
204 "condition": {
205 "if": [
206 {"or": [
207 {"var": "field_56a.is_some"},
208 {"var": "field_56d.is_some"}
209 ]},
210 {"or": [
211 {"var": "field_57a.is_some"},
212 {"var": "field_57b.is_some"},
213 {"var": "field_57d.is_some"}
214 ]},
215 true
216 ]
217 }
218 }
219 ],
220 "constants": {
221 "VALID_TIME_CODES": ["CLS", "RNC", "SND"],
222 "VALID_INSTRUCTION_CODES": ["/INT/", "/COV/", "/REIMBURSEMENT/", "/SETTLEMENT/", "/SDVA/", "/RETN/", "/REJT/"]
223 }
224}"#;