swift_mt_message/messages/mt192.rs
1use crate::fields::*;
2use serde::{Deserialize, Serialize};
3use swift_mt_message_macros::{SwiftMessage, serde_swift_fields};
4
5/// # MT192: Request for Cancellation
6///
7/// This message is sent by a financial institution to request the cancellation
8/// of a previously sent message. MT192 is used for cancellation requests related
9/// to customer credit transfers and other payment instructions.
10///
11/// ## Key Features
12/// - **Cancellation request**: Official request to cancel a previously sent message
13/// - **Reference tracking**: Links to the original message through multiple reference fields
14/// - **Conditional structure**: Either narrative (field 79) or copy of original message fields
15/// - **Audit trail**: Maintains complete cancellation audit records
16/// - **Reason codes**: Standardized cancellation reason codes for processing
17///
18/// ## Field Structure
19/// The message follows a conditional structure where either field 79 (narrative description)
20/// or a copy of the mandatory fields from the original message must be present, or both.
21///
22/// ## Cancellation Process
23/// Used when a sender needs to request cancellation of a previously sent message,
24/// typically due to errors, fraud, customer request, or technical problems.
25/// The receiver processes the request and may accept or reject the cancellation.
26#[serde_swift_fields]
27#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, SwiftMessage)]
28#[validation_rules(MT192_VALIDATION_RULES)]
29pub struct MT192 {
30 /// **Transaction Reference Number** - Field 20
31 ///
32 /// Unique reference assigned by the sender for this cancellation request.
33 /// This reference is used throughout the cancellation lifecycle for tracking,
34 /// acknowledgment, and audit purposes. Must be unique within sender's system per business day.
35 #[field("20", mandatory)]
36 pub field_20: GenericReferenceField,
37
38 /// **Related Reference** - Field 21
39 ///
40 /// Contains the reference from field 20 of the message to be cancelled.
41 /// This creates a direct link between the cancellation request and the original
42 /// message, enabling the receiver to identify exactly which message to cancel.
43 #[field("21", mandatory)]
44 pub field_21: GenericReferenceField,
45
46 /// **MT and Date of the Original Message** - Field 11S
47 ///
48 /// Specifies the message type, date, session number, and Input Sequence Number (ISN)
49 /// of the original message to be cancelled. Format: 3!n6!n4!n/4!n
50 /// Example: 103231215001/0123 (MT103 dated 2023-12-15, session 0001, ISN 0123)
51 #[field("11S", mandatory)]
52 pub field_11s: Field11S,
53
54 /// **Narrative Description of the Original Message** - Field 79 (Conditional)
55 ///
56 /// Contains cancellation reason codes and free-form text explaining the cancellation.
57 /// Must be present if copy of original message fields is not included, or both may be present.
58 /// Common reason codes: AGNT, AM09, COVR, CURR, CUST, CUTA, DUPL, FRAD, TECH, UPAY
59 #[field("79", optional)]
60 pub field_79: Option<GenericMultiLine6x35>,
61
62 /// **Copy of Mandatory Fields from Original Message** - Multiple Fields (Conditional)
63 ///
64 /// When present, contains a copy of at least the mandatory fields from the original message.
65 /// This helps the receiver identify the exact transaction to be cancelled.
66 /// The specific fields depend on the original message type referenced in field 11S.
67 ///
68 /// For MT103: Would include fields 23B, 32A, 50, 59, 71A
69 ///
70 /// Note: This is represented as optional structured content that can contain
71 /// various field combinations depending on the original message type.
72
73 #[field("13C", optional)]
74 pub field_13c: Option<Field13C>,
75
76 #[field("23B", optional)]
77 pub field_23b: Option<GenericTextField>,
78
79 #[field("32A", optional)]
80 pub field_32a: Option<Field32A>,
81
82 #[field("50", optional)]
83 pub field_50: Option<Field50>,
84
85 #[field("59", optional)]
86 pub field_59: Option<Field59>,
87
88 #[field("71A", optional)]
89 pub field_71a: Option<GenericTextField>,
90}
91
92/// Enhanced validation rules for MT192
93const MT192_VALIDATION_RULES: &str = r#"{
94 "rules": [
95 {
96 "id": "CONDITIONAL_C1",
97 "description": "Either field 79 or copy of original message fields must be present, or both",
98 "condition": {
99 "or": [
100 {"!!": {"var": "field_79"}},
101 {
102 "or": [
103 {"!!": {"var": "field_23b"}},
104 {"!!": {"var": "field_32a"}},
105 {"!!": {"var": "field_50"}},
106 {"!!": {"var": "field_59"}},
107 {"!!": {"var": "field_71a"}}
108 ]
109 }
110 ]
111 }
112 },
113 {
114 "id": "REFERENCE_FORMAT",
115 "description": "Reference fields must not have invalid slash patterns",
116 "condition": {
117 "and": [
118 {"!": {"startsWith": [{"var": "field_20.value"}, "/"]}},
119 {"!": {"endsWith": [{"var": "field_20.value"}, "/"]}},
120 {"!": {"includes": [{"var": "field_20.value"}, "//"]}},
121 {"!": {"startsWith": [{"var": "field_21.value"}, "/"]}},
122 {"!": {"endsWith": [{"var": "field_21.value"}, "/"]}},
123 {"!": {"includes": [{"var": "field_21.value"}, "//"]}}
124 ]
125 }
126 },
127 {
128 "id": "FIELD_11S_FORMAT",
129 "description": "Field 11S must have proper format for MT and date reference",
130 "condition": {
131 "and": [
132 {"==": [{"strlen": {"var": "field_11s.message_type"}}, 3]},
133 {"==": [{"strlen": {"var": "field_11s.date"}}, 6]},
134 {"==": [{"strlen": {"var": "field_11s.session_number"}}, 4]},
135 {"==": [{"strlen": {"var": "field_11s.input_sequence_number"}}, 4]}
136 ]
137 }
138 },
139 {
140 "id": "REQUIRED_FIELDS",
141 "description": "All mandatory fields must be present and non-empty",
142 "condition": {
143 "and": [
144 {"!=": [{"var": "field_20.value"}, ""]},
145 {"!=": [{"var": "field_21.value"}, ""]},
146 {"!=": [{"var": "field_11s.message_type"}, ""]},
147 {"!=": [{"var": "field_11s.date"}, ""]}
148 ]
149 }
150 },
151 {
152 "id": "REASON_CODE_VALIDATION",
153 "description": "If field 79 is present, it should contain valid cancellation reason codes",
154 "condition": {
155 "if": [
156 {"!!": {"var": "field_79"}},
157 {
158 "or": [
159 {"includes": [{"var": "field_79.lines.0"}, "AGNT"]},
160 {"includes": [{"var": "field_79.lines.0"}, "AM09"]},
161 {"includes": [{"var": "field_79.lines.0"}, "COVR"]},
162 {"includes": [{"var": "field_79.lines.0"}, "CURR"]},
163 {"includes": [{"var": "field_79.lines.0"}, "CUST"]},
164 {"includes": [{"var": "field_79.lines.0"}, "CUTA"]},
165 {"includes": [{"var": "field_79.lines.0"}, "DUPL"]},
166 {"includes": [{"var": "field_79.lines.0"}, "FRAD"]},
167 {"includes": [{"var": "field_79.lines.0"}, "TECH"]},
168 {"includes": [{"var": "field_79.lines.0"}, "UPAY"]}
169 ]
170 },
171 true
172 ]
173 }
174 }
175 ]
176}"#;