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#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
27#[cfg_attr(feature = "json-schema", schemars(rename = "AufAbschlag"))]
28#[serde(rename_all = "camelCase")]
29pub struct Surcharge {
30 #[serde(flatten)]
32 pub meta: Bo4eMeta,
33
34 #[serde(skip_serializing_if = "Option::is_none")]
36 #[cfg_attr(feature = "json-schema", schemars(rename = "bezeichnung"))]
37 pub description: Option<String>,
38
39 #[serde(skip_serializing_if = "Option::is_none")]
41 #[cfg_attr(feature = "json-schema", schemars(rename = "aufAbschlagstyp"))]
42 pub surcharge_type: Option<SurchargeType>,
43
44 #[serde(skip_serializing_if = "Option::is_none")]
47 #[cfg_attr(feature = "json-schema", schemars(rename = "wert"))]
48 pub value: Option<f64>,
49
50 #[serde(skip_serializing_if = "Option::is_none")]
52 #[cfg_attr(feature = "json-schema", schemars(rename = "waehrungseinheit"))]
53 pub currency: Option<Currency>,
54
55 #[serde(skip_serializing_if = "Option::is_none")]
57 #[cfg_attr(feature = "json-schema", schemars(rename = "aufAbschlagsziel"))]
58 pub target: Option<SurchargeTarget>,
59
60 #[serde(default, skip_serializing_if = "Vec::is_empty")]
62 #[cfg_attr(feature = "json-schema", schemars(rename = "staffeln"))]
63 pub tiers: Vec<PriceTier>,
64
65 #[serde(skip_serializing_if = "Option::is_none")]
67 #[cfg_attr(feature = "json-schema", schemars(rename = "beschreibung"))]
68 pub details: Option<String>,
69
70 #[serde(skip_serializing_if = "Option::is_none")]
72 #[cfg_attr(feature = "json-schema", schemars(rename = "website"))]
73 pub website: Option<String>,
74}
75
76impl Bo4eObject for Surcharge {
77 fn type_name_german() -> &'static str {
78 "AufAbschlag"
79 }
80
81 fn type_name_english() -> &'static str {
82 "Surcharge"
83 }
84
85 fn meta(&self) -> &Bo4eMeta {
86 &self.meta
87 }
88
89 fn meta_mut(&mut self) -> &mut Bo4eMeta {
90 &mut self.meta
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn test_surcharge() {
100 let surcharge = Surcharge {
101 description: Some("Ökosteuer".to_string()),
102 value: Some(0.02),
103 surcharge_type: Some(SurchargeType::Absolute),
104 currency: Some(Currency::Eur),
105 ..Default::default()
106 };
107
108 let json = serde_json::to_string(&surcharge).unwrap();
109 let parsed: Surcharge = serde_json::from_str(&json).unwrap();
110 assert_eq!(surcharge, parsed);
111 }
112
113 #[test]
114 fn test_discount() {
115 let discount = Surcharge {
116 description: Some("Neukunden-Rabatt".to_string()),
117 value: Some(-50.0),
118 surcharge_type: Some(SurchargeType::Absolute),
119 currency: Some(Currency::Eur),
120 ..Default::default()
121 };
122
123 assert!(discount.value.unwrap() < 0.0);
124 }
125
126 #[test]
127 fn test_percentage_surcharge() {
128 let surcharge = Surcharge {
129 description: Some("MwSt".to_string()),
130 value: Some(19.0),
131 surcharge_type: Some(SurchargeType::Relative),
132 ..Default::default()
133 };
134
135 assert_eq!(surcharge.surcharge_type, Some(SurchargeType::Relative));
136 }
137
138 #[test]
139 fn test_tiered_surcharge() {
140 let surcharge = Surcharge {
141 description: Some("Staffelrabatt".to_string()),
142 tiers: vec![
143 PriceTier {
144 lower_limit: Some(0.0),
145 upper_limit: Some(1000.0),
146 unit_price: Some(0.05),
147 ..Default::default()
148 },
149 PriceTier {
150 lower_limit: Some(1000.0),
151 upper_limit: Some(5000.0),
152 unit_price: Some(0.03),
153 ..Default::default()
154 },
155 ],
156 ..Default::default()
157 };
158
159 assert_eq!(surcharge.tiers.len(), 2);
160 }
161
162 #[test]
163 fn test_default() {
164 let surcharge = Surcharge::default();
165 assert!(surcharge.description.is_none());
166 assert!(surcharge.value.is_none());
167 assert!(surcharge.tiers.is_empty());
168 }
169
170 #[test]
171 fn test_bo4e_object_impl() {
172 assert_eq!(Surcharge::type_name_german(), "AufAbschlag");
173 assert_eq!(Surcharge::type_name_english(), "Surcharge");
174 }
175}