swift_mt_message/messages/
mt107.rs

1use crate::fields::{
2    Field20, Field21, Field23E, Field26T, Field30, Field36, Field50, Field59, Field70, Field71A,
3    Field72, Field77B, GenericBalanceField, GenericBicField, GenericCurrencyAmountField,
4};
5use serde::{Deserialize, Serialize};
6use swift_mt_message_macros::{SwiftMessage, serde_swift_fields};
7
8/// # MT107: Request for Cancellation/Amendment (Enhanced Architecture)
9///
10/// ## Overview
11/// MT107 is used by financial institutions to request cancellation or amendment
12/// of previously sent direct debit instructions. It supports batch processing
13/// of multiple transaction modifications with detailed settlement information.
14///
15/// This implementation uses the enhanced macro system with separate transaction
16/// structures for optimal type safety and validation.
17///
18/// ## Structure
19/// - **Sequence A**: General Information (mandatory, single occurrence)
20/// - **Sequence B**: Transaction Details (mandatory, repetitive) - MT107Transaction struct
21/// - **Sequence C**: Settlement Details (optional, single occurrence) - Individual fields
22///
23/// ## Key Features
24/// - Multiple transaction modification support in single message
25/// - Flexible creditor/debtor identification
26/// - Optional settlement consolidation
27/// - Comprehensive regulatory reporting
28/// - Charge allocation options
29/// - Amendment and cancellation instructions
30/// - Type-safe transaction handling
31#[serde_swift_fields]
32#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, SwiftMessage)]
33#[validation_rules(MT107_VALIDATION_RULES)]
34pub struct MT107 {
35    // ================================
36    // SEQUENCE A - GENERAL INFORMATION
37    // ================================
38    /// **Sender's Reference** - Field 20 (Mandatory)
39    /// Unique ID assigned by the sender to identify this MT107 message.
40    #[field("20", mandatory)]
41    pub field_20: Field20,
42
43    /// **Instruction Code** - Field 23E Seq A (Conditional)
44    /// Values: AUTH, NAUT, OTHR, RTND (C1)
45    #[field("23E", optional)]
46    pub field_23e: Option<Field23E>,
47
48    /// **Registration Reference** - Field 21E (Conditional)
49    /// Optional ID. Subject to C2/C3
50    #[field("21E", optional)]
51    pub field_21e: Option<Field21>,
52
53    /// **Requested Execution Date** - Field 30 (Mandatory)
54    /// Format: YYMMDD
55    #[field("30", mandatory)]
56    pub field_30: Field30,
57
58    /// **Sending Institution** - Field 51A (Optional)
59    /// FileAct only
60    #[field("51A", optional)]
61    pub field_51a: Option<GenericBicField>,
62
63    /// **Instructing Party** - Field 50a Seq A (Conditional)
64    /// Options: C, L. Who orders debit. Subject to C2
65    #[field("50A_INSTRUCTING", optional)]
66    pub field_50a_instructing: Option<Field50>,
67
68    /// **Creditor** - Field 50a Seq A (Conditional)
69    /// Options: A, K. Name & account details. Subject to C1/C3
70    #[field("50A_CREDITOR", optional)]
71    pub field_50a_creditor: Option<Field50>,
72
73    /// **Creditor's Bank** - Field 52a Seq A (Conditional)
74    /// Options: A, C, D. Clearing/routing. Subject to C2
75    #[field("52A", optional)]
76    pub field_52a: Option<GenericBicField>,
77
78    /// **Transaction Type Code** - Field 26T Seq A (Conditional)
79    /// Purpose code. Subject to C2
80    #[field("26T", optional)]
81    pub field_26t: Option<Field26T>,
82
83    /// **Regulatory Reporting** - Field 77B Seq A (Conditional)
84    /// Statutory codes. Subject to C2
85    #[field("77B", optional)]
86    pub field_77b: Option<Field77B>,
87
88    /// **Details of Charges** - Field 71A Seq A (Conditional)
89    /// Values: BEN, OUR, SHA. Subject to C2
90    #[field("71A", optional)]
91    pub field_71a: Option<Field71A>,
92
93    /// **Sender to Receiver Information** - Field 72 (Conditional)
94    /// RTND required. Subject to C4
95    #[field("72", optional)]
96    pub field_72: Option<Field72>,
97
98    // ================================
99    // SEQUENCE B - TRANSACTION DETAILS (REPEATING)
100    // ================================
101    /// **Transaction Details** - Sequence B (Mandatory, Repetitive)
102    /// Each entry represents one transaction to be cancelled/amended
103    #[field("TRANSACTIONS", repetitive)]
104    pub transactions: Vec<MT107Transaction>,
105
106    // ================================
107    // SEQUENCE C - SETTLEMENT DETAILS (OPTIONAL)
108    // ================================
109    /// **Settlement Amount** - Field 32B Seq C (Optional)
110    /// Final amount including charges
111    #[field("32B", optional)]
112    pub field_32b: Option<GenericCurrencyAmountField>,
113
114    /// **Sum of Amounts** - Field 19 (Conditional)
115    /// If 32B not used. Subject to C8
116    #[field("19", optional)]
117    pub field_19: Option<GenericBalanceField>,
118
119    /// **Sum of Sender's Charges** - Field 71F Seq C (Conditional)
120    /// Totals from B blocks. Subject to C5
121    #[field("71F", optional)]
122    pub field_71f: Option<GenericCurrencyAmountField>,
123
124    /// **Sum of Receiver's Charges** - Field 71G Seq C (Conditional)
125    /// Totals from B blocks. Subject to C5
126    #[field("71G", optional)]
127    pub field_71g: Option<GenericCurrencyAmountField>,
128
129    /// **Sender's Correspondent** - Field 53a (Optional)
130    /// Options: A, B. Reimbursement branch
131    #[field("53A", optional)]
132    pub field_53a: Option<GenericBicField>,
133}
134
135/// # MT107 Transaction (Sequence B)
136///
137/// Represents a single transaction within an MT107 cancellation/amendment message.
138/// This structure demonstrates the enhanced architecture for handling repetitive SWIFT sequences.
139///
140/// ## Architectural Benefits:
141/// 1. **Complete Validation**: Each transaction validates all its fields independently
142/// 2. **Memory Efficiency**: Only allocates fields that are present  
143/// 3. **Type Safety**: Compile-time validation of field types
144/// 4. **Business Logic**: Clear transaction-level operations and validation
145/// 5. **Scalability**: Easy to add new transaction types or fields
146#[serde_swift_fields]
147#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, SwiftMessage)]
148#[validation_rules(MT107_TRANSACTION_VALIDATION_RULES)]
149pub struct MT107Transaction {
150    /// **Transaction Reference** - Field 21 (Mandatory)
151    /// Unique reference for each transaction
152    #[field("21", mandatory)]
153    pub field_21: Field21,
154
155    /// **Instruction Code** - Field 23E Seq B (Conditional)
156    /// Values: AUTH, NAUT, OTHR (C1)
157    #[field("23E", optional)]
158    pub field_23e: Option<Field23E>,
159
160    /// **Mandate Reference** - Field 21C (Optional)
161    /// Used for mandates
162    #[field("21C", optional)]
163    pub field_21c: Option<Field21>,
164
165    /// **Direct Debit Reference** - Field 21D (Optional)
166    /// Used for returns
167    #[field("21D", optional)]
168    pub field_21d: Option<Field21>,
169
170    /// **Registration Reference** - Field 21E Seq B (Conditional)
171    /// Subject to C2/C3
172    #[field("21E", optional)]
173    pub field_21e: Option<Field21>,
174
175    /// **Currency/Transaction Amount** - Field 32B (Mandatory)
176    /// Amount to debit
177    #[field("32B", mandatory)]
178    pub field_32b: GenericCurrencyAmountField,
179
180    /// **Instructing Party** - Field 50a Seq B (Conditional)
181    /// Options: C, L. Who orders debit. Subject to C2
182    #[field("50A_INSTRUCTING", optional)]
183    pub field_50a_instructing: Option<Field50>,
184
185    /// **Creditor** - Field 50a Seq B (Conditional)
186    /// Options: A, K. Name & account details. Subject to C1/C3
187    #[field("50A_CREDITOR", optional)]
188    pub field_50a_creditor: Option<Field50>,
189
190    /// **Creditor's Bank** - Field 52a Seq B (Conditional)
191    /// Options: A, C, D. Routing bank. Subject to C2
192    #[field("52A", optional)]
193    pub field_52a: Option<GenericBicField>,
194
195    /// **Debtor's Bank** - Field 57a (Optional)
196    /// Options: A, C, D. Account servicing bank
197    #[field("57A", optional)]
198    pub field_57a: Option<GenericBicField>,
199
200    /// **Debtor** - Field 59a (Mandatory)
201    /// Must include account. Options: A/none
202    #[field("59A", mandatory)]
203    pub field_59a: Field59,
204
205    /// **Remittance Information** - Field 70 (Optional)
206    /// Details to debtor
207    #[field("70", optional)]
208    pub field_70: Option<Field70>,
209
210    /// **Transaction Type Code** - Field 26T Seq B (Conditional)
211    /// Reason for payment. Subject to C2
212    #[field("26T", optional)]
213    pub field_26t: Option<Field26T>,
214
215    /// **Regulatory Reporting** - Field 77B Seq B (Conditional)
216    /// Residence, codes. Subject to C2
217    #[field("77B", optional)]
218    pub field_77b: Option<Field77B>,
219
220    /// **Original Ordered Amount** - Field 33B (Optional)
221    /// Must differ from 32B
222    #[field("33B", optional)]
223    pub field_33b: Option<GenericCurrencyAmountField>,
224
225    /// **Details of Charges** - Field 71A Seq B (Conditional)
226    /// Values: BEN, OUR, SHA. Subject to C2
227    #[field("71A", optional)]
228    pub field_71a: Option<Field71A>,
229
230    /// **Sender's Charges** - Field 71F (Conditional)
231    /// Total sender charges. Subject to C5
232    #[field("71F", optional)]
233    pub field_71f: Option<GenericCurrencyAmountField>,
234
235    /// **Receiver's Charges** - Field 71G (Conditional)
236    /// Total receiver charges. Subject to C5
237    #[field("71G", optional)]
238    pub field_71g: Option<GenericCurrencyAmountField>,
239
240    /// **Exchange Rate** - Field 36 (Conditional)
241    /// Required if 33B ≠ 32B. Subject to C7
242    #[field("36", optional)]
243    pub field_36: Option<Field36>,
244}
245
246/// Enhanced validation rules with forEach support for repetitive sequences
247const MT107_VALIDATION_RULES: &str = r#"{
248  "rules": [
249    {
250      "id": "C1",
251      "description": "If 23E is AUTH/NAUT/OTHR in Seq A, same restriction applies to Seq B",
252      "condition": {
253        "if": [
254          {"var": "field_23e.is_some"},
255          {
256            "forEach": {
257              "collection": "transactions",
258              "condition": {
259                "if": [
260                  {"var": "field_23e.is_some"},
261                  {"in": [{"var": "field_23e.code"}, ["AUTH", "NAUT", "OTHR"]]},
262                  true
263                ]
264              }
265            }
266          },
267          true
268        ]
269      }
270    },
271    {
272      "id": "C2",
273      "description": "Instructing party appears in exactly one sequence",
274      "condition": {
275        "xor": [
276          {"var": "field_50a_instructing.is_some"},
277          {
278            "any": {
279              "map": ["transactions", "field_50a_instructing.is_some"]
280            }
281          }
282        ]
283      }
284    },
285    {
286      "id": "C4",
287      "description": "Field 72 required when 23E = RTND",
288      "condition": {
289        "if": [
290          {"and": [
291            {"var": "field_23e.is_some"},
292            {"==": [{"var": "field_23e.code"}, "RTND"]}
293          ]},
294          {"var": "field_72.is_some"},
295          true
296        ]
297      }
298    },
299    {
300      "id": "TXN_MIN",
301      "description": "At least one transaction required",
302      "condition": {
303        ">=": [{"length": {"var": "transactions"}}, 1]
304      }
305    }
306  ]
307}"#;
308
309/// Validation rules specific to MT107 transactions
310const MT107_TRANSACTION_VALIDATION_RULES: &str = r#"{
311  "rules": [
312    {
313      "id": "T_C7",
314      "description": "Exchange rate required when 33B differs from 32B",
315      "condition": {
316        "if": [
317          {"and": [
318            {"var": "field_33b.is_some"},
319            {"!=": [{"var": "field_33b.amount"}, {"var": "field_32b.amount"}]}
320          ]},
321          {"var": "field_36.is_some"},
322          true
323        ]
324      }
325    },
326    {
327      "id": "T_REF",
328      "description": "Transaction reference must be unique within the message",
329      "condition": {
330        "!=": [{"var": "field_21.value"}, ""]
331      }
332    }
333  ]
334}"#;