bo4e_core/bo/
tariff_info.rs

1//! Tariff info (Tarifinfo) business object.
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6use crate::com::{EnergyMix, PriceGuarantee, TariffRestriction, TimePeriod};
7use crate::enums::{CustomerType, Division};
8use crate::traits::{Bo4eMeta, Bo4eObject};
9
10/// Tariff information/overview.
11///
12/// Provides summary information about a tariff without the full details.
13///
14/// German: Tarifinfo
15///
16/// # Example
17///
18/// ```rust
19/// use bo4e_core::bo::TariffInfo;
20/// use bo4e_core::enums::{CustomerType, Division};
21///
22/// let tariff_info = TariffInfo {
23///     tariff_name: Some("Oekostrom Basis".to_string()),
24///     division: Some(Division::Electricity),
25///     customer_type: Some(CustomerType::Household),
26///     ..Default::default()
27/// };
28/// ```
29#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
30#[serde(rename_all = "camelCase")]
31pub struct TariffInfo {
32    /// BO4E metadata
33    #[serde(flatten)]
34    pub meta: Bo4eMeta,
35
36    /// Tariff name (Tarifname)
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub tariff_name: Option<String>,
39
40    /// Tariff description (Tarifbeschreibung)
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub description: Option<String>,
43
44    /// Energy division (Sparte)
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub division: Option<Division>,
47
48    /// Target customer type (Kundentyp)
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub customer_type: Option<CustomerType>,
51
52    /// Website URL for tariff information (Website)
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub website: Option<String>,
55
56    /// Validity period (Gueltigkeitszeitraum)
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub validity_period: Option<TimePeriod>,
59
60    /// Start date of tariff availability (Angebotsdatum)
61    #[serde(skip_serializing_if = "Option::is_none")]
62    pub available_from: Option<DateTime<Utc>>,
63
64    /// End date of tariff availability (Enddatum)
65    #[serde(skip_serializing_if = "Option::is_none")]
66    pub available_until: Option<DateTime<Utc>>,
67
68    /// Energy mix composition (Energiemix)
69    #[serde(skip_serializing_if = "Option::is_none")]
70    pub energy_mix: Option<EnergyMix>,
71
72    /// Price guarantee (Preisgarantie)
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub price_guarantee: Option<PriceGuarantee>,
75
76    /// Tariff restrictions (Tarifeinschraenkungen)
77    #[serde(default, skip_serializing_if = "Vec::is_empty")]
78    pub restrictions: Vec<TariffRestriction>,
79
80    /// Provider/supplier
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub supplier: Option<Box<super::BusinessPartner>>,
83}
84
85impl Bo4eObject for TariffInfo {
86    fn type_name_german() -> &'static str {
87        "Tarifinfo"
88    }
89
90    fn type_name_english() -> &'static str {
91        "TariffInfo"
92    }
93
94    fn meta(&self) -> &Bo4eMeta {
95        &self.meta
96    }
97
98    fn meta_mut(&mut self) -> &mut Bo4eMeta {
99        &mut self.meta
100    }
101}
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106
107    #[test]
108    fn test_tariff_info_creation() {
109        let tariff_info = TariffInfo {
110            tariff_name: Some("Oekostrom Basis".to_string()),
111            division: Some(Division::Electricity),
112            customer_type: Some(CustomerType::Household),
113            website: Some("https://example.com/tariff".to_string()),
114            ..Default::default()
115        };
116
117        assert_eq!(tariff_info.tariff_name, Some("Oekostrom Basis".to_string()));
118        assert_eq!(tariff_info.customer_type, Some(CustomerType::Household));
119    }
120
121    #[test]
122    fn test_serialize() {
123        let tariff_info = TariffInfo {
124            meta: Bo4eMeta::with_type("Tarifinfo"),
125            tariff_name: Some("Green Energy".to_string()),
126            division: Some(Division::Electricity),
127            ..Default::default()
128        };
129
130        let json = serde_json::to_string(&tariff_info).unwrap();
131        assert!(json.contains(r#""tariffName":"Green Energy""#));
132        assert!(json.contains(r#""_typ":"Tarifinfo""#));
133    }
134
135    #[test]
136    fn test_roundtrip() {
137        let tariff_info = TariffInfo {
138            meta: Bo4eMeta::with_type("Tarifinfo"),
139            tariff_name: Some("Test Tariff".to_string()),
140            description: Some("A test tariff info".to_string()),
141            division: Some(Division::Gas),
142            customer_type: Some(CustomerType::Commercial),
143            website: Some("https://test.com".to_string()),
144            ..Default::default()
145        };
146
147        let json = serde_json::to_string(&tariff_info).unwrap();
148        let parsed: TariffInfo = serde_json::from_str(&json).unwrap();
149        assert_eq!(tariff_info, parsed);
150    }
151
152    #[test]
153    fn test_bo4e_object_impl() {
154        assert_eq!(TariffInfo::type_name_german(), "Tarifinfo");
155        assert_eq!(TariffInfo::type_name_english(), "TariffInfo");
156    }
157}