bo4e_core/bo/
tariff_costs.rs1use serde::{Deserialize, Serialize};
4
5use crate::com::{Amount, CostBlock, Price, TimePeriod};
6use crate::enums::Division;
7use crate::traits::{Bo4eMeta, Bo4eObject};
8
9#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
31#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
32#[cfg_attr(feature = "json-schema", schemars(rename = "Tarifkosten"))]
33#[serde(rename_all = "camelCase")]
34pub struct TariffCosts {
35 #[serde(flatten)]
37 pub meta: Bo4eMeta,
38
39 #[serde(skip_serializing_if = "Option::is_none")]
41 #[cfg_attr(feature = "json-schema", schemars(rename = "bezeichnung"))]
42 pub designation: Option<String>,
43
44 #[serde(skip_serializing_if = "Option::is_none")]
46 #[cfg_attr(feature = "json-schema", schemars(rename = "beschreibung"))]
47 pub description: Option<String>,
48
49 #[serde(skip_serializing_if = "Option::is_none")]
51 #[cfg_attr(feature = "json-schema", schemars(rename = "sparte"))]
52 pub division: Option<Division>,
53
54 #[serde(skip_serializing_if = "Option::is_none")]
56 #[cfg_attr(feature = "json-schema", schemars(rename = "abrechnungszeitraum"))]
57 pub period: Option<TimePeriod>,
58
59 #[serde(skip_serializing_if = "Option::is_none")]
61 #[cfg_attr(feature = "json-schema", schemars(rename = "gesamtbetrag"))]
62 pub total_amount: Option<Amount>,
63
64 #[serde(skip_serializing_if = "Option::is_none")]
66 #[cfg_attr(feature = "json-schema", schemars(rename = "grundpreis"))]
67 pub base_price: Option<Price>,
68
69 #[serde(skip_serializing_if = "Option::is_none")]
71 #[cfg_attr(feature = "json-schema", schemars(rename = "grundpreiskosten"))]
72 pub base_price_cost: Option<Amount>,
73
74 #[serde(skip_serializing_if = "Option::is_none")]
76 #[cfg_attr(feature = "json-schema", schemars(rename = "arbeitspreis"))]
77 pub working_price: Option<Price>,
78
79 #[serde(skip_serializing_if = "Option::is_none")]
81 #[cfg_attr(feature = "json-schema", schemars(rename = "arbeitspreiskosten"))]
82 pub working_price_cost: Option<Amount>,
83
84 #[serde(skip_serializing_if = "Option::is_none")]
86 #[cfg_attr(feature = "json-schema", schemars(rename = "verbrauchsmenge"))]
87 pub consumption: Option<f64>,
88
89 #[serde(default, skip_serializing_if = "Vec::is_empty")]
91 #[cfg_attr(feature = "json-schema", schemars(rename = "kostenbloecke"))]
92 pub cost_blocks: Vec<CostBlock>,
93
94 #[serde(skip_serializing_if = "Option::is_none")]
96 #[cfg_attr(feature = "json-schema", schemars(rename = "tarif"))]
97 pub tariff: Option<Box<super::Tariff>>,
98}
99
100impl Bo4eObject for TariffCosts {
101 fn type_name_german() -> &'static str {
102 "Tarifkosten"
103 }
104
105 fn type_name_english() -> &'static str {
106 "TariffCosts"
107 }
108
109 fn meta(&self) -> &Bo4eMeta {
110 &self.meta
111 }
112
113 fn meta_mut(&mut self) -> &mut Bo4eMeta {
114 &mut self.meta
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn test_tariff_costs_creation() {
124 let tariff_costs = TariffCosts {
125 designation: Some("Haushaltstarif Kosten".to_string()),
126 division: Some(Division::Electricity),
127 base_price: Some(Price::eur_per_month(9.95)),
128 base_price_cost: Some(Amount::eur(119.40)),
129 working_price: Some(Price::eur_per_kwh(0.32)),
130 working_price_cost: Some(Amount::eur(960.00)),
131 consumption: Some(3000.0),
132 total_amount: Some(Amount::eur(1079.40)),
133 ..Default::default()
134 };
135
136 assert_eq!(tariff_costs.consumption, Some(3000.0));
137 }
138
139 #[test]
140 fn test_serialize() {
141 let tariff_costs = TariffCosts {
142 meta: Bo4eMeta::with_type("Tarifkosten"),
143 designation: Some("Test Tariff Costs".to_string()),
144 total_amount: Some(Amount::eur(500.0)),
145 ..Default::default()
146 };
147
148 let json = serde_json::to_string(&tariff_costs).unwrap();
149 assert!(json.contains(r#""designation":"Test Tariff Costs""#));
150 assert!(json.contains(r#""_typ":"Tarifkosten""#));
151 }
152
153 #[test]
154 fn test_roundtrip() {
155 let tariff_costs = TariffCosts {
156 meta: Bo4eMeta::with_type("Tarifkosten"),
157 designation: Some("Gas Tariff Costs".to_string()),
158 description: Some("Annual gas tariff costs".to_string()),
159 division: Some(Division::Gas),
160 consumption: Some(15000.0),
161 total_amount: Some(Amount::eur(1500.0)),
162 ..Default::default()
163 };
164
165 let json = serde_json::to_string(&tariff_costs).unwrap();
166 let parsed: TariffCosts = serde_json::from_str(&json).unwrap();
167 assert_eq!(tariff_costs, parsed);
168 }
169
170 #[test]
171 fn test_bo4e_object_impl() {
172 assert_eq!(TariffCosts::type_name_german(), "Tarifkosten");
173 assert_eq!(TariffCosts::type_name_english(), "TariffCosts");
174 }
175}