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("23B", optional)]
74 pub field_23b: Option<GenericTextField>,
75
76 #[field("32A", optional)]
77 pub field_32a: Option<Field32A>,
78
79 #[field("50", optional)]
80 pub field_50: Option<Field50>,
81
82 #[field("59", optional)]
83 pub field_59: Option<Field59>,
84
85 #[field("71A", optional)]
86 pub field_71a: Option<GenericTextField>,
87}
88
89/// Enhanced validation rules for MT192
90const MT192_VALIDATION_RULES: &str = r#"{
91 "rules": [
92 {
93 "id": "CONDITIONAL_C1",
94 "description": "Either field 79 or copy of original message fields must be present, or both",
95 "condition": {
96 "or": [
97 {"!!": {"var": "field_79"}},
98 {
99 "or": [
100 {"!!": {"var": "field_23b"}},
101 {"!!": {"var": "field_32a"}},
102 {"!!": {"var": "field_50"}},
103 {"!!": {"var": "field_59"}},
104 {"!!": {"var": "field_71a"}}
105 ]
106 }
107 ]
108 }
109 },
110 {
111 "id": "REFERENCE_FORMAT",
112 "description": "Reference fields must not have invalid slash patterns",
113 "condition": {
114 "and": [
115 {"!": {"startsWith": [{"var": "field_20.value"}, "/"]}},
116 {"!": {"endsWith": [{"var": "field_20.value"}, "/"]}},
117 {"!": {"includes": [{"var": "field_20.value"}, "//"]}},
118 {"!": {"startsWith": [{"var": "field_21.value"}, "/"]}},
119 {"!": {"endsWith": [{"var": "field_21.value"}, "/"]}},
120 {"!": {"includes": [{"var": "field_21.value"}, "//"]}}
121 ]
122 }
123 },
124 {
125 "id": "FIELD_11S_FORMAT",
126 "description": "Field 11S must have proper format for MT and date reference",
127 "condition": {
128 "and": [
129 {"==": [{"strlen": {"var": "field_11s.message_type"}}, 3]},
130 {"==": [{"strlen": {"var": "field_11s.date"}}, 6]},
131 {"==": [{"strlen": {"var": "field_11s.session_number"}}, 4]},
132 {"==": [{"strlen": {"var": "field_11s.input_sequence_number"}}, 4]}
133 ]
134 }
135 },
136 {
137 "id": "REQUIRED_FIELDS",
138 "description": "All mandatory fields must be present and non-empty",
139 "condition": {
140 "and": [
141 {"!=": [{"var": "field_20.value"}, ""]},
142 {"!=": [{"var": "field_21.value"}, ""]},
143 {"!=": [{"var": "field_11s.message_type"}, ""]},
144 {"!=": [{"var": "field_11s.date"}, ""]}
145 ]
146 }
147 },
148 {
149 "id": "REASON_CODE_VALIDATION",
150 "description": "If field 79 is present, it should contain valid cancellation reason codes",
151 "condition": {
152 "if": [
153 {"!!": {"var": "field_79"}},
154 {
155 "or": [
156 {"includes": [{"var": "field_79.lines.0"}, "AGNT"]},
157 {"includes": [{"var": "field_79.lines.0"}, "AM09"]},
158 {"includes": [{"var": "field_79.lines.0"}, "COVR"]},
159 {"includes": [{"var": "field_79.lines.0"}, "CURR"]},
160 {"includes": [{"var": "field_79.lines.0"}, "CUST"]},
161 {"includes": [{"var": "field_79.lines.0"}, "CUTA"]},
162 {"includes": [{"var": "field_79.lines.0"}, "DUPL"]},
163 {"includes": [{"var": "field_79.lines.0"}, "FRAD"]},
164 {"includes": [{"var": "field_79.lines.0"}, "TECH"]},
165 {"includes": [{"var": "field_79.lines.0"}, "UPAY"]}
166 ]
167 },
168 true
169 ]
170 }
171 }
172 ]
173}"#;