Skip to main content

bo4e_core/com/
surcharge_per_location.rs

1//! Surcharge per location (AufAbschlagProOrt) component.
2
3use serde::{Deserialize, Serialize};
4
5use crate::traits::{Bo4eMeta, Bo4eObject};
6
7use super::Surcharge;
8
9/// A surcharge or discount that applies to a specific location.
10///
11/// German: AufAbschlagProOrt
12///
13/// # Example
14///
15/// ```rust
16/// use bo4e_core::com::SurchargePerLocation;
17///
18/// let surcharge = SurchargePerLocation {
19///     postal_code: Some("50667".to_string()),
20///     municipality: Some("Köln".to_string()),
21///     ..Default::default()
22/// };
23/// ```
24#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
25#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
26#[cfg_attr(feature = "json-schema", schemars(rename = "AufAbschlagProOrt"))]
27#[serde(rename_all = "camelCase")]
28pub struct SurchargePerLocation {
29    /// BO4E metadata
30    #[serde(flatten)]
31    pub meta: Bo4eMeta,
32
33    /// Postal code (Postleitzahl)
34    #[serde(skip_serializing_if = "Option::is_none")]
35    #[cfg_attr(feature = "json-schema", schemars(rename = "postleitzahl"))]
36    pub postal_code: Option<String>,
37
38    /// Municipality/city (Ort)
39    #[serde(skip_serializing_if = "Option::is_none")]
40    #[cfg_attr(feature = "json-schema", schemars(rename = "ort"))]
41    pub municipality: Option<String>,
42
43    /// Network area code (Netznummer)
44    #[serde(skip_serializing_if = "Option::is_none")]
45    #[cfg_attr(feature = "json-schema", schemars(rename = "netznummer"))]
46    pub network_area_code: Option<String>,
47
48    /// Surcharges applicable to this location (AufAbschläge)
49    #[serde(default, skip_serializing_if = "Vec::is_empty")]
50    #[cfg_attr(feature = "json-schema", schemars(rename = "aufAbschlaege"))]
51    pub surcharges: Vec<Surcharge>,
52}
53
54impl Bo4eObject for SurchargePerLocation {
55    fn type_name_german() -> &'static str {
56        "AufAbschlagProOrt"
57    }
58
59    fn type_name_english() -> &'static str {
60        "SurchargePerLocation"
61    }
62
63    fn meta(&self) -> &Bo4eMeta {
64        &self.meta
65    }
66
67    fn meta_mut(&mut self) -> &mut Bo4eMeta {
68        &mut self.meta
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn test_location_surcharge() {
78        let surcharge = SurchargePerLocation {
79            postal_code: Some("50667".to_string()),
80            municipality: Some("Köln".to_string()),
81            surcharges: vec![Surcharge {
82                description: Some("Konzessionsabgabe".to_string()),
83                value: Some(1.59),
84                ..Default::default()
85            }],
86            ..Default::default()
87        };
88
89        assert_eq!(surcharge.postal_code, Some("50667".to_string()));
90        assert_eq!(surcharge.surcharges.len(), 1);
91    }
92
93    #[test]
94    fn test_default() {
95        let surcharge = SurchargePerLocation::default();
96        assert!(surcharge.postal_code.is_none());
97        assert!(surcharge.surcharges.is_empty());
98    }
99
100    #[test]
101    fn test_roundtrip() {
102        let surcharge = SurchargePerLocation {
103            postal_code: Some("80331".to_string()),
104            municipality: Some("München".to_string()),
105            network_area_code: Some("9900001".to_string()),
106            ..Default::default()
107        };
108
109        let json = serde_json::to_string(&surcharge).unwrap();
110        let parsed: SurchargePerLocation = serde_json::from_str(&json).unwrap();
111        assert_eq!(surcharge, parsed);
112    }
113
114    #[test]
115    fn test_bo4e_object_impl() {
116        assert_eq!(
117            SurchargePerLocation::type_name_german(),
118            "AufAbschlagProOrt"
119        );
120        assert_eq!(
121            SurchargePerLocation::type_name_english(),
122            "SurchargePerLocation"
123        );
124    }
125}