mx_message/header/
bah_admi_024_001_01.rs

1// Plasmatic MX Message Parsing Library
2// https://github.com/GoPlasmatic/MXMessage
3//
4// Copyright (c) 2025 Plasmatic
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9//     http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16//
17// You may obtain a copy of this library at
18// https://github.com/GoPlasmatic/MXMessage
19use crate::parse_result::{ErrorCollector, ParserConfig};
20use crate::validation::{Validate, helpers};
21use serde::{Deserialize, Serialize};
22
23// BranchAndFinancialInstitutionIdentification61: Unique and unambiguous identification of a financial institution, as assigned under an internationally recognised or proprietary identification scheme.
24#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
25pub struct BranchAndFinancialInstitutionIdentification61 {
26    #[serde(rename = "FinInstnId")]
27    pub fin_instn_id: FinancialInstitutionIdentification181,
28}
29
30impl Validate for BranchAndFinancialInstitutionIdentification61 {
31    fn validate(&self, path: &str, config: &ParserConfig, collector: &mut ErrorCollector) {
32        self.fin_instn_id
33            .validate(&helpers::child_path(path, "FinInstnId"), config, collector);
34    }
35}
36
37// BusinessApplicationHeader51: Relative indication of the processing precedence of the message over a (set of) Business Messages with assigned priorities.
38#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
39pub struct BusinessApplicationHeader51 {
40    #[serde(rename = "CharSet", skip_serializing_if = "Option::is_none")]
41    pub char_set: Option<String>,
42    #[serde(rename = "Fr")]
43    pub fr: Party44Choice1,
44    #[serde(rename = "To")]
45    pub to: Party44Choice1,
46    #[serde(rename = "BizMsgIdr")]
47    pub biz_msg_idr: String,
48    #[serde(rename = "MsgDefIdr")]
49    pub msg_def_idr: String,
50    #[serde(rename = "BizSvc", skip_serializing_if = "Option::is_none")]
51    pub biz_svc: Option<String>,
52    #[serde(rename = "CreDt")]
53    pub cre_dt: String,
54    #[serde(rename = "CpyDplct", skip_serializing_if = "Option::is_none")]
55    pub cpy_dplct: Option<CopyDuplicate1Code>,
56    #[serde(rename = "Prty", skip_serializing_if = "Option::is_none")]
57    pub prty: Option<String>,
58}
59
60impl Validate for BusinessApplicationHeader51 {
61    fn validate(&self, path: &str, config: &ParserConfig, collector: &mut ErrorCollector) {
62        self.fr
63            .validate(&helpers::child_path(path, "Fr"), config, collector);
64        self.to
65            .validate(&helpers::child_path(path, "To"), config, collector);
66        helpers::validate_length(
67            &self.biz_msg_idr,
68            "BizMsgIdr",
69            Some(1),
70            Some(35),
71            &helpers::child_path(path, "BizMsgIdr"),
72            config,
73            collector,
74        );
75        helpers::validate_length(
76            &self.msg_def_idr,
77            "MsgDefIdr",
78            Some(1),
79            Some(35),
80            &helpers::child_path(path, "MsgDefIdr"),
81            config,
82            collector,
83        );
84        if let Some(ref val) = self.biz_svc {
85            helpers::validate_length(
86                val,
87                "BizSvc",
88                Some(1),
89                Some(35),
90                &helpers::child_path(path, "BizSvc"),
91                config,
92                collector,
93            );
94        }
95        helpers::validate_pattern(
96            &self.cre_dt,
97            "CreDt",
98            ".*(\\+|-)((0[0-9])|(1[0-4])):[0-5][0-9]",
99            &helpers::child_path(path, "CreDt"),
100            config,
101            collector,
102        );
103        if let Some(ref val) = self.cpy_dplct
104            && config.validate_optional_fields
105        {
106            val.validate(&helpers::child_path(path, "CpyDplct"), config, collector);
107        }
108    }
109}
110
111// BusinessApplicationHeaderV02: Specifies the Business Application Header(s) of the Business Message(s) to which this Business Message relates.
112// Can be used when replying to a query; can also be used when canceling or amending.
113#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
114#[serde(rename = "AppHdr")]
115pub struct BusinessApplicationHeaderV02 {
116    #[serde(rename = "CharSet", skip_serializing_if = "Option::is_none")]
117    pub char_set: Option<String>,
118    #[serde(rename = "Fr")]
119    pub fr: Party44Choice1,
120    #[serde(rename = "To")]
121    pub to: Party44Choice1,
122    #[serde(rename = "BizMsgIdr")]
123    pub biz_msg_idr: String,
124    #[serde(rename = "MsgDefIdr")]
125    pub msg_def_idr: String,
126    #[serde(rename = "BizSvc")]
127    pub biz_svc: Max35Textfixed,
128    #[serde(rename = "MktPrctc", skip_serializing_if = "Option::is_none")]
129    pub mkt_prctc: Option<ImplementationSpecification1>,
130    #[serde(rename = "CreDt")]
131    pub cre_dt: String,
132    #[serde(rename = "CpyDplct", skip_serializing_if = "Option::is_none")]
133    pub cpy_dplct: Option<CopyDuplicate1Code>,
134    #[serde(rename = "PssblDplct", skip_serializing_if = "Option::is_none")]
135    pub pssbl_dplct: Option<bool>,
136    #[serde(rename = "Prty", skip_serializing_if = "Option::is_none")]
137    pub prty: Option<Priority2Code>,
138    #[serde(rename = "Rltd", skip_serializing_if = "Option::is_none")]
139    pub rltd: Option<BusinessApplicationHeader51>,
140}
141
142impl Validate for BusinessApplicationHeaderV02 {
143    fn validate(&self, path: &str, config: &ParserConfig, collector: &mut ErrorCollector) {
144        self.fr
145            .validate(&helpers::child_path(path, "Fr"), config, collector);
146        self.to
147            .validate(&helpers::child_path(path, "To"), config, collector);
148        helpers::validate_length(
149            &self.biz_msg_idr,
150            "BizMsgIdr",
151            Some(1),
152            Some(35),
153            &helpers::child_path(path, "BizMsgIdr"),
154            config,
155            collector,
156        );
157        helpers::validate_length(
158            &self.msg_def_idr,
159            "MsgDefIdr",
160            Some(1),
161            Some(35),
162            &helpers::child_path(path, "MsgDefIdr"),
163            config,
164            collector,
165        );
166        self.biz_svc
167            .validate(&helpers::child_path(path, "BizSvc"), config, collector);
168        if let Some(ref val) = self.mkt_prctc
169            && config.validate_optional_fields
170        {
171            val.validate(&helpers::child_path(path, "MktPrctc"), config, collector);
172        }
173        helpers::validate_pattern(
174            &self.cre_dt,
175            "CreDt",
176            ".*(\\+|-)((0[0-9])|(1[0-4])):[0-5][0-9]",
177            &helpers::child_path(path, "CreDt"),
178            config,
179            collector,
180        );
181        if let Some(ref val) = self.cpy_dplct
182            && config.validate_optional_fields
183        {
184            val.validate(&helpers::child_path(path, "CpyDplct"), config, collector);
185        }
186        if let Some(ref val) = self.prty
187            && config.validate_optional_fields
188        {
189            val.validate(&helpers::child_path(path, "Prty"), config, collector);
190        }
191        if let Some(ref val) = self.rltd
192            && config.validate_optional_fields
193        {
194            val.validate(&helpers::child_path(path, "Rltd"), config, collector);
195        }
196    }
197}
198
199// ClearingSystemIdentification2Choice1: Identification of a clearing system, in a coded form as published in an external list.
200#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
201pub struct ClearingSystemIdentification2Choice1 {
202    #[serde(rename = "Cd", skip_serializing_if = "Option::is_none")]
203    pub cd: Option<String>,
204}
205
206impl Validate for ClearingSystemIdentification2Choice1 {
207    fn validate(&self, path: &str, config: &ParserConfig, collector: &mut ErrorCollector) {
208        if let Some(ref val) = self.cd {
209            helpers::validate_length(
210                val,
211                "Cd",
212                Some(1),
213                Some(5),
214                &helpers::child_path(path, "Cd"),
215                config,
216                collector,
217            );
218        }
219    }
220}
221
222// ClearingSystemMemberIdentification21: Identification of a member of a clearing system.
223#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
224pub struct ClearingSystemMemberIdentification21 {
225    #[serde(rename = "ClrSysId")]
226    pub clr_sys_id: ClearingSystemIdentification2Choice1,
227    #[serde(rename = "MmbId")]
228    pub mmb_id: String,
229}
230
231impl Validate for ClearingSystemMemberIdentification21 {
232    fn validate(&self, path: &str, config: &ParserConfig, collector: &mut ErrorCollector) {
233        self.clr_sys_id
234            .validate(&helpers::child_path(path, "ClrSysId"), config, collector);
235        helpers::validate_length(
236            &self.mmb_id,
237            "MmbId",
238            Some(1),
239            Some(28),
240            &helpers::child_path(path, "MmbId"),
241            config,
242            collector,
243        );
244        helpers::validate_pattern(
245            &self.mmb_id,
246            "MmbId",
247            "[0-9a-zA-Z/\\-\\?:\\(\\)\\.,'\\+ ]+",
248            &helpers::child_path(path, "MmbId"),
249            config,
250            collector,
251        );
252    }
253}
254
255// CopyDuplicate1Code: Message is for information/confirmation purposes. It is a duplicate of a message previously sent.
256#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
257pub enum CopyDuplicate1Code {
258    #[default]
259    #[serde(rename = "CODU")]
260    CodeCODU,
261    #[serde(rename = "COPY")]
262    CodeCOPY,
263    #[serde(rename = "DUPL")]
264    CodeDUPL,
265}
266
267impl Validate for CopyDuplicate1Code {
268    fn validate(&self, _path: &str, _config: &ParserConfig, _collector: &mut ErrorCollector) {
269        // Enum validation is typically empty
270    }
271}
272
273// FinancialInstitutionIdentification181: Legal entity identifier of the financial institution.
274#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
275pub struct FinancialInstitutionIdentification181 {
276    #[serde(rename = "BICFI")]
277    pub bicfi: String,
278    #[serde(rename = "ClrSysMmbId", skip_serializing_if = "Option::is_none")]
279    pub clr_sys_mmb_id: Option<ClearingSystemMemberIdentification21>,
280    #[serde(rename = "LEI", skip_serializing_if = "Option::is_none")]
281    pub lei: Option<String>,
282}
283
284impl Validate for FinancialInstitutionIdentification181 {
285    fn validate(&self, path: &str, config: &ParserConfig, collector: &mut ErrorCollector) {
286        helpers::validate_pattern(
287            &self.bicfi,
288            "BICFI",
289            "[A-Z0-9]{4,4}[A-Z]{2,2}[A-Z0-9]{2,2}([A-Z0-9]{3,3}){0,1}",
290            &helpers::child_path(path, "BICFI"),
291            config,
292            collector,
293        );
294        if let Some(ref val) = self.clr_sys_mmb_id
295            && config.validate_optional_fields
296        {
297            val.validate(&helpers::child_path(path, "ClrSysMmbId"), config, collector);
298        }
299        if let Some(ref val) = self.lei {
300            helpers::validate_pattern(
301                val,
302                "LEI",
303                "[A-Z0-9]{18,18}[0-9]{2,2}",
304                &helpers::child_path(path, "LEI"),
305                config,
306                collector,
307            );
308        }
309    }
310}
311
312// ImplementationSpecification1: Identifier which unambiguously identifies, within the implementation specification registry, the implementation specification to which the ISO 20022 message is compliant. This can be done via a URN. It can also contain a version number or date.
313// For instance, "2018-01-01 – Version 2" or "urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66".
314#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
315pub struct ImplementationSpecification1 {
316    #[serde(rename = "Regy")]
317    pub regy: String,
318    #[serde(rename = "Id")]
319    pub id: String,
320}
321
322impl Validate for ImplementationSpecification1 {
323    fn validate(&self, path: &str, config: &ParserConfig, collector: &mut ErrorCollector) {
324        helpers::validate_length(
325            &self.regy,
326            "Regy",
327            Some(1),
328            Some(350),
329            &helpers::child_path(path, "Regy"),
330            config,
331            collector,
332        );
333        helpers::validate_length(
334            &self.id,
335            "Id",
336            Some(1),
337            Some(2048),
338            &helpers::child_path(path, "Id"),
339            config,
340            collector,
341        );
342    }
343}
344
345// Max35Text_fixed: swift.cbprplus.01
346#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
347pub enum Max35Textfixed {
348    #[default]
349    #[serde(rename = "swift.cbprplus.01")]
350    CodeSWIFTCBPRPLUS01,
351}
352
353impl Validate for Max35Textfixed {
354    fn validate(&self, _path: &str, _config: &ParserConfig, _collector: &mut ErrorCollector) {
355        // Enum validation is typically empty
356    }
357}
358
359// Party44Choice1: Identification of a financial institution.
360#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
361pub struct Party44Choice1 {
362    #[serde(rename = "FIId", skip_serializing_if = "Option::is_none")]
363    pub fi_id: Option<BranchAndFinancialInstitutionIdentification61>,
364}
365
366impl Validate for Party44Choice1 {
367    fn validate(&self, path: &str, config: &ParserConfig, collector: &mut ErrorCollector) {
368        if let Some(ref val) = self.fi_id
369            && config.validate_optional_fields
370        {
371            val.validate(&helpers::child_path(path, "FIId"), config, collector);
372        }
373    }
374}
375
376// Priority2Code: Priority level is normal.
377#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
378pub enum Priority2Code {
379    #[default]
380    #[serde(rename = "HIGH")]
381    CodeHIGH,
382    #[serde(rename = "NORM")]
383    CodeNORM,
384}
385
386impl Validate for Priority2Code {
387    fn validate(&self, _path: &str, _config: &ParserConfig, _collector: &mut ErrorCollector) {
388        // Enum validation is typically empty
389    }
390}