swift_mt_message/messages/
mt191.rs

1use crate::errors::SwiftValidationError;
2use crate::fields::*;
3use crate::parser::utils::*;
4use serde::{Deserialize, Serialize};
5
6/// **MT191: Request for Payment of Charges, Interest and Other Expenses**
7///
8/// Request for payment of charges, interest, and expenses from another financial institution.
9///
10/// **Usage:** Charge reimbursement requests, expense recovery
11/// **Category:** Category 1 (Customer Payments & Cheques)
12#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
13pub struct MT191 {
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    /// Currency Code, Amount (Field 32B)
23    #[serde(rename = "32B")]
24    pub field_32b: Field32B,
25
26    /// Ordering Institution (Field 52)
27    #[serde(flatten, skip_serializing_if = "Option::is_none")]
28    pub field_52: Option<Field52OrderingInstitution>,
29
30    /// Account With Institution (Field 57)
31    #[serde(flatten, skip_serializing_if = "Option::is_none")]
32    pub field_57: Option<Field57AccountWithInstitution>,
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 MT191 {
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, "191");
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_32b = parser.parse_field::<Field32B>("32B")?;
52
53        // Parse optional fields
54        let field_52 = parser.parse_optional_variant_field::<Field52OrderingInstitution>("52")?;
55        let field_57 =
56            parser.parse_optional_variant_field::<Field57AccountWithInstitution>("57")?;
57
58        // Parse mandatory field 71B
59        let field_71b = parser.parse_field::<Field71B>("71B")?;
60
61        // Parse optional field 72
62        let field_72 = parser.parse_optional_field::<Field72>("72")?;
63
64        Ok(MT191 {
65            field_20,
66            field_21,
67            field_32b,
68            field_52,
69            field_57,
70            field_71b,
71            field_72,
72        })
73    }
74
75    /// Parse from generic SWIFT input (tries to detect blocks)
76    pub fn parse(input: &str) -> Result<Self, crate::errors::ParseError> {
77        let block4 = extract_block4(input)?;
78        Self::parse_from_block4(&block4)
79    }
80
81    /// Convert to SWIFT MT text format
82    pub fn to_mt_string(&self) -> String {
83        let mut result = String::new();
84
85        append_field(&mut result, &self.field_20);
86        append_field(&mut result, &self.field_21);
87        append_field(&mut result, &self.field_32b);
88        append_optional_field(&mut result, &self.field_52);
89        append_optional_field(&mut result, &self.field_57);
90        append_field(&mut result, &self.field_71b);
91        append_optional_field(&mut result, &self.field_72);
92
93        result.push('-');
94        result
95    }
96
97    // ========================================================================
98    // NETWORK VALIDATION RULES (SR 2025 MT191)
99    // ========================================================================
100    //
101    // Per SR 2025 MTn91 specification (line 35):
102    // "There are no network validated rules for this message type."
103    //
104    // This implementation follows the MT101 pattern for consistency,
105    // but returns an empty vector as there are no validation rules.
106    // ========================================================================
107
108    /// Main validation method - validates all network rules
109    /// Returns array of validation errors, respects stop_on_first_error flag
110    ///
111    /// **Note**: MT191 has no network validated rules per SR 2025 specification.
112    /// This method is provided for consistency with other message types and
113    /// returns an empty vector.
114    pub fn validate_network_rules(&self, _stop_on_first_error: bool) -> Vec<SwiftValidationError> {
115        // No network validated rules for MT191
116        Vec::new()
117    }
118}
119
120impl crate::traits::SwiftMessageBody for MT191 {
121    fn message_type() -> &'static str {
122        "191"
123    }
124
125    fn parse_from_block4(block4: &str) -> Result<Self, crate::errors::ParseError> {
126        // Call the existing public method implementation
127        MT191::parse_from_block4(block4)
128    }
129
130    fn to_mt_string(&self) -> String {
131        // Call the existing public method implementation
132        MT191::to_mt_string(self)
133    }
134
135    fn validate_network_rules(&self, stop_on_first_error: bool) -> Vec<SwiftValidationError> {
136        // Call the existing public method implementation
137        MT191::validate_network_rules(self, stop_on_first_error)
138    }
139}