swift_mt_message/messages/
mt101.rs1#[cfg(test)]
2use crate::SwiftMessageBody;
3use crate::fields::*;
4use serde::{Deserialize, Serialize};
5use swift_mt_message_macros::{SwiftMessage, serde_swift_fields};
6
7#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, SwiftMessage)]
11#[validation_rules(MT101_VALIDATION_RULES)]
12#[serde_swift_fields]
13pub struct MT101 {
14 #[field("20", mandatory)]
17 pub field_20: GenericReferenceField, #[field("28D", mandatory)]
20 pub field_28d: Field28D, #[field("30", mandatory)]
23 pub field_30: GenericTextField, #[field("21R", optional)]
27 pub field_21r: Option<GenericReferenceField>, #[field("50A", optional)]
30 pub field_50a_seq_a: Option<Field50>, #[field("52A", optional)]
33 pub field_52a_seq_a: Option<GenericBicField>, #[field("52C", optional)]
36 pub field_52c_seq_a: Option<GenericAccountField>, #[field("51A", optional)]
39 pub field_51a: Option<GenericBicField>, #[field("25", optional)]
42 pub field_25: Option<GenericTextField>, #[field("TRANSACTIONS", repetitive)]
47 pub transactions: Vec<MT101Transaction>,
48}
49
50#[serde_swift_fields]
54#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, SwiftMessage)]
55#[validation_rules(MT101_TRANSACTION_VALIDATION_RULES)]
56pub struct MT101Transaction {
57 #[field("21", mandatory)]
59 pub field_21: GenericReferenceField, #[field("32B", mandatory)]
62 pub field_32b: GenericCurrencyAmountField, #[field("59A", mandatory)]
65 pub field_59a: Field59, #[field("71A", mandatory)]
68 pub field_71a: GenericTextField, #[field("21F", optional)]
72 pub field_21f: Option<GenericReferenceField>, #[field("23E", optional)]
75 pub field_23e: Option<Field23E>, #[field("50A_SEQ_B", optional)]
78 pub field_50a_seq_b: Option<Field50>, #[field("50F_SEQ_B", optional)]
81 pub field_50f_seq_b: Option<GenericPartyField>, #[field("50G_SEQ_B", optional)]
84 pub field_50g_seq_b: Option<GenericPartyField>, #[field("50H_SEQ_B", optional)]
87 pub field_50h_seq_b: Option<GenericPartyField>, #[field("52A_SEQ_B", optional)]
90 pub field_52a_seq_b: Option<GenericBicField>, #[field("52C_SEQ_B", optional)]
93 pub field_52c_seq_b: Option<GenericAccountField>, #[field("56A", optional)]
96 pub field_56a: Option<GenericBicField>, #[field("56C", optional)]
99 pub field_56c: Option<GenericAccountField>, #[field("56D", optional)]
102 pub field_56d: Option<GenericNameAddressField>, #[field("57A", optional)]
105 pub field_57a: Option<GenericBicField>, #[field("57C", optional)]
108 pub field_57c: Option<GenericAccountField>, #[field("57D", optional)]
111 pub field_57d: Option<GenericNameAddressField>, #[field("70", optional)]
114 pub field_70: Option<GenericMultiLine4x35>, #[field("77B", optional)]
117 pub field_77b: Option<GenericMultiLine3x35>, #[field("33B", optional)]
120 pub field_33b: Option<GenericCurrencyAmountField>, #[field("25A", optional)]
123 pub field_25a: Option<GenericAccountField>, #[field("36", optional)]
126 pub field_36: Option<Field36>, }
128
129const MT101_VALIDATION_RULES: &str = r#"{
131 "rules": [
132 {
133 "id": "C1",
134 "description": "Per-transaction: If 36 present → 21F must be present",
135 "forEach": {
136 "collection": "transactions",
137 "condition": {
138 "if": [
139 {"var": "field_36.is_some"},
140 {"var": "field_21f.is_some"},
141 true
142 ]
143 }
144 }
145 },
146 {
147 "id": "C8",
148 "description": "Cross-transaction: All currencies must match if 21R present",
149 "condition": {
150 "if": [
151 {"var": "field_21r.is_some"},
152 {"allEqual": {"map": ["transactions", "field_32b.currency"]}},
153 true
154 ]
155 }
156 },
157 {
158 "id": "SEQ_B_MIN",
159 "description": "At least one transaction required",
160 "condition": {
161 ">=": [{"length": {"var": "transactions"}}, 1]
162 }
163 }
164 ]
165}"#;
166
167const MT101_TRANSACTION_VALIDATION_RULES: &str = r#"{
169 "rules": [
170 {
171 "id": "T_C1",
172 "description": "If exchange rate (36) is present, F/X deal reference (21F) must be present",
173 "condition": {
174 "if": [
175 {"var": "field_36.is_some"},
176 {"var": "field_21f.is_some"},
177 true
178 ]
179 }
180 },
181 {
182 "id": "T_C7",
183 "description": "If intermediary institution (56A/C/D) is present, account with institution (57A/C/D) must be present",
184 "condition": {
185 "if": [
186 {"or": [
187 {"var": "field_56a.is_some"},
188 {"var": "field_56c.is_some"},
189 {"var": "field_56d.is_some"}
190 ]},
191 {"or": [
192 {"var": "field_57a.is_some"},
193 {"var": "field_57c.is_some"},
194 {"var": "field_57d.is_some"}
195 ]},
196 true
197 ]
198 }
199 },
200 {
201 "id": "T_REF",
202 "description": "Transaction reference must be unique within the message",
203 "condition": {
204 "!=": [{"var": "field_21.value"}, ""]
205 }
206 }
207 ]
208}"#;
209
210#[cfg(test)]
211mod tests {
212 use super::*;
213 use std::collections::HashMap;
214
215 #[test]
216 fn test_mt101_compilation() {
217 let field_map = HashMap::new();
219
220 let result = MT101::from_fields(field_map);
222
223 assert!(result.is_err());
226 }
227
228 #[test]
229 fn test_mt101_transaction_compilation() {
230 let field_map = HashMap::new();
232
233 let result = MT101Transaction::from_fields(field_map);
235
236 assert!(result.is_err());
239 }
240}