swift_mt_message/fields/
field64.rs1use super::swift_utils::{parse_amount, parse_currency, parse_date_yymmdd, parse_exact_length};
2use crate::errors::ParseError;
3use crate::traits::SwiftField;
4use chrono::NaiveDate;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
18pub struct Field64 {
19 pub debit_credit_mark: String,
21
22 pub value_date: NaiveDate,
24
25 pub currency: String,
27
28 pub amount: f64,
30}
31
32impl SwiftField for Field64 {
33 fn parse(input: &str) -> crate::Result<Self>
34 where
35 Self: Sized,
36 {
37 if input.len() < 10 {
39 return Err(ParseError::InvalidFormat {
40 message: "Field 64 must be at least 10 characters long".to_string(),
41 });
42 }
43
44 let debit_credit_mark = parse_exact_length(&input[0..1], 1, "Field 64 debit/credit mark")?;
46 if debit_credit_mark != "D" && debit_credit_mark != "C" {
47 return Err(ParseError::InvalidFormat {
48 message: "Field 64 debit/credit mark must be 'D' or 'C'".to_string(),
49 });
50 }
51
52 let date_str = parse_exact_length(&input[1..7], 6, "Field 64 value date")?;
54 let value_date = parse_date_yymmdd(&date_str)?;
55
56 let currency = parse_exact_length(&input[7..10], 3, "Field 64 currency")?;
58 let currency = parse_currency(¤cy)?;
59
60 let amount_str = &input[10..];
62 let amount = parse_amount(amount_str)?;
63
64 Ok(Field64 {
65 debit_credit_mark,
66 value_date,
67 currency,
68 amount,
69 })
70 }
71
72 fn to_swift_string(&self) -> String {
73 format!(
74 ":64:{}{}{}{}",
75 self.debit_credit_mark,
76 self.value_date.format("%y%m%d"),
77 self.currency,
78 format!("{:.2}", self.amount).replace('.', ",")
79 )
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86 use chrono::NaiveDate;
87
88 #[test]
89 fn test_field64_parse_valid() {
90 let field = Field64::parse("C231225USD1234,56").unwrap();
91 assert_eq!(field.debit_credit_mark, "C");
92 assert_eq!(
93 field.value_date,
94 NaiveDate::from_ymd_opt(2023, 12, 25).unwrap()
95 );
96 assert_eq!(field.currency, "USD");
97 assert_eq!(field.amount, 1234.56);
98 }
99
100 #[test]
101 fn test_field64_parse_debit() {
102 let field = Field64::parse("D991231EUR500,00").unwrap();
103 assert_eq!(field.debit_credit_mark, "D");
104 assert_eq!(
105 field.value_date,
106 NaiveDate::from_ymd_opt(1999, 12, 31).unwrap()
107 );
108 assert_eq!(field.currency, "EUR");
109 assert_eq!(field.amount, 500.00);
110 }
111
112 #[test]
113 fn test_field64_invalid_debit_credit_mark() {
114 assert!(Field64::parse("X231225USD1234,56").is_err());
115 }
116
117 #[test]
118 fn test_field64_too_short() {
119 assert!(Field64::parse("C2312").is_err());
120 }
121
122 #[test]
123 fn test_field64_to_swift_string() {
124 let field = Field64 {
125 debit_credit_mark: "C".to_string(),
126 value_date: NaiveDate::from_ymd_opt(2023, 12, 25).unwrap(),
127 currency: "USD".to_string(),
128 amount: 1234.56,
129 };
130 assert_eq!(field.to_swift_string(), ":64:C231225USD1234,56");
131 }
132
133 #[test]
134 fn test_field64_debit_to_swift_string() {
135 let field = Field64 {
136 debit_credit_mark: "D".to_string(),
137 value_date: NaiveDate::from_ymd_opt(2023, 12, 25).unwrap(),
138 currency: "EUR".to_string(),
139 amount: 500.00,
140 };
141 assert_eq!(field.to_swift_string(), ":64:D231225EUR500,00");
142 }
143}