tap_ivms101/
types.rs

1//! Core IVMS 101.2023 data types
2//!
3//! This module implements the data types defined in the IVMS 101.2023 specification
4//! for the interVASP Messaging Standard.
5
6use serde::{Deserialize, Serialize};
7use std::fmt;
8
9/// ISO 3166-1 alpha-2 country code
10pub type CountryCode = String;
11
12/// ISO 4217 currency code
13pub type CurrencyCode = String;
14
15/// Legal Entity Identifier (LEI) - 20 character alphanumeric code
16pub type LeiCode = String;
17
18/// Business Identifier Code (BIC) - 8 or 11 character code
19pub type BicCode = String;
20
21/// Name identifier type enumeration
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
23#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
24pub enum NameIdentifierType {
25    /// Legal name
26    LegalName,
27    /// Short name
28    ShortName,
29    /// Trading name
30    TradingName,
31    /// Other name type
32    OtherName,
33}
34
35impl fmt::Display for NameIdentifierType {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        match self {
38            Self::LegalName => write!(f, "LEGAL_NAME"),
39            Self::ShortName => write!(f, "SHORT_NAME"),
40            Self::TradingName => write!(f, "TRADING_NAME"),
41            Self::OtherName => write!(f, "OTHER_NAME"),
42        }
43    }
44}
45
46/// Legal person name identifier type enumeration
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
48#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
49pub enum LegalPersonNameIdentifierType {
50    /// Legal name
51    LegalName,
52    /// Short name
53    ShortName,
54    /// Trading name
55    TradingName,
56}
57
58impl fmt::Display for LegalPersonNameIdentifierType {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        match self {
61            Self::LegalName => write!(f, "LEGAL_NAME"),
62            Self::ShortName => write!(f, "SHORT_NAME"),
63            Self::TradingName => write!(f, "TRADING_NAME"),
64        }
65    }
66}
67
68/// Address type enumeration
69#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
70#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
71pub enum AddressType {
72    /// Home address
73    Home,
74    /// Business address
75    Business,
76    /// Geographic address
77    Geographic,
78}
79
80impl fmt::Display for AddressType {
81    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82        match self {
83            Self::Home => write!(f, "HOME"),
84            Self::Business => write!(f, "BUSINESS"),
85            Self::Geographic => write!(f, "GEOGRAPHIC"),
86        }
87    }
88}
89
90/// National identifier type enumeration
91#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
92#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
93pub enum NationalIdentifierType {
94    /// National identity number
95    NationalIdentityNumber,
96    /// Social security number
97    SocialSecurityNumber,
98    /// Tax identification number
99    TaxIdentificationNumber,
100    /// Alien registration number
101    AlienRegistrationNumber,
102    /// Passport number
103    PassportNumber,
104    /// Driver license number
105    DriverLicenseNumber,
106    /// Other identifier type
107    OtherIdentifierType,
108}
109
110impl fmt::Display for NationalIdentifierType {
111    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112        match self {
113            Self::NationalIdentityNumber => write!(f, "NATIONAL_IDENTITY_NUMBER"),
114            Self::SocialSecurityNumber => write!(f, "SOCIAL_SECURITY_NUMBER"),
115            Self::TaxIdentificationNumber => write!(f, "TAX_IDENTIFICATION_NUMBER"),
116            Self::AlienRegistrationNumber => write!(f, "ALIEN_REGISTRATION_NUMBER"),
117            Self::PassportNumber => write!(f, "PASSPORT_NUMBER"),
118            Self::DriverLicenseNumber => write!(f, "DRIVER_LICENSE_NUMBER"),
119            Self::OtherIdentifierType => write!(f, "OTHER_IDENTIFIER_TYPE"),
120        }
121    }
122}
123
124/// Customer identification type enumeration
125#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
126#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
127pub enum CustomerIdentificationType {
128    /// Customer identification number
129    CustomerIdentificationNumber,
130    /// Unique transaction reference
131    UniqueTransactionReference,
132    /// Other customer ID type
133    OtherCustomerIdType,
134}
135
136impl fmt::Display for CustomerIdentificationType {
137    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138        match self {
139            Self::CustomerIdentificationNumber => write!(f, "CUSTOMER_IDENTIFICATION_NUMBER"),
140            Self::UniqueTransactionReference => write!(f, "UNIQUE_TRANSACTION_REFERENCE"),
141            Self::OtherCustomerIdType => write!(f, "OTHER_CUSTOMER_ID_TYPE"),
142        }
143    }
144}
145
146/// Registration authority type enumeration
147#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
148#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
149pub enum RegistrationAuthorityType {
150    /// Registration authority entity identifier
151    RaEntityId,
152    /// Registration authority name
153    RaName,
154    /// Other registration authority
155    OtherRegistrationAuthority,
156}
157
158impl fmt::Display for RegistrationAuthorityType {
159    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160        match self {
161            Self::RaEntityId => write!(f, "RA_ENTITY_ID"),
162            Self::RaName => write!(f, "RA_NAME"),
163            Self::OtherRegistrationAuthority => write!(f, "OTHER_REGISTRATION_AUTHORITY"),
164        }
165    }
166}
167
168/// Transaction direction enumeration
169#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
170#[serde(rename_all = "lowercase")]
171pub enum TransactionDirection {
172    /// Outgoing transaction (from originator)
173    Outgoing,
174    /// Incoming transaction (to beneficiary)
175    Incoming,
176}
177
178impl fmt::Display for TransactionDirection {
179    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180        match self {
181            Self::Outgoing => write!(f, "outgoing"),
182            Self::Incoming => write!(f, "incoming"),
183        }
184    }
185}
186
187/// Payment type enumeration
188#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
189#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
190pub enum PaymentType {
191    /// Annuity payment
192    Annuity,
193    /// Business expenses
194    BusinessExpenses,
195    /// Charity donation
196    CharityDonation,
197    /// Goods
198    Goods,
199    /// Hotel accommodation
200    HotelAccommodation,
201    /// Investment income
202    InvestmentIncome,
203    /// Investment capital
204    InvestmentCapital,
205    /// Lottery payout
206    LotteryPayout,
207    /// Other payment type
208    Other,
209    /// Pension payment
210    Pension,
211    /// Rental income
212    RentalIncome,
213    /// Royalties and fees
214    RoyaltiesAndFees,
215    /// Salary and wages
216    SalaryAndWages,
217    /// Services
218    Services,
219    /// Study costs
220    StudyCosts,
221    /// Travel and tourism
222    TravelAndTourism,
223}
224
225impl fmt::Display for PaymentType {
226    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227        let s = match self {
228            Self::Annuity => "ANNUITY",
229            Self::BusinessExpenses => "BUSINESS_EXPENSES",
230            Self::CharityDonation => "CHARITY_DONATION",
231            Self::Goods => "GOODS",
232            Self::HotelAccommodation => "HOTEL_ACCOMMODATION",
233            Self::InvestmentIncome => "INVESTMENT_INCOME",
234            Self::InvestmentCapital => "INVESTMENT_CAPITAL",
235            Self::LotteryPayout => "LOTTERY_PAYOUT",
236            Self::Other => "OTHER",
237            Self::Pension => "PENSION",
238            Self::RentalIncome => "RENTAL_INCOME",
239            Self::RoyaltiesAndFees => "ROYALTIES_AND_FEES",
240            Self::SalaryAndWages => "SALARY_AND_WAGES",
241            Self::Services => "SERVICES",
242            Self::StudyCosts => "STUDY_COSTS",
243            Self::TravelAndTourism => "TRAVEL_AND_TOURISM",
244        };
245        write!(f, "{}", s)
246    }
247}
248
249/// Transaction network type enumeration
250#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
251#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
252pub enum TransactionNetworkType {
253    /// Bitcoin network
254    Bitcoin,
255    /// Ethereum network
256    Ethereum,
257    /// Litecoin network
258    Litecoin,
259    /// XRP Ledger
260    XrpLedger,
261    /// Stellar network
262    Stellar,
263    /// Other network
264    Other,
265}
266
267impl fmt::Display for TransactionNetworkType {
268    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269        let s = match self {
270            Self::Bitcoin => "BITCOIN",
271            Self::Ethereum => "ETHEREUM",
272            Self::Litecoin => "LITECOIN",
273            Self::XrpLedger => "XRP_LEDGER",
274            Self::Stellar => "STELLAR",
275            Self::Other => "OTHER",
276        };
277        write!(f, "{}", s)
278    }
279}
280
281/// Date and place of birth
282#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
283#[serde(rename_all = "camelCase")]
284pub struct DateAndPlaceOfBirth {
285    /// Date of birth in YYYY-MM-DD format
286    pub date_of_birth: String,
287    /// City of birth
288    pub city_of_birth: String,
289    /// Country of birth (ISO 3166-1 alpha-2)
290    pub country_of_birth: CountryCode,
291}
292
293/// Geographic address
294#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
295#[serde(rename_all = "camelCase")]
296pub struct GeographicAddress {
297    /// Address type (optional)
298    #[serde(skip_serializing_if = "Option::is_none")]
299    pub address_type: Option<AddressType>,
300    /// Department (optional)
301    #[serde(skip_serializing_if = "Option::is_none")]
302    pub department: Option<String>,
303    /// Sub department (optional)
304    #[serde(skip_serializing_if = "Option::is_none")]
305    pub sub_department: Option<String>,
306    /// Street name
307    pub street_name: String,
308    /// Building number (optional)
309    #[serde(skip_serializing_if = "Option::is_none")]
310    pub building_number: Option<String>,
311    /// Building name (optional)
312    #[serde(skip_serializing_if = "Option::is_none")]
313    pub building_name: Option<String>,
314    /// Floor (optional)
315    #[serde(skip_serializing_if = "Option::is_none")]
316    pub floor: Option<String>,
317    /// Post box (optional)
318    #[serde(skip_serializing_if = "Option::is_none")]
319    pub post_box: Option<String>,
320    /// Room (optional)
321    #[serde(skip_serializing_if = "Option::is_none")]
322    pub room: Option<String>,
323    /// Post code
324    pub post_code: String,
325    /// Town name
326    pub town_name: String,
327    /// Town location name (optional)
328    #[serde(skip_serializing_if = "Option::is_none")]
329    pub town_location_name: Option<String>,
330    /// District name (optional)
331    #[serde(skip_serializing_if = "Option::is_none")]
332    pub district_name: Option<String>,
333    /// Country sub division (optional)
334    #[serde(skip_serializing_if = "Option::is_none")]
335    pub country_sub_division: Option<String>,
336    /// Address line (optional, max 7 lines)
337    #[serde(skip_serializing_if = "Option::is_none")]
338    pub address_line: Option<Vec<String>>,
339    /// Country (ISO 3166-1 alpha-2)
340    pub country: CountryCode,
341}