swift_mt_message/fields/field71a.rs
1use crate::SwiftField;
2use serde::{Deserialize, Serialize};
3
4/// # Field 71A: Details of Charges
5///
6/// ## Overview
7/// Field 71A specifies who bears the charges in SWIFT payment messages. This field indicates
8/// the party responsible for paying the various fees and charges associated with the payment
9/// transaction, including correspondent banking fees, intermediary charges, and beneficiary
10/// bank charges. The charge allocation is crucial for cost transparency and proper payment
11/// processing in international transfers.
12///
13/// ## Format Specification
14/// **Format**: `3!a`
15/// - **3!a**: 3 alphabetic characters indicating charge bearer
16/// - **Character set**: Alphabetic characters only (A-Z)
17/// - **Case**: Typically uppercase
18///
19/// ## Structure
20/// ```text
21/// OUR
22/// │││
23/// └┴┴─ Charge code (3 letters)
24/// ```
25///
26/// ## Field Components
27/// - **Charge Code**: Three-letter code indicating charge responsibility
28/// - Must be exactly 3 alphabetic characters
29/// - Standard codes defined by SWIFT
30/// - Case-insensitive but typically uppercase
31///
32/// ## Usage Context
33/// Field 71A is used in:
34/// - **MT103**: Single Customer Credit Transfer
35/// - **MT200**: Financial Institution Transfer
36/// - **MT202**: General Financial Institution Transfer
37/// - **MT202COV**: Cover for customer credit transfer
38/// - **MT205**: Financial Institution Transfer for its own account
39///
40/// ### Business Applications
41/// - **Cost allocation**: Determining who pays transaction fees
42/// - **Pricing transparency**: Clear fee responsibility indication
43/// - **Correspondent banking**: Managing charge arrangements
44/// - **Customer agreements**: Implementing charge policies
45/// - **Regulatory compliance**: Meeting charge disclosure requirements
46/// - **Payment processing**: Automated charge handling
47///
48/// ## Standard Charge Codes
49/// ### BEN (Beneficiary)
50/// - **Description**: Beneficiary bears all charges
51/// - **Usage**: All fees deducted from payment amount
52/// - **Impact**: Beneficiary receives net amount after charges
53/// - **Common in**: Incoming payments, salary transfers
54///
55/// ### OUR (Ordering Customer)
56/// - **Description**: Ordering customer bears all charges
57/// - **Usage**: All fees paid separately by sender
58/// - **Impact**: Beneficiary receives full payment amount
59/// - **Common in**: Commercial payments, urgent transfers
60///
61/// ### SHA (Shared)
62/// - **Description**: Charges shared between parties
63/// - **Usage**: Sender pays sending charges, beneficiary pays receiving charges
64/// - **Impact**: Each party pays their respective bank's fees
65/// - **Common in**: Standard international transfers
66///
67/// ## Examples
68/// ```text
69/// :71A:OUR
70/// └─── Ordering customer bears all charges
71///
72/// :71A:BEN
73/// └─── Beneficiary bears all charges
74///
75/// :71A:SHA
76/// └─── Charges shared between parties
77/// ```
78///
79/// ## Charge Code Details
80/// - **OUR**: Ordering customer pays all charges
81/// - Sender bank charges: Paid by ordering customer
82/// - Correspondent charges: Paid by ordering customer
83/// - Beneficiary bank charges: Paid by ordering customer
84/// - Result: Beneficiary receives full amount
85///
86/// - **BEN**: Beneficiary pays all charges
87/// - Sender bank charges: Deducted from payment
88/// - Correspondent charges: Deducted from payment
89/// - Beneficiary bank charges: Deducted from payment
90/// - Result: Beneficiary receives net amount
91///
92/// - **SHA**: Shared charge arrangement
93/// - Sender bank charges: Paid by ordering customer
94/// - Correspondent charges: Typically shared or negotiated
95/// - Beneficiary bank charges: Paid by beneficiary
96/// - Result: Beneficiary receives amount minus receiving charges
97///
98/// ## Validation Rules
99/// 1. **Length**: Must be exactly 3 characters
100/// 2. **Character type**: Alphabetic characters only
101/// 3. **Case**: Case-insensitive but normalized to uppercase
102/// 4. **Standard codes**: Should use recognized SWIFT codes
103/// 5. **Required field**: Must be present in applicable message types
104///
105/// ## Network Validated Rules (SWIFT Standards)
106/// - Must be exactly 3 alphabetic characters (Error: T15)
107/// - Must use valid charge code (Error: T71)
108/// - Code must be recognized by SWIFT network (Error: T72)
109/// - Field is mandatory in applicable messages (Error: M71)
110/// - Must be consistent with message type (Error: C71)
111///
112
113#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, SwiftField)]
114#[format("3!a")]
115pub struct Field71A {
116 /// Charge details code (3 characters)
117 #[format("3!a")]
118 pub details_of_charges: String,
119}
120
121impl Field71A {
122 /// Create a new Field71A with the given charge code
123 pub fn new(details_of_charges: String) -> Self {
124 Self {
125 details_of_charges: details_of_charges.to_uppercase(),
126 }
127 }
128
129 /// Get the charge code
130 pub fn charge_code(&self) -> &str {
131 &self.details_of_charges
132 }
133
134 /// Check if this is a standard charge code
135 pub fn is_standard_code(&self) -> bool {
136 matches!(self.details_of_charges.as_str(), "BEN" | "OUR" | "SHA")
137 }
138
139 /// Get human-readable description of the charge code
140 pub fn description(&self) -> &'static str {
141 match self.details_of_charges.as_str() {
142 "BEN" => "Beneficiary bears all charges",
143 "OUR" => "Ordering customer bears all charges",
144 "SHA" => "Charges shared between ordering customer and beneficiary",
145 _ => "Unknown charge code",
146 }
147 }
148}
149
150impl std::fmt::Display for Field71A {
151 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
152 write!(f, "{}", self.details_of_charges)
153 }
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159
160 #[test]
161 fn test_field71a_creation() {
162 let field = Field71A::new("OUR".to_string());
163 assert_eq!(field.charge_code(), "OUR");
164 assert!(field.is_standard_code());
165 assert_eq!(field.description(), "Ordering customer bears all charges");
166 }
167
168 #[test]
169 fn test_field71a_parse() {
170 let field = Field71A::parse("SHA").unwrap();
171 assert_eq!(field.details_of_charges, "SHA");
172 }
173
174 #[test]
175 fn test_field71a_case_insensitive() {
176 let field = Field71A::new("ben".to_string());
177 assert_eq!(field.details_of_charges, "BEN");
178 }
179}