Skip to main content

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#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
25#[cfg_attr(feature = "json-schema", schemars(rename = "Tarifeinschraenkung"))]
26#[serde(rename_all = "camelCase")]
27pub struct TariffRestriction {
28    /// BO4E metadata
29    #[serde(flatten)]
30    pub meta: Bo4eMeta,
31
32    /// Applicable customer types (Kundentypen)
33    #[serde(default, skip_serializing_if = "Vec::is_empty")]
34    #[cfg_attr(feature = "json-schema", schemars(rename = "kundentypen"))]
35    pub customer_types: Vec<CustomerType>,
36
37    /// Energy division (Sparte)
38    #[serde(skip_serializing_if = "Option::is_none")]
39    #[cfg_attr(feature = "json-schema", schemars(rename = "sparte"))]
40    pub division: Option<Division>,
41
42    /// Required tariff features (Tarifmerkmale)
43    #[serde(default, skip_serializing_if = "Vec::is_empty")]
44    #[cfg_attr(feature = "json-schema", schemars(rename = "tarifmerkmale"))]
45    pub required_features: Vec<TariffFeature>,
46
47    /// Excluded tariff features (Ausgeschlossene Tarifmerkmale)
48    #[serde(default, skip_serializing_if = "Vec::is_empty")]
49    #[cfg_attr(
50        feature = "json-schema",
51        schemars(rename = "ausgeschlosseneTarifmerkmale")
52    )]
53    pub excluded_features: Vec<TariffFeature>,
54
55    /// Minimum annual consumption (Mindestjahresverbrauch)
56    #[serde(skip_serializing_if = "Option::is_none")]
57    #[cfg_attr(feature = "json-schema", schemars(rename = "mindestjahresverbrauch"))]
58    pub min_annual_consumption: Option<f64>,
59
60    /// Maximum annual consumption (Höchstjahresverbrauch)
61    #[serde(skip_serializing_if = "Option::is_none")]
62    #[cfg_attr(feature = "json-schema", schemars(rename = "hoechstjahresverbrauch"))]
63    pub max_annual_consumption: Option<f64>,
64
65    /// Additional notes (Bemerkung)
66    #[serde(skip_serializing_if = "Option::is_none")]
67    #[cfg_attr(feature = "json-schema", schemars(rename = "bemerkung"))]
68    pub notes: Option<String>,
69}
70
71impl Bo4eObject for TariffRestriction {
72    fn type_name_german() -> &'static str {
73        "Tarifeinschraenkung"
74    }
75
76    fn type_name_english() -> &'static str {
77        "TariffRestriction"
78    }
79
80    fn meta(&self) -> &Bo4eMeta {
81        &self.meta
82    }
83
84    fn meta_mut(&mut self) -> &mut Bo4eMeta {
85        &mut self.meta
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use super::*;
92
93    #[test]
94    fn test_private_customer_tariff() {
95        let restriction = TariffRestriction {
96            customer_types: vec![CustomerType::Private],
97            division: Some(Division::Electricity),
98            max_annual_consumption: Some(10000.0),
99            ..Default::default()
100        };
101
102        assert_eq!(restriction.customer_types, vec![CustomerType::Private]);
103    }
104
105    #[test]
106    fn test_business_tariff_with_features() {
107        let restriction = TariffRestriction {
108            customer_types: vec![CustomerType::Commercial],
109            required_features: vec![TariffFeature::Online],
110            min_annual_consumption: Some(10000.0),
111            ..Default::default()
112        };
113
114        assert_eq!(restriction.required_features.len(), 1);
115    }
116
117    #[test]
118    fn test_default() {
119        let restriction = TariffRestriction::default();
120        assert!(restriction.customer_types.is_empty());
121        assert!(restriction.division.is_none());
122    }
123
124    #[test]
125    fn test_roundtrip() {
126        let restriction = TariffRestriction {
127            customer_types: vec![CustomerType::Private, CustomerType::Commercial],
128            division: Some(Division::Gas),
129            notes: Some("Available in selected areas only".to_string()),
130            ..Default::default()
131        };
132
133        let json = serde_json::to_string(&restriction).unwrap();
134        let parsed: TariffRestriction = serde_json::from_str(&json).unwrap();
135        assert_eq!(restriction, parsed);
136    }
137
138    #[test]
139    fn test_bo4e_object_impl() {
140        assert_eq!(TariffRestriction::type_name_german(), "Tarifeinschraenkung");
141        assert_eq!(TariffRestriction::type_name_english(), "TariffRestriction");
142    }
143}