1use serde::{Deserialize, Serialize};
4
5use crate::enums::{Currency, PriceStatus, PriceType, Unit};
6use crate::traits::{Bo4eMeta, Bo4eObject};
7
8#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
26#[serde(rename_all = "camelCase")]
27pub struct Price {
28 #[serde(flatten)]
30 pub meta: Bo4eMeta,
31
32 #[serde(skip_serializing_if = "Option::is_none")]
34 pub value: Option<f64>,
35
36 #[serde(skip_serializing_if = "Option::is_none")]
38 pub currency: Option<Currency>,
39
40 #[serde(skip_serializing_if = "Option::is_none")]
42 pub reference_unit: Option<Unit>,
43
44 #[serde(skip_serializing_if = "Option::is_none")]
46 pub price_type: Option<PriceType>,
47
48 #[serde(skip_serializing_if = "Option::is_none")]
50 pub status: Option<PriceStatus>,
51}
52
53impl Bo4eObject for Price {
54 fn type_name_german() -> &'static str {
55 "Preis"
56 }
57
58 fn type_name_english() -> &'static str {
59 "Price"
60 }
61
62 fn meta(&self) -> &Bo4eMeta {
63 &self.meta
64 }
65
66 fn meta_mut(&mut self) -> &mut Bo4eMeta {
67 &mut self.meta
68 }
69}
70
71impl Price {
72 pub fn eur_per_kwh(value: f64) -> Self {
74 Self {
75 value: Some(value),
76 currency: Some(Currency::Eur),
77 reference_unit: Some(Unit::KilowattHour),
78 ..Default::default()
79 }
80 }
81
82 pub fn eur_per_month(value: f64) -> Self {
84 Self {
85 value: Some(value),
86 currency: Some(Currency::Eur),
87 reference_unit: Some(Unit::Month),
88 price_type: Some(PriceType::BasePrice),
89 ..Default::default()
90 }
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn test_energy_price() {
100 let price = Price::eur_per_kwh(0.30);
101 assert_eq!(price.value, Some(0.30));
102 assert_eq!(price.currency, Some(Currency::Eur));
103 assert_eq!(price.reference_unit, Some(Unit::KilowattHour));
104 }
105
106 #[test]
107 fn test_base_price() {
108 let price = Price::eur_per_month(12.50);
109 assert_eq!(price.value, Some(12.50));
110 assert_eq!(price.currency, Some(Currency::Eur));
111 assert_eq!(price.reference_unit, Some(Unit::Month));
112 assert_eq!(price.price_type, Some(PriceType::BasePrice));
113 }
114
115 #[test]
116 fn test_serialize() {
117 let price = Price {
118 value: Some(12.50),
119 currency: Some(Currency::Eur),
120 ..Default::default()
121 };
122
123 let json = serde_json::to_string(&price).unwrap();
124 assert!(json.contains(r#""value":12.5"#));
125 assert!(json.contains(r#""currency":"EUR""#));
126 }
127
128 #[test]
129 fn test_roundtrip() {
130 let price = Price::eur_per_kwh(0.2567);
131 let json = serde_json::to_string(&price).unwrap();
132 let parsed: Price = serde_json::from_str(&json).unwrap();
133 assert_eq!(price, parsed);
134 }
135
136 #[test]
137 fn test_bo4e_object_impl() {
138 assert_eq!(Price::type_name_german(), "Preis");
139 assert_eq!(Price::type_name_english(), "Price");
140 }
141}