swift_mt_message/messages/mt200.rs
1use crate::fields::*;
2use serde::{Deserialize, Serialize};
3use swift_mt_message_macros::{SwiftMessage, serde_swift_fields};
4
5/// MT200: Financial Institution Transfer for its Own Account
6///
7/// ## Purpose
8/// Used for transfers between financial institutions where the institution is acting for its own account,
9/// not on behalf of a customer. This message type facilitates proprietary fund movements between institutions
10/// for purposes such as liquidity management, nostro account funding, or internal account adjustments.
11///
12/// ## Scope
13/// This message is:
14/// - Sent between financial institutions for their own account transfers
15/// - Used for nostro/vostro account management and liquidity adjustments
16/// - Applicable for same-currency transfers between correspondent accounts
17/// - Not used for customer-initiated transfers or third-party payments
18/// - Compatible with real-time gross settlement (RTGS) systems
19/// - Suitable for both domestic and cross-border institutional transfers
20///
21/// ## Key Features
22/// - **Simplified Structure**: Streamlined format for institution-to-institution transfers
23/// - **Own Account Focus**: Specifically designed for proprietary institutional movements
24/// - **Direct Routing**: Minimal intermediary support for direct institutional transfers
25/// - **Settlement Efficiency**: Optimized for same-day value and immediate settlement
26/// - **Correspondent Banking**: Built for nostro/vostro account management
27/// - **Minimal Validation**: No complex customer validation rules required
28///
29/// ## Common Use Cases
30/// - Nostro account funding and adjustments
31/// - Vostro account management
32/// - Liquidity transfers between branches
33/// - Foreign exchange position management
34/// - End-of-day settlement positions
35/// - Cash concentration and disbursement
36/// - Internal book transfers between institutions
37///
38/// ## Message Structure
39/// - **Field 20**: Transaction Reference Number (mandatory) - Unique sender reference
40/// - **Field 32A**: Value Date, Currency Code, Amount (mandatory) - Settlement details
41/// - **Field 53B**: Sender's Correspondent (optional) - Account at correspondent bank
42/// - **Field 56**: Intermediary (optional) - Intermediary institution if required
43/// - **Field 57**: Account With Institution (mandatory) - Institution maintaining the account
44/// - **Field 72**: Sender to Receiver Information (optional) - Additional instructions
45///
46/// ## Network Validation Rules
47/// - No specific network validation rules apply to MT200
48/// - Standard SWIFT field format validations apply
49/// - BIC and account number format validations as per SWIFT standards
50///
51/// ## Integration Considerations
52/// - **Banking Systems**: Direct integration with treasury and liquidity management systems
53/// - **Settlement**: Compatible with major settlement systems and RTGS platforms
54/// - **Processing**: Typically processed with high priority for same-day value
55/// - **Reconciliation**: Simplified reconciliation due to institution-to-institution nature
56///
57/// ## Relationship to Other Messages
58/// - **Related to MT202**: MT202 is used when acting on behalf of customers
59/// - **Related to MT205**: MT205 includes mandatory ordering institution field
60/// - **Confirmations**: May generate MT900 (debit) or MT910 (credit) confirmations
61/// - **Account Reporting**: Reflected in MT940/MT950 account statements
62/// - **Status Updates**: May receive MT192/MT196 for queries and responses
63#[serde_swift_fields]
64#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, SwiftMessage)]
65#[validation_rules(MT200_VALIDATION_RULES)]
66pub struct MT200 {
67 #[field("20")]
68 pub field_20: Field20,
69
70 #[field("32A")]
71 pub field_32a: Field32A,
72
73 #[field("53B")]
74 pub field_53b: Option<Field53B>,
75
76 #[field("56")]
77 pub field_56: Option<Field56IntermediaryAD>,
78
79 #[field("57")]
80 pub field_57: Field57DebtInstitution,
81
82 #[field("72")]
83 pub field_72: Option<Field72>,
84}
85
86impl MT200 {
87 /// Creates a new MT200 message with mandatory fields
88 pub fn new(
89 transaction_reference: Field20,
90 value_date_amount: Field32A,
91 account_with_institution: Field57DebtInstitution,
92 ) -> Self {
93 Self {
94 field_20: transaction_reference,
95 field_32a: value_date_amount,
96 field_53b: None,
97 field_56: None,
98 field_57: account_with_institution,
99 field_72: None,
100 }
101 }
102
103 /// Sets the sender's correspondent (Field 53B)
104 pub fn with_senders_correspondent(mut self, correspondent: Field53B) -> Self {
105 self.field_53b = Some(correspondent);
106 self
107 }
108
109 /// Sets the intermediary institution (Field 56)
110 pub fn with_intermediary(mut self, intermediary: Field56IntermediaryAD) -> Self {
111 self.field_56 = Some(intermediary);
112 self
113 }
114
115 /// Sets sender to receiver information (Field 72)
116 pub fn with_sender_to_receiver_info(mut self, info: Field72) -> Self {
117 self.field_72 = Some(info);
118 self
119 }
120}
121
122// Validation rules for MT200 using JSONLogic
123// MT200 has no specific network validated rules according to SWIFT standards
124pub const MT200_VALIDATION_RULES: &str = r#"{
125 "rules": []
126}"#;
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131
132 #[test]
133 fn test_mt200_creation() {
134 let reference = Field20 {
135 reference: "REF123456".to_string(),
136 };
137 let amount = Field32A {
138 value_date: Some(chrono::NaiveDate::from_ymd_opt(2024, 12, 25).unwrap()),
139 currency: "USD".to_string(),
140 amount: 1000000.00,
141 };
142 let account_with = Field57DebtInstitution::A(Field57A {
143 party_identifier: None,
144 bic: "BANKUSAA".to_string(),
145 });
146
147 let mt200 = MT200::new(reference, amount, account_with);
148
149 assert_eq!(mt200.field_20.reference, "REF123456");
150 assert_eq!(mt200.field_32a.currency, "USD");
151 assert!(mt200.field_53b.is_none());
152 assert!(mt200.field_56.is_none());
153 assert!(mt200.field_72.is_none());
154 }
155
156 #[test]
157 fn test_mt200_with_optional_fields() {
158 let reference = Field20 {
159 reference: "REF123456".to_string(),
160 };
161 let amount = Field32A {
162 value_date: Some(chrono::NaiveDate::from_ymd_opt(2024, 12, 25).unwrap()),
163 currency: "USD".to_string(),
164 amount: 1000000.00,
165 };
166 let account_with = Field57DebtInstitution::A(Field57A {
167 party_identifier: None,
168 bic: "BANKUSAA".to_string(),
169 });
170 let intermediary = Field56IntermediaryAD::A(Field56A {
171 party_identifier: None,
172 bic: "INTMUSAA".to_string(),
173 });
174
175 let mt200 = MT200::new(reference, amount, account_with).with_intermediary(intermediary);
176
177 assert!(mt200.field_56.is_some());
178 }
179}