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}"#;