swift_mt_message/messages/mt202.rs
1use crate::fields::*;
2use serde::{Deserialize, Serialize};
3use swift_mt_message_macros::{SwiftMessage, serde_swift_fields};
4
5/// MT202: General Financial Institution Transfer
6///
7/// ## Purpose
8/// Used for financial institution-to-financial institution payments where both the ordering
9/// and beneficiary customers are financial institutions. This message facilitates transfers
10/// of funds between institutions for their own account or on behalf of third parties.
11///
12/// ## Scope
13/// This message is:
14/// - Sent between financial institutions for interbank transfers
15/// - Used for settlement of obligations between financial institutions
16/// - Applicable for both cover payments (with underlying customer details) and direct institution transfers
17/// - Compatible with real-time gross settlement (RTGS) systems
18/// - Subject to SRG2025 contingency processing for FI-to-FI transfers
19///
20/// ## Key Features
21/// - **Dual Sequence Structure**:
22/// - Sequence A: Basic interbank transfer details
23/// - Sequence B: Cover payment details (when applicable)
24/// - **Flexible Routing**: Support for correspondent banking chains through fields 52-57
25/// - **Cover Payment Detection**: Automatic identification of cover vs. direct transfers
26/// - **Reject/Return Handling**: Built-in support for payment exception processing
27/// - **Settlement Integration**: Compatible with various settlement methods and systems
28/// - **SRG2025 Compliance**: Enhanced network validation rules for contingency processing
29///
30/// ## Common Use Cases
31/// - Interbank settlement transactions
32/// - Cover payments for underlying customer transfers
33/// - Foreign exchange settlement
34/// - Correspondent banking transfers
35/// - Central bank operations
36/// - Cross-border payment settlement
37/// - SWIFT gpi (global payments innovation) transactions
38///
39/// ## Message Structure
40/// ### Sequence A (Mandatory)
41/// - **Field 20**: Transaction Reference (mandatory) - Unique sender reference
42/// - **Field 21**: Related Reference (mandatory) - Reference to related message/transaction
43/// - **Field 13C**: Time Indication (optional, repetitive) - Processing time constraints
44/// - **Field 32A**: Value Date/Currency/Amount (mandatory) - Settlement details
45/// - **Field 52**: Ordering Institution (optional) - Institution initiating the transfer
46/// - **Field 53**: Sender's Correspondent (optional) - Sender's correspondent bank
47/// - **Field 54**: Receiver's Correspondent (optional) - Receiver's correspondent bank
48/// - **Field 56**: Intermediary Institution (optional) - Intermediary in the payment chain
49/// - **Field 57**: Account With Institution (optional) - Final crediting institution
50/// - **Field 58**: Beneficiary Institution (mandatory) - Final beneficiary institution
51/// - **Field 72**: Sender to Receiver Information (optional) - Additional instructions
52///
53/// ### Sequence B (Optional - Cover Payment Details)
54/// - **Field 50**: Ordering Customer (optional) - Underlying ordering customer
55/// - **Field 52**: Ordering Institution (optional) - Ordering institution details for cover
56/// - **Field 56**: Intermediary Institution (optional) - Intermediary for cover payment
57/// - **Field 57**: Account With Institution (optional) - Account details for cover
58/// - **Field 59**: Beneficiary Customer (optional) - Underlying beneficiary customer
59/// - **Field 70**: Remittance Information (optional) - Payment purpose/details
60/// - **Field 72**: Sender to Receiver Info (optional) - Cover-specific instructions
61/// - **Field 33B**: Currency/Instructed Amount (optional) - Original instructed amount
62///
63/// ## Network Validation Rules
64/// - **Intermediary Chain Validation**: If field 56 is present, field 57 becomes mandatory
65/// - **Cover Payment Structure**: Validation of Sequence B customer fields for cover detection
66/// - **Cross-border Compliance**: Enhanced validation for contingency processing (SRG2025)
67/// - **Settlement Method Validation**: Proper correspondent banking chain validation
68/// - **Time Indication Compliance**: CLS/TARGET timing constraint validation
69/// - **Reference Format Validation**: Proper format validation for all reference fields
70/// - **REJT/RETN Indicators**: Structured validation of reject/return codes in field 72
71///
72/// ## SRG2025 Status
73/// - **Structural Changes**: Enhanced - Additional network validated rules for contingency processing
74/// - **Validation Updates**: Contingency processing applicable to FI-to-FI transfers
75/// - **Processing Improvements**: ISO 20022 automatic conversion for compliant messages
76/// - **Compliance Notes**: Scope includes FI-to-FI including MA-CUGs (excludes SCORE, MI-CUGs)
77///
78/// ## Integration Considerations
79/// - **Banking Systems**: Compatible with real-time gross settlement (RTGS) systems and net settlement systems
80/// - **API Integration**: RESTful API support for modern interbank payment platforms
81/// - **Processing Requirements**: Supports correspondent banking arrangements and central bank settlement
82/// - **Compliance Integration**: Built-in support for cross-currency settlement and regulatory reporting
83///
84/// ## Relationship to Other Messages
85/// - **Triggers**: Often triggered by MT103 customer payments requiring cover or institutional settlement
86/// - **Responses**: May generate MT900/MT910 (confirmations) or MT292/MT296 (reject notifications)
87/// - **Related**: Works with MT205 (with mandatory ordering institution) and account reporting messages
88/// - **Alternatives**: MT205 for transfers requiring explicit ordering institution identification
89/// - **Status Updates**: May receive MT192/MT196/MT199 for status notifications and inquiry responses
90
91#[serde_swift_fields]
92#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, SwiftMessage)]
93#[validation_rules(MT202_VALIDATION_RULES)]
94pub struct MT202 {
95 #[field("20")]
96 pub field_20: Field20,
97
98 #[field("21")]
99 pub field_21: Field21NoOption,
100
101 #[field("13C")]
102 pub field_13c: Option<Vec<Field13C>>,
103
104 #[field("32A")]
105 pub field_32a: Field32A,
106
107 #[field("52")]
108 pub field_52: Option<Field52OrderingInstitution>,
109
110 #[field("53")]
111 pub field_53: Option<Field53SenderCorrespondent>,
112
113 #[field("54")]
114 pub field_54: Option<Field54ReceiverCorrespondent>,
115
116 #[field("56")]
117 pub field_56: Option<Field56Intermediary>,
118
119 #[field("57")]
120 pub field_57: Option<Field57AccountWithInstitution>,
121
122 #[field("58")]
123 pub field_58: Field58,
124
125 #[field("72")]
126 pub field_72: Option<Field72>,
127
128 #[field("50#b")]
129 pub field_50_seq_b: Option<Field50OrderingCustomerAFK>,
130
131 #[field("52#b")]
132 pub field_52_seq_b: Option<Field52OrderingInstitution>,
133
134 #[field("56#b")]
135 pub field_56_seq_b: Option<Field56Intermediary>,
136
137 #[field("57#b")]
138 pub field_57_seq_b: Option<Field57AccountWithInstitution>,
139
140 #[field("59#b")]
141 pub field_59_seq_b: Option<Field59>,
142
143 #[field("70#b")]
144 pub field_70_seq_b: Option<Field70>,
145
146 #[field("72#b")]
147 pub field_72_seq_b: Option<Field72>,
148
149 #[field("33B#b")]
150 pub field_33b_seq_b: Option<Field33B>,
151}
152
153impl MT202 {
154 /// Check if this MT202 message contains reject codes
155 ///
156 /// Reject messages are identified by checking:
157 /// 1. Field 20 (Transaction Reference) for "REJT" prefix or content
158 /// 2. Field 72 (Sender to Receiver Information) containing `/REJT/` codes
159 /// 3. Additional structured reject information in field 72
160 pub fn has_reject_codes(&self) -> bool {
161 // Check field 20 (transaction reference)
162 if self.field_20.reference.to_uppercase().contains("REJT") {
163 return true;
164 }
165
166 // Check field 72 for structured reject codes
167 if let Some(field_72) = &self.field_72 {
168 let content = field_72.information.join(" ").to_uppercase();
169 if content.contains("/REJT/") || content.contains("REJT") {
170 return true;
171 }
172 }
173
174 false
175 }
176
177 /// Check if this MT202 message contains return codes
178 ///
179 /// Return messages are identified by checking:
180 /// 1. Field 20 (Transaction Reference) for "RETN" prefix or content
181 /// 2. Field 72 (Sender to Receiver Information) containing `/RETN/` codes
182 /// 3. Additional structured return information in field 72
183 pub fn has_return_codes(&self) -> bool {
184 // Check field 20 (transaction reference)
185 if self.field_20.reference.to_uppercase().contains("RETN") {
186 return true;
187 }
188
189 // Check field 72 for structured return codes
190 if let Some(field_72) = &self.field_72 {
191 let content = field_72.information.join(" ").to_uppercase();
192 if content.contains("/RETN/") || content.contains("RETN") {
193 return true;
194 }
195 }
196
197 false
198 }
199
200 /// Check if this MT202 message is a Cover (COV) message
201 ///
202 /// COV messages are distinguished by:
203 /// - Presence of customer fields (50A/50 and 59A/59) indicating underlying customer details
204 /// - Field 121 (UETR) in Block 3 is typically mandatory for COV messages
205 pub fn is_cover_message(&self) -> bool {
206 // COV messages contain customer fields that indicate underlying customer credit transfer details
207 self.field_50_seq_b.is_some() && (self.field_59_seq_b.is_some())
208 }
209}
210
211const MT202_VALIDATION_RULES: &str = r#"{
212 "rules": [
213 {
214 "id": "C1",
215 "description": "If field 56a is present, then field 57a must also be present",
216 "condition": {
217 "if": [
218 {"exists": ["fields", "56"]},
219 {"exists": ["fields", "57"]},
220 true
221 ]
222 }
223 },
224 {
225 "id": "C2",
226 "description": "If field 56a is present in Sequence B, then field 57a must also be present",
227 "condition": {
228 "if": [
229 {"exists": ["fields", "56#b"]},
230 {"exists": ["fields", "57#b"]},
231 true
232 ]
233 }
234 },
235 {
236 "id": "COV_FIELDS",
237 "description": "MT202 COV must include both field 50a (Ordering Customer) and 59a (Beneficiary)",
238 "condition": {
239 "if": [
240 {"or": [
241 {"exists": ["fields", "50#b"]},
242 {"exists": ["fields", "59#b"]}
243 ]},
244 {"and": [
245 {"exists": ["fields", "50#b"]},
246 {"exists": ["fields", "59#b"]}
247 ]},
248 true
249 ]
250 }
251 }
252 ]
253}"#;