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#[serde(rename_all = "camelCase")]
32pub struct TariffCosts {
33 #[serde(flatten)]
35 pub meta: Bo4eMeta,
36
37 #[serde(skip_serializing_if = "Option::is_none")]
39 pub designation: Option<String>,
40
41 #[serde(skip_serializing_if = "Option::is_none")]
43 pub description: Option<String>,
44
45 #[serde(skip_serializing_if = "Option::is_none")]
47 pub division: Option<Division>,
48
49 #[serde(skip_serializing_if = "Option::is_none")]
51 pub period: Option<TimePeriod>,
52
53 #[serde(skip_serializing_if = "Option::is_none")]
55 pub total_amount: Option<Amount>,
56
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub base_price: Option<Price>,
60
61 #[serde(skip_serializing_if = "Option::is_none")]
63 pub base_price_cost: Option<Amount>,
64
65 #[serde(skip_serializing_if = "Option::is_none")]
67 pub working_price: Option<Price>,
68
69 #[serde(skip_serializing_if = "Option::is_none")]
71 pub working_price_cost: Option<Amount>,
72
73 #[serde(skip_serializing_if = "Option::is_none")]
75 pub consumption: Option<f64>,
76
77 #[serde(default, skip_serializing_if = "Vec::is_empty")]
79 pub cost_blocks: Vec<CostBlock>,
80
81 #[serde(skip_serializing_if = "Option::is_none")]
83 pub tariff: Option<Box<super::Tariff>>,
84}
85
86impl Bo4eObject for TariffCosts {
87 fn type_name_german() -> &'static str {
88 "Tarifkosten"
89 }
90
91 fn type_name_english() -> &'static str {
92 "TariffCosts"
93 }
94
95 fn meta(&self) -> &Bo4eMeta {
96 &self.meta
97 }
98
99 fn meta_mut(&mut self) -> &mut Bo4eMeta {
100 &mut self.meta
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn test_tariff_costs_creation() {
110 let tariff_costs = TariffCosts {
111 designation: Some("Haushaltstarif Kosten".to_string()),
112 division: Some(Division::Electricity),
113 base_price: Some(Price::eur_per_month(9.95)),
114 base_price_cost: Some(Amount::eur(119.40)),
115 working_price: Some(Price::eur_per_kwh(0.32)),
116 working_price_cost: Some(Amount::eur(960.00)),
117 consumption: Some(3000.0),
118 total_amount: Some(Amount::eur(1079.40)),
119 ..Default::default()
120 };
121
122 assert_eq!(tariff_costs.consumption, Some(3000.0));
123 }
124
125 #[test]
126 fn test_serialize() {
127 let tariff_costs = TariffCosts {
128 meta: Bo4eMeta::with_type("Tarifkosten"),
129 designation: Some("Test Tariff Costs".to_string()),
130 total_amount: Some(Amount::eur(500.0)),
131 ..Default::default()
132 };
133
134 let json = serde_json::to_string(&tariff_costs).unwrap();
135 assert!(json.contains(r#""designation":"Test Tariff Costs""#));
136 assert!(json.contains(r#""_typ":"Tarifkosten""#));
137 }
138
139 #[test]
140 fn test_roundtrip() {
141 let tariff_costs = TariffCosts {
142 meta: Bo4eMeta::with_type("Tarifkosten"),
143 designation: Some("Gas Tariff Costs".to_string()),
144 description: Some("Annual gas tariff costs".to_string()),
145 division: Some(Division::Gas),
146 consumption: Some(15000.0),
147 total_amount: Some(Amount::eur(1500.0)),
148 ..Default::default()
149 };
150
151 let json = serde_json::to_string(&tariff_costs).unwrap();
152 let parsed: TariffCosts = serde_json::from_str(&json).unwrap();
153 assert_eq!(tariff_costs, parsed);
154 }
155
156 #[test]
157 fn test_bo4e_object_impl() {
158 assert_eq!(TariffCosts::type_name_german(), "Tarifkosten");
159 assert_eq!(TariffCosts::type_name_english(), "TariffCosts");
160 }
161}