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