1use serde::{Deserialize, Serialize};
4
5use crate::enums::Currency;
6use crate::traits::{Bo4eMeta, Bo4eObject};
7
8#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
25#[serde(rename_all = "camelCase")]
26pub struct Amount {
27 #[serde(flatten)]
29 pub meta: Bo4eMeta,
30
31 #[serde(skip_serializing_if = "Option::is_none")]
33 pub value: Option<f64>,
34
35 #[serde(skip_serializing_if = "Option::is_none")]
37 pub currency: Option<Currency>,
38}
39
40impl Bo4eObject for Amount {
41 fn type_name_german() -> &'static str {
42 "Betrag"
43 }
44
45 fn type_name_english() -> &'static str {
46 "Amount"
47 }
48
49 fn meta(&self) -> &Bo4eMeta {
50 &self.meta
51 }
52
53 fn meta_mut(&mut self) -> &mut Bo4eMeta {
54 &mut self.meta
55 }
56}
57
58impl Amount {
59 pub fn eur(value: f64) -> Self {
61 Self {
62 value: Some(value),
63 currency: Some(Currency::Eur),
64 ..Default::default()
65 }
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn test_eur_amount() {
75 let amount = Amount::eur(100.50);
76 assert_eq!(amount.value, Some(100.50));
77 assert_eq!(amount.currency, Some(Currency::Eur));
78 }
79
80 #[test]
81 fn test_default() {
82 let amount = Amount::default();
83 assert!(amount.value.is_none());
84 assert!(amount.currency.is_none());
85 }
86
87 #[test]
88 fn test_serialize() {
89 let amount = Amount::eur(250.75);
90 let json = serde_json::to_string(&amount).unwrap();
91 assert!(json.contains(r#""value":250.75"#));
92 assert!(json.contains(r#""currency":"EUR""#));
93 }
94
95 #[test]
96 fn test_roundtrip() {
97 let amount = Amount::eur(999.99);
98 let json = serde_json::to_string(&amount).unwrap();
99 let parsed: Amount = serde_json::from_str(&json).unwrap();
100 assert_eq!(amount, parsed);
101 }
102
103 #[test]
104 fn test_bo4e_object_impl() {
105 assert_eq!(Amount::type_name_german(), "Betrag");
106 assert_eq!(Amount::type_name_english(), "Amount");
107 }
108}