bo4e_core/com/
tariff_restriction.rs

1//! Tariff restriction (Tarifeinschraenkung) component.
2
3use serde::{Deserialize, Serialize};
4
5use crate::enums::{CustomerType, Division, TariffFeature};
6use crate::traits::{Bo4eMeta, Bo4eObject};
7
8/// Restrictions that apply to a tariff.
9///
10/// German: Tarifeinschraenkung
11///
12/// # Example
13///
14/// ```rust
15/// use bo4e_core::com::TariffRestriction;
16/// use bo4e_core::enums::CustomerType;
17///
18/// let restriction = TariffRestriction {
19///     customer_types: vec![CustomerType::Private],
20///     ..Default::default()
21/// };
22/// ```
23#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
24#[serde(rename_all = "camelCase")]
25pub struct TariffRestriction {
26    /// BO4E metadata
27    #[serde(flatten)]
28    pub meta: Bo4eMeta,
29
30    /// Applicable customer types (Kundentypen)
31    #[serde(default, skip_serializing_if = "Vec::is_empty")]
32    pub customer_types: Vec<CustomerType>,
33
34    /// Energy division (Sparte)
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub division: Option<Division>,
37
38    /// Required tariff features (Tarifmerkmale)
39    #[serde(default, skip_serializing_if = "Vec::is_empty")]
40    pub required_features: Vec<TariffFeature>,
41
42    /// Excluded tariff features (Ausgeschlossene Tarifmerkmale)
43    #[serde(default, skip_serializing_if = "Vec::is_empty")]
44    pub excluded_features: Vec<TariffFeature>,
45
46    /// Minimum annual consumption (Mindestjahresverbrauch)
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub min_annual_consumption: Option<f64>,
49
50    /// Maximum annual consumption (Höchstjahresverbrauch)
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub max_annual_consumption: Option<f64>,
53
54    /// Additional notes (Bemerkung)
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub notes: Option<String>,
57}
58
59impl Bo4eObject for TariffRestriction {
60    fn type_name_german() -> &'static str {
61        "Tarifeinschraenkung"
62    }
63
64    fn type_name_english() -> &'static str {
65        "TariffRestriction"
66    }
67
68    fn meta(&self) -> &Bo4eMeta {
69        &self.meta
70    }
71
72    fn meta_mut(&mut self) -> &mut Bo4eMeta {
73        &mut self.meta
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80
81    #[test]
82    fn test_private_customer_tariff() {
83        let restriction = TariffRestriction {
84            customer_types: vec![CustomerType::Private],
85            division: Some(Division::Electricity),
86            max_annual_consumption: Some(10000.0),
87            ..Default::default()
88        };
89
90        assert_eq!(restriction.customer_types, vec![CustomerType::Private]);
91    }
92
93    #[test]
94    fn test_business_tariff_with_features() {
95        let restriction = TariffRestriction {
96            customer_types: vec![CustomerType::Commercial],
97            required_features: vec![TariffFeature::Online],
98            min_annual_consumption: Some(10000.0),
99            ..Default::default()
100        };
101
102        assert_eq!(restriction.required_features.len(), 1);
103    }
104
105    #[test]
106    fn test_default() {
107        let restriction = TariffRestriction::default();
108        assert!(restriction.customer_types.is_empty());
109        assert!(restriction.division.is_none());
110    }
111
112    #[test]
113    fn test_roundtrip() {
114        let restriction = TariffRestriction {
115            customer_types: vec![CustomerType::Private, CustomerType::Commercial],
116            division: Some(Division::Gas),
117            notes: Some("Available in selected areas only".to_string()),
118            ..Default::default()
119        };
120
121        let json = serde_json::to_string(&restriction).unwrap();
122        let parsed: TariffRestriction = serde_json::from_str(&json).unwrap();
123        assert_eq!(restriction, parsed);
124    }
125
126    #[test]
127    fn test_bo4e_object_impl() {
128        assert_eq!(TariffRestriction::type_name_german(), "Tarifeinschraenkung");
129        assert_eq!(TariffRestriction::type_name_english(), "TariffRestriction");
130    }
131}