bo4e_core/com/
regional_surcharge.rs

1//! Regional surcharge (AufAbschlagRegional) component.
2
3use serde::{Deserialize, Serialize};
4
5use crate::enums::TariffRegionCriterion;
6use crate::traits::{Bo4eMeta, Bo4eObject};
7
8use super::Surcharge;
9
10/// A surcharge that applies to a specific regional criterion.
11///
12/// German: AufAbschlagRegional
13///
14/// # Example
15///
16/// ```rust
17/// use bo4e_core::com::RegionalSurcharge;
18/// use bo4e_core::enums::TariffRegionCriterion;
19///
20/// let surcharge = RegionalSurcharge {
21///     region_criterion: Some(TariffRegionCriterion::PostalCode),
22///     region_code: Some("50*".to_string()),
23///     ..Default::default()
24/// };
25/// ```
26#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
27#[serde(rename_all = "camelCase")]
28pub struct RegionalSurcharge {
29    /// BO4E metadata
30    #[serde(flatten)]
31    pub meta: Bo4eMeta,
32
33    /// Type of regional criterion (Tarifregionskriterium)
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub region_criterion: Option<TariffRegionCriterion>,
36
37    /// Region code/value (Regionscode)
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub region_code: Option<String>,
40
41    /// Surcharges applicable to this region (AufAbschläge)
42    #[serde(default, skip_serializing_if = "Vec::is_empty")]
43    pub surcharges: Vec<Surcharge>,
44}
45
46impl Bo4eObject for RegionalSurcharge {
47    fn type_name_german() -> &'static str {
48        "AufAbschlagRegional"
49    }
50
51    fn type_name_english() -> &'static str {
52        "RegionalSurcharge"
53    }
54
55    fn meta(&self) -> &Bo4eMeta {
56        &self.meta
57    }
58
59    fn meta_mut(&mut self) -> &mut Bo4eMeta {
60        &mut self.meta
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn test_postal_region_surcharge() {
70        let surcharge = RegionalSurcharge {
71            region_criterion: Some(TariffRegionCriterion::PostalCode),
72            region_code: Some("50*".to_string()),
73            surcharges: vec![Surcharge {
74                description: Some("Regional discount".to_string()),
75                value: Some(-5.0),
76                ..Default::default()
77            }],
78            ..Default::default()
79        };
80
81        assert_eq!(
82            surcharge.region_criterion,
83            Some(TariffRegionCriterion::PostalCode)
84        );
85        assert_eq!(surcharge.surcharges.len(), 1);
86    }
87
88    #[test]
89    fn test_default() {
90        let surcharge = RegionalSurcharge::default();
91        assert!(surcharge.region_criterion.is_none());
92        assert!(surcharge.surcharges.is_empty());
93    }
94
95    #[test]
96    fn test_roundtrip() {
97        let surcharge = RegionalSurcharge {
98            region_criterion: Some(TariffRegionCriterion::NetworkNumber),
99            region_code: Some("9990001".to_string()),
100            ..Default::default()
101        };
102
103        let json = serde_json::to_string(&surcharge).unwrap();
104        let parsed: RegionalSurcharge = serde_json::from_str(&json).unwrap();
105        assert_eq!(surcharge, parsed);
106    }
107
108    #[test]
109    fn test_bo4e_object_impl() {
110        assert_eq!(RegionalSurcharge::type_name_german(), "AufAbschlagRegional");
111        assert_eq!(RegionalSurcharge::type_name_english(), "RegionalSurcharge");
112    }
113}