swift_mt_message/messages/mt110.rs
1use crate::fields::{
2 Field20, Field21, Field30, Field50, Field59, Field72, GenericBicField,
3 GenericCurrencyAmountField,
4};
5use serde::{Deserialize, Serialize};
6use swift_mt_message_macros::{SwiftMessage, serde_swift_fields};
7
8/// # MT110: Advice of Cheque (Enhanced Architecture)
9///
10/// ## Overview
11/// MT110 is used by financial institutions to advise the receipt or dispatch
12/// of cheques. It provides detailed information about individual cheques including
13/// payer, payee, amounts, and banking details. The message supports batch processing
14/// of up to 10 cheques with consistent currency requirements.
15///
16/// This implementation uses the enhanced macro system with separate cheque
17/// structures for optimal type safety and validation.
18///
19/// ## Structure
20/// - **Header Fields**: General information and correspondent details
21/// - **Repeating Sequence**: Individual cheque details (up to 10 occurrences) - MT110Cheque struct
22///
23/// ## Key Features
24/// - Multiple cheque processing in single message (up to 10)
25/// - Consistent currency requirement across all cheques
26/// - Flexible correspondent bank routing
27/// - Detailed payer/payee identification
28/// - Support for national clearing codes
29/// - Optional structured sender-to-receiver information
30/// - Type-safe cheque handling
31#[serde_swift_fields]
32#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, SwiftMessage)]
33#[validation_rules(MT110_VALIDATION_RULES)]
34pub struct MT110 {
35 // ================================
36 // HEADER FIELDS
37 // ================================
38 /// **Sender's Reference** - Field 20 (Mandatory)
39 /// No leading/trailing slash, no '//'
40 #[field("20", mandatory)]
41 pub field_20: Field20,
42
43 /// **Sender's Correspondent** - Field 53a (Optional)
44 /// Options: A, B, D. Required if no direct account relationship
45 #[field("53A", optional)]
46 pub field_53a: Option<GenericBicField>,
47
48 /// **Receiver's Correspondent** - Field 54a (Optional)
49 /// Options: A, B, D. Used to route funds to Receiver
50 #[field("54A", optional)]
51 pub field_54a: Option<GenericBicField>,
52
53 /// **Sender to Receiver Information** - Field 72 (Optional)
54 /// Format: 6*35x, optional structured codes
55 /// Codes: ACC, INS, INT; REJT/RETN special rules
56 #[field("72", optional)]
57 pub field_72: Option<Field72>,
58
59 // ================================
60 // REPEATING SEQUENCE - CHEQUE DETAILS (UP TO 10)
61 // ================================
62 /// **Cheque Details** - Repeating Sequence (Mandatory, up to 10 occurrences)
63 /// Each entry represents one cheque being advised
64 #[field("CHEQUES", repetitive)]
65 pub cheques: Vec<MT110Cheque>,
66}
67
68/// # MT110 Cheque (Repeating Sequence)
69///
70/// Represents a single cheque within an MT110 advice message.
71/// This structure demonstrates the enhanced architecture for handling repetitive SWIFT sequences.
72///
73/// ## Architectural Benefits:
74/// 1. **Complete Validation**: Each cheque validates all its fields independently
75/// 2. **Memory Efficiency**: Only allocates fields that are present
76/// 3. **Type Safety**: Compile-time validation of field types
77/// 4. **Business Logic**: Clear cheque-level operations and validation
78/// 5. **Scalability**: Easy to add new cheque types or fields
79#[serde_swift_fields]
80#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, SwiftMessage)]
81#[validation_rules(MT110_CHEQUE_VALIDATION_RULES)]
82pub struct MT110Cheque {
83 /// **Cheque Number** - Field 21 (Mandatory)
84 /// Unique per cheque; no '/' or '//'
85 #[field("21", mandatory)]
86 pub field_21: Field21,
87
88 /// **Date of Issue** - Field 30 (Mandatory)
89 /// Format: YYMMDD. Must be a valid date
90 #[field("30", mandatory)]
91 pub field_30: Field30,
92
93 /// **Amount** - Field 32a (Mandatory)
94 /// Options: A (6!n3!a15d) / B (3!a15d)
95 /// Currency must be same for all cheques in the message
96 #[field("32A", mandatory)]
97 pub field_32a: GenericCurrencyAmountField,
98
99 /// **Payer** - Field 50a (Optional)
100 /// Options: A, F, K. Detailed identity formats
101 #[field("50A", optional)]
102 pub field_50a: Option<Field50>,
103
104 /// **Drawer Bank** - Field 52a (Optional)
105 /// Options: A, B, D. Can specify BIC or national code
106 #[field("52A", optional)]
107 pub field_52a: Option<GenericBicField>,
108
109 /// **Payee** - Field 59a (Mandatory)
110 /// Options: No letter, F option. Must use structured address and name
111 #[field("59A", mandatory)]
112 pub field_59a: Field59,
113}
114
115/// Enhanced validation rules with forEach support for repetitive sequences
116const MT110_VALIDATION_RULES: &str = r#"{
117 "rules": [
118 {
119 "id": "C1",
120 "description": "Maximum 10 cheques per message",
121 "condition": {
122 "<=": [{"length": {"var": "cheques"}}, 10]
123 }
124 },
125 {
126 "id": "C2",
127 "description": "All cheques must have the same currency",
128 "condition": {
129 "if": [
130 {">": [{"length": {"var": "cheques"}}, 0]},
131 {
132 "allEqual": {
133 "map": ["cheques", "field_32a.currency"]
134 }
135 },
136 true
137 ]
138 }
139 },
140 {
141 "id": "CHQ_MIN",
142 "description": "At least one cheque required",
143 "condition": {
144 ">=": [{"length": {"var": "cheques"}}, 1]
145 }
146 }
147 ]
148}"#;
149
150/// Validation rules specific to MT110 cheques
151const MT110_CHEQUE_VALIDATION_RULES: &str = r#"{
152 "rules": [
153 {
154 "id": "CHQ_REF",
155 "description": "Cheque reference must be unique and not contain '/' or '//'",
156 "condition": {
157 "and": [
158 {"!=": [{"var": "field_21.value"}, ""]},
159 {"!": [{"in": ["/", {"var": "field_21.value"}]}]},
160 {"!": [{"in": ["//", {"var": "field_21.value"}]}]}
161 ]
162 }
163 },
164 {
165 "id": "CHQ_DATE",
166 "description": "Date of issue must be a valid date",
167 "condition": {
168 "!=": [{"var": "field_30.value"}, ""]
169 }
170 }
171 ]
172}"#;