Skip to main content

bo4e_core/bo/
concession_fee_price_sheet.rs

1//! Concession fee price sheet (PreisblattKonzessionsabgabe) business object.
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6use crate::com::{ConcessionFee, TimePeriod};
7use crate::enums::{ConcessionFeeCustomerGroup, Division};
8use crate::traits::{Bo4eMeta, Bo4eObject};
9
10/// A price sheet for concession fees.
11///
12/// Concession fees are paid to municipalities for the use of public
13/// ways for energy infrastructure.
14///
15/// German: PreisblattKonzessionsabgabe
16///
17/// # Example
18///
19/// ```rust
20/// use bo4e_core::bo::ConcessionFeePriceSheet;
21/// use bo4e_core::enums::Division;
22///
23/// let price_sheet = ConcessionFeePriceSheet {
24///     designation: Some("Konzessionsabgaben 2024".to_string()),
25///     division: Some(Division::Electricity),
26///     ..Default::default()
27/// };
28/// ```
29#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
30#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
31#[cfg_attr(
32    feature = "json-schema",
33    schemars(rename = "PreisblattKonzessionsabgabe")
34)]
35#[serde(rename_all = "camelCase")]
36pub struct ConcessionFeePriceSheet {
37    /// BO4E metadata
38    #[serde(flatten)]
39    pub meta: Bo4eMeta,
40
41    /// Name/designation of the price sheet (Bezeichnung)
42    #[serde(skip_serializing_if = "Option::is_none")]
43    #[cfg_attr(feature = "json-schema", schemars(rename = "bezeichnung"))]
44    pub designation: Option<String>,
45
46    /// Description (Beschreibung)
47    #[serde(skip_serializing_if = "Option::is_none")]
48    #[cfg_attr(feature = "json-schema", schemars(rename = "beschreibung"))]
49    pub description: Option<String>,
50
51    /// Energy division (Sparte)
52    #[serde(skip_serializing_if = "Option::is_none")]
53    #[cfg_attr(feature = "json-schema", schemars(rename = "sparte"))]
54    pub division: Option<Division>,
55
56    /// Customer group for concession fees (Kundengruppe)
57    #[serde(skip_serializing_if = "Option::is_none")]
58    #[cfg_attr(feature = "json-schema", schemars(rename = "kundengruppe"))]
59    pub customer_group: Option<ConcessionFeeCustomerGroup>,
60
61    /// Price sheet number/identifier (Preisblattnummer)
62    #[serde(skip_serializing_if = "Option::is_none")]
63    #[cfg_attr(feature = "json-schema", schemars(rename = "preisblattnummer"))]
64    pub price_sheet_number: Option<String>,
65
66    /// Validity period (Gueltigkeitszeitraum)
67    #[serde(skip_serializing_if = "Option::is_none")]
68    #[cfg_attr(feature = "json-schema", schemars(rename = "gueltigkeitszeitraum"))]
69    pub validity_period: Option<TimePeriod>,
70
71    /// Valid from date (Gueltig ab)
72    #[serde(skip_serializing_if = "Option::is_none")]
73    #[cfg_attr(feature = "json-schema", schemars(rename = "gueltigAb"))]
74    pub valid_from: Option<DateTime<Utc>>,
75
76    /// Valid until date (Gueltig bis)
77    #[serde(skip_serializing_if = "Option::is_none")]
78    #[cfg_attr(feature = "json-schema", schemars(rename = "gueltigBis"))]
79    pub valid_until: Option<DateTime<Utc>>,
80
81    /// Concession fees (Konzessionsabgaben)
82    #[serde(default, skip_serializing_if = "Vec::is_empty")]
83    #[cfg_attr(feature = "json-schema", schemars(rename = "konzessionsabgaben"))]
84    pub concession_fees: Vec<ConcessionFee>,
85
86    /// Municipality/area name (Gemeindebezeichnung)
87    #[serde(skip_serializing_if = "Option::is_none")]
88    #[cfg_attr(feature = "json-schema", schemars(rename = "gemeindebezeichnung"))]
89    pub municipality: Option<String>,
90
91    /// Network operator
92    #[serde(skip_serializing_if = "Option::is_none")]
93    #[cfg_attr(feature = "json-schema", schemars(rename = "netzbetreiber"))]
94    pub operator: Option<Box<super::BusinessPartner>>,
95}
96
97impl Bo4eObject for ConcessionFeePriceSheet {
98    fn type_name_german() -> &'static str {
99        "PreisblattKonzessionsabgabe"
100    }
101
102    fn type_name_english() -> &'static str {
103        "ConcessionFeePriceSheet"
104    }
105
106    fn meta(&self) -> &Bo4eMeta {
107        &self.meta
108    }
109
110    fn meta_mut(&mut self) -> &mut Bo4eMeta {
111        &mut self.meta
112    }
113}
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118
119    #[test]
120    fn test_concession_fee_price_sheet_creation() {
121        let price_sheet = ConcessionFeePriceSheet {
122            designation: Some("Konzessionsabgaben 2024".to_string()),
123            division: Some(Division::Electricity),
124            customer_group: Some(ConcessionFeeCustomerGroup::ElectricityTariff25000),
125            municipality: Some("Musterstadt".to_string()),
126            price_sheet_number: Some("KA-2024-001".to_string()),
127            ..Default::default()
128        };
129
130        assert_eq!(
131            price_sheet.customer_group,
132            Some(ConcessionFeeCustomerGroup::ElectricityTariff25000)
133        );
134    }
135
136    #[test]
137    fn test_serialize() {
138        let price_sheet = ConcessionFeePriceSheet {
139            meta: Bo4eMeta::with_type("PreisblattKonzessionsabgabe"),
140            designation: Some("Concession Fees".to_string()),
141            ..Default::default()
142        };
143
144        let json = serde_json::to_string(&price_sheet).unwrap();
145        assert!(json.contains(r#""designation":"Concession Fees""#));
146        assert!(json.contains(r#""_typ":"PreisblattKonzessionsabgabe""#));
147    }
148
149    #[test]
150    fn test_roundtrip() {
151        let price_sheet = ConcessionFeePriceSheet {
152            meta: Bo4eMeta::with_type("PreisblattKonzessionsabgabe"),
153            designation: Some("Municipal Fees".to_string()),
154            description: Some("Concession fees for municipality".to_string()),
155            division: Some(Division::Electricity),
156            municipality: Some("Teststadt".to_string()),
157            price_sheet_number: Some("MF-2024".to_string()),
158            ..Default::default()
159        };
160
161        let json = serde_json::to_string(&price_sheet).unwrap();
162        let parsed: ConcessionFeePriceSheet = serde_json::from_str(&json).unwrap();
163        assert_eq!(price_sheet, parsed);
164    }
165
166    #[test]
167    fn test_bo4e_object_impl() {
168        assert_eq!(
169            ConcessionFeePriceSheet::type_name_german(),
170            "PreisblattKonzessionsabgabe"
171        );
172        assert_eq!(
173            ConcessionFeePriceSheet::type_name_english(),
174            "ConcessionFeePriceSheet"
175        );
176    }
177}