Skip to main content

bo4e_core/com/
consumed_quantity.rs

1//! Consumed quantity (VerbrauchteQuantitaet) component.
2
3use serde::{Deserialize, Serialize};
4
5use crate::enums::Unit;
6use crate::traits::{Bo4eMeta, Bo4eObject};
7
8/// A consumed quantity with value and unit.
9///
10/// German: VerbrauchteQuantitaet
11///
12/// # Example
13///
14/// ```rust
15/// use bo4e_core::com::ConsumedQuantity;
16/// use bo4e_core::enums::Unit;
17///
18/// let quantity = ConsumedQuantity {
19///     value: Some(3500.0),
20///     unit: Some(Unit::KilowattHour),
21///     ..Default::default()
22/// };
23/// ```
24#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
25#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
26#[cfg_attr(feature = "json-schema", schemars(rename = "VerbrauchteQuantitaet"))]
27#[serde(rename_all = "camelCase")]
28pub struct ConsumedQuantity {
29    /// BO4E metadata
30    #[serde(flatten)]
31    pub meta: Bo4eMeta,
32
33    /// The quantity value (Wert)
34    #[serde(skip_serializing_if = "Option::is_none")]
35    #[cfg_attr(feature = "json-schema", schemars(rename = "wert"))]
36    pub value: Option<f64>,
37
38    /// Unit of measurement (Einheit)
39    #[serde(skip_serializing_if = "Option::is_none")]
40    #[cfg_attr(feature = "json-schema", schemars(rename = "einheit"))]
41    pub unit: Option<Unit>,
42}
43
44impl Bo4eObject for ConsumedQuantity {
45    fn type_name_german() -> &'static str {
46        "VerbrauchteQuantitaet"
47    }
48
49    fn type_name_english() -> &'static str {
50        "ConsumedQuantity"
51    }
52
53    fn meta(&self) -> &Bo4eMeta {
54        &self.meta
55    }
56
57    fn meta_mut(&mut self) -> &mut Bo4eMeta {
58        &mut self.meta
59    }
60}
61
62impl ConsumedQuantity {
63    /// Create a quantity in kWh.
64    pub fn kwh(value: f64) -> Self {
65        Self {
66            value: Some(value),
67            unit: Some(Unit::KilowattHour),
68            ..Default::default()
69        }
70    }
71
72    /// Create a quantity in cubic meters.
73    pub fn cubic_meters(value: f64) -> Self {
74        Self {
75            value: Some(value),
76            unit: Some(Unit::CubicMeter),
77            ..Default::default()
78        }
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    fn test_kwh_quantity() {
88        let quantity = ConsumedQuantity::kwh(3500.0);
89        assert_eq!(quantity.value, Some(3500.0));
90        assert_eq!(quantity.unit, Some(Unit::KilowattHour));
91    }
92
93    #[test]
94    fn test_cubic_meters() {
95        let quantity = ConsumedQuantity::cubic_meters(1250.0);
96        assert_eq!(quantity.value, Some(1250.0));
97        assert_eq!(quantity.unit, Some(Unit::CubicMeter));
98    }
99
100    #[test]
101    fn test_default() {
102        let quantity = ConsumedQuantity::default();
103        assert!(quantity.value.is_none());
104        assert!(quantity.unit.is_none());
105    }
106
107    #[test]
108    fn test_roundtrip() {
109        let quantity = ConsumedQuantity {
110            value: Some(5678.9),
111            unit: Some(Unit::KilowattHour),
112            ..Default::default()
113        };
114
115        let json = serde_json::to_string(&quantity).unwrap();
116        let parsed: ConsumedQuantity = serde_json::from_str(&json).unwrap();
117        assert_eq!(quantity, parsed);
118    }
119
120    #[test]
121    fn test_bo4e_object_impl() {
122        assert_eq!(
123            ConsumedQuantity::type_name_german(),
124            "VerbrauchteQuantitaet"
125        );
126        assert_eq!(ConsumedQuantity::type_name_english(), "ConsumedQuantity");
127    }
128}