swift_mt_message/messages/
mt190.rs

1use crate::errors::SwiftValidationError;
2use crate::fields::*;
3use crate::parser::utils::*;
4use serde::{Deserialize, Serialize};
5
6/// **MT190: Advice of Charges, Interest and Other Adjustments**
7///
8/// Notification of charges, interest, and adjustments debited or credited to account.
9///
10/// **Usage:** Charge notifications, interest advice
11/// **Category:** Category 1 (Customer Payments & Cheques)
12#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
13pub struct MT190 {
14    /// Transaction Reference Number (Field 20)
15    #[serde(rename = "20")]
16    pub field_20: Field20,
17
18    /// Related Reference (Field 21)
19    #[serde(rename = "21")]
20    pub field_21: Field21NoOption,
21
22    /// Account Identification (Field 25)
23    #[serde(rename = "25")]
24    pub field_25: Field25NoOption,
25
26    /// Value Date, Currency Code, Amount (Field 32)
27    #[serde(flatten)]
28    pub field_32: Field32AmountCD,
29
30    /// Ordering Institution (Field 52)
31    #[serde(flatten, skip_serializing_if = "Option::is_none")]
32    pub field_52: Option<Field52OrderingInstitution>,
33
34    /// Details of Charges (Field 71B)
35    #[serde(rename = "71B")]
36    pub field_71b: Field71B,
37
38    /// Sender to Receiver Information (Field 72)
39    #[serde(rename = "72", skip_serializing_if = "Option::is_none")]
40    pub field_72: Option<Field72>,
41}
42
43impl MT190 {
44    /// Parse message from Block 4 content
45    pub fn parse_from_block4(block4: &str) -> Result<Self, crate::errors::ParseError> {
46        let mut parser = crate::parser::MessageParser::new(block4, "190");
47
48        // Parse mandatory fields
49        let field_20 = parser.parse_field::<Field20>("20")?;
50        let field_21 = parser.parse_field::<Field21NoOption>("21")?;
51        let field_25 = parser.parse_field::<Field25NoOption>("25")?;
52
53        // Parse amount - can be 32C or 32D for credit/debit adjustments
54        let field_32 = parser.parse_variant_field::<Field32AmountCD>("32")?;
55
56        // Parse optional fields
57        let field_52 = parser.parse_optional_variant_field::<Field52OrderingInstitution>("52")?;
58
59        // Parse mandatory field 71B
60        let field_71b = parser.parse_field::<Field71B>("71B")?;
61
62        // Parse optional field 72
63        let field_72 = parser.parse_optional_field::<Field72>("72")?;
64
65        Ok(MT190 {
66            field_20,
67            field_21,
68            field_25,
69            field_32,
70            field_52,
71            field_71b,
72            field_72,
73        })
74    }
75
76    /// Parse from generic SWIFT input (tries to detect blocks)
77    pub fn parse(input: &str) -> Result<Self, crate::errors::ParseError> {
78        let block4 = extract_block4(input)?;
79        Self::parse_from_block4(&block4)
80    }
81
82    /// Convert to SWIFT MT text format
83    pub fn to_mt_string(&self) -> String {
84        let mut result = String::new();
85
86        append_field(&mut result, &self.field_20);
87        append_field(&mut result, &self.field_21);
88        append_field(&mut result, &self.field_25);
89        append_field(&mut result, &self.field_32);
90        append_optional_field(&mut result, &self.field_52);
91        append_field(&mut result, &self.field_71b);
92        append_optional_field(&mut result, &self.field_72);
93
94        result.push('-');
95        result
96    }
97
98    // ========================================================================
99    // NETWORK VALIDATION RULES (SR 2025 MT190)
100    // ========================================================================
101
102    /// Main validation method - validates all network rules
103    /// Returns array of validation errors, respects stop_on_first_error flag
104    ///
105    /// **Note**: According to SR 2025 specification, MT190 has NO network validated rules.
106    /// This method always returns an empty vector.
107    pub fn validate_network_rules(&self, _stop_on_first_error: bool) -> Vec<SwiftValidationError> {
108        // SR 2025 MT190 specification states:
109        // "There are no network validated rules for this message type."
110        Vec::new()
111    }
112}
113
114impl crate::traits::SwiftMessageBody for MT190 {
115    fn message_type() -> &'static str {
116        "190"
117    }
118
119    fn parse_from_block4(block4: &str) -> Result<Self, crate::errors::ParseError> {
120        // Call the existing public method implementation
121        MT190::parse_from_block4(block4)
122    }
123
124    fn to_mt_string(&self) -> String {
125        // Call the existing public method implementation
126        MT190::to_mt_string(self)
127    }
128
129    fn validate_network_rules(&self, stop_on_first_error: bool) -> Vec<SwiftValidationError> {
130        // Call the existing public method implementation
131        MT190::validate_network_rules(self, stop_on_first_error)
132    }
133}