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}"#;