bo4e_core/com/
surcharge.rs1use serde::{Deserialize, Serialize};
4
5use crate::enums::{Currency, SurchargeTarget, SurchargeType};
6use crate::traits::{Bo4eMeta, Bo4eObject};
7
8use super::PriceTier;
9
10#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
26#[serde(rename_all = "camelCase")]
27pub struct Surcharge {
28 #[serde(flatten)]
30 pub meta: Bo4eMeta,
31
32 #[serde(skip_serializing_if = "Option::is_none")]
34 pub description: Option<String>,
35
36 #[serde(skip_serializing_if = "Option::is_none")]
38 pub surcharge_type: Option<SurchargeType>,
39
40 #[serde(skip_serializing_if = "Option::is_none")]
43 pub value: Option<f64>,
44
45 #[serde(skip_serializing_if = "Option::is_none")]
47 pub currency: Option<Currency>,
48
49 #[serde(skip_serializing_if = "Option::is_none")]
51 pub target: Option<SurchargeTarget>,
52
53 #[serde(default, skip_serializing_if = "Vec::is_empty")]
55 pub tiers: Vec<PriceTier>,
56
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub details: Option<String>,
60
61 #[serde(skip_serializing_if = "Option::is_none")]
63 pub website: Option<String>,
64}
65
66impl Bo4eObject for Surcharge {
67 fn type_name_german() -> &'static str {
68 "AufAbschlag"
69 }
70
71 fn type_name_english() -> &'static str {
72 "Surcharge"
73 }
74
75 fn meta(&self) -> &Bo4eMeta {
76 &self.meta
77 }
78
79 fn meta_mut(&mut self) -> &mut Bo4eMeta {
80 &mut self.meta
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 #[test]
89 fn test_surcharge() {
90 let surcharge = Surcharge {
91 description: Some("Ökosteuer".to_string()),
92 value: Some(0.02),
93 surcharge_type: Some(SurchargeType::Absolute),
94 currency: Some(Currency::Eur),
95 ..Default::default()
96 };
97
98 let json = serde_json::to_string(&surcharge).unwrap();
99 let parsed: Surcharge = serde_json::from_str(&json).unwrap();
100 assert_eq!(surcharge, parsed);
101 }
102
103 #[test]
104 fn test_discount() {
105 let discount = Surcharge {
106 description: Some("Neukunden-Rabatt".to_string()),
107 value: Some(-50.0),
108 surcharge_type: Some(SurchargeType::Absolute),
109 currency: Some(Currency::Eur),
110 ..Default::default()
111 };
112
113 assert!(discount.value.unwrap() < 0.0);
114 }
115
116 #[test]
117 fn test_percentage_surcharge() {
118 let surcharge = Surcharge {
119 description: Some("MwSt".to_string()),
120 value: Some(19.0),
121 surcharge_type: Some(SurchargeType::Relative),
122 ..Default::default()
123 };
124
125 assert_eq!(surcharge.surcharge_type, Some(SurchargeType::Relative));
126 }
127
128 #[test]
129 fn test_tiered_surcharge() {
130 let surcharge = Surcharge {
131 description: Some("Staffelrabatt".to_string()),
132 tiers: vec![
133 PriceTier {
134 lower_limit: Some(0.0),
135 upper_limit: Some(1000.0),
136 unit_price: Some(0.05),
137 ..Default::default()
138 },
139 PriceTier {
140 lower_limit: Some(1000.0),
141 upper_limit: Some(5000.0),
142 unit_price: Some(0.03),
143 ..Default::default()
144 },
145 ],
146 ..Default::default()
147 };
148
149 assert_eq!(surcharge.tiers.len(), 2);
150 }
151
152 #[test]
153 fn test_default() {
154 let surcharge = Surcharge::default();
155 assert!(surcharge.description.is_none());
156 assert!(surcharge.value.is_none());
157 assert!(surcharge.tiers.is_empty());
158 }
159
160 #[test]
161 fn test_bo4e_object_impl() {
162 assert_eq!(Surcharge::type_name_german(), "AufAbschlag");
163 assert_eq!(Surcharge::type_name_english(), "Surcharge");
164 }
165}