swift_mt_message/messages/
mt111.rs

1use crate::fields::{
2    Field20, Field21, Field30, Field59, Field75, GenericBicField, GenericCurrencyAmountField,
3};
4use serde::{Deserialize, Serialize};
5use swift_mt_message_macros::{SwiftMessage, serde_swift_fields};
6
7/// # MT111: Request for Stop Payment of a Cheque (Enhanced Architecture)
8///
9/// ## Overview
10/// MT111 is used by financial institutions to request the stop payment of a cheque
11/// that has been previously issued. This message provides all necessary details
12/// to identify the specific cheque and includes optional query information about
13/// the reason for the stop payment request.
14///
15/// This implementation uses the enhanced macro system for optimal type safety and validation.
16///
17/// ## Structure
18/// All fields are at the message level (no repeating sequences)
19///
20/// ## Key Features
21/// - Stop payment request for specific cheque
22/// - Must match original cheque details if MT110 was previously sent
23/// - Optional query information with predefined codes
24/// - Support for national clearing codes
25/// - Payee identification without account numbers
26/// - Validation against original MT110 if applicable
27/// - Type-safe field handling
28#[serde_swift_fields]
29#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, SwiftMessage)]
30#[validation_rules(MT111_VALIDATION_RULES)]
31pub struct MT111 {
32    /// **Sender's Reference** - Field 20 (Mandatory)
33    /// No '/' start/end, no '//'
34    #[field("20", mandatory)]
35    pub field_20: Field20,
36
37    /// **Cheque Number** - Field 21 (Mandatory)
38    /// Must match original cheque if MT110 was sent
39    #[field("21", mandatory)]
40    pub field_21: Field21,
41
42    /// **Date of Issue** - Field 30 (Mandatory)
43    /// Valid date format (YYMMDD)
44    #[field("30", mandatory)]
45    pub field_30: Field30,
46
47    /// **Amount** - Field 32a (Mandatory)
48    /// Options: A (6!n3!a15d), B (3!a15d)
49    /// Must match MT110 if already sent
50    /// Use Option A if sender credited receiver in advance, otherwise Option B
51    #[field("32A", mandatory)]
52    pub field_32a: GenericCurrencyAmountField,
53
54    /// **Drawer Bank** - Field 52a (Optional)
55    /// Options: A, B, D. Use national clearing codes if no BIC
56    #[field("52A", optional)]
57    pub field_52a: Option<GenericBicField>,
58
59    /// **Payee** - Field 59 (Optional)
60    /// Account field not used - only name and address allowed
61    /// Must not contain an account number
62    #[field("59", optional)]
63    pub field_59: Option<Field59>,
64
65    /// **Queries** - Field 75 (Optional)
66    /// Format: 6*35x, optional format with codes
67    /// Predefined codes: 3, 18, 19, 20, 21
68    #[field("75", optional)]
69    pub field_75: Option<Field75>,
70}
71
72/// Enhanced validation rules for MT111
73const MT111_VALIDATION_RULES: &str = r#"{
74  "rules": [
75    {
76      "id": "REF_FORMAT",
77      "description": "Sender's reference must not start/end with '/' or contain '//'",
78      "condition": {
79        "and": [
80          {"!=": [{"var": "field_20.value"}, ""]},
81          {"!": [{"startsWith": [{"var": "field_20.value"}, "/"]}]},
82          {"!": [{"endsWith": [{"var": "field_20.value"}, "/"]}]},
83          {"!": [{"in": ["//", {"var": "field_20.value"}]}]}
84        ]
85      }
86    },
87    {
88      "id": "CHQ_FORMAT",
89      "description": "Cheque number must not contain '/' or '//'",
90      "condition": {
91        "and": [
92          {"!=": [{"var": "field_21.value"}, ""]},
93          {"!": [{"in": ["/", {"var": "field_21.value"}]}]},
94          {"!": [{"in": ["//", {"var": "field_21.value"}]}]}
95        ]
96      }
97    },
98    {
99      "id": "DATE_VALID",
100      "description": "Date of issue must be a valid date",
101      "condition": {
102        "!=": [{"var": "field_30.value"}, ""]
103      }
104    },
105    {
106      "id": "PAYEE_NO_ACCOUNT",
107      "description": "Payee must not contain account number - only name and address",
108      "condition": {
109        "if": [
110          {"var": "field_59.is_some"},
111          true,
112          true
113        ]
114      }
115    }
116  ]
117}"#;