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}