Skip to main content

bo4e_core/com/
service_price.rs

1//! Service price (Dienstleistungspreis) component.
2
3use serde::{Deserialize, Serialize};
4
5use crate::enums::{Currency, ServiceType, Unit};
6use crate::traits::{Bo4eMeta, Bo4eObject};
7
8/// A price for a service.
9///
10/// German: Dienstleistungspreis
11///
12/// # Example
13///
14/// ```rust
15/// use bo4e_core::com::ServicePrice;
16/// use bo4e_core::enums::ServiceType;
17///
18/// let price = ServicePrice {
19///     service_type: Some(ServiceType::Disconnection),
20///     value: Some(75.0),
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 = "Dienstleistungspreis"))]
27#[serde(rename_all = "camelCase")]
28pub struct ServicePrice {
29    /// BO4E metadata
30    #[serde(flatten)]
31    pub meta: Bo4eMeta,
32
33    /// Type of service (Dienstleistungstyp)
34    #[serde(skip_serializing_if = "Option::is_none")]
35    #[cfg_attr(feature = "json-schema", schemars(rename = "dienstleistungstyp"))]
36    pub service_type: Option<ServiceType>,
37
38    /// Price value (Wert)
39    #[serde(skip_serializing_if = "Option::is_none")]
40    #[cfg_attr(feature = "json-schema", schemars(rename = "wert"))]
41    pub value: Option<f64>,
42
43    /// Currency (Waehrung)
44    #[serde(skip_serializing_if = "Option::is_none")]
45    #[cfg_attr(feature = "json-schema", schemars(rename = "waehrung"))]
46    pub currency: Option<Currency>,
47
48    /// Reference unit (Bezugseinheit)
49    #[serde(skip_serializing_if = "Option::is_none")]
50    #[cfg_attr(feature = "json-schema", schemars(rename = "bezugseinheit"))]
51    pub reference_unit: Option<Unit>,
52
53    /// Description (Beschreibung)
54    #[serde(skip_serializing_if = "Option::is_none")]
55    #[cfg_attr(feature = "json-schema", schemars(rename = "beschreibung"))]
56    pub description: Option<String>,
57}
58
59impl Bo4eObject for ServicePrice {
60    fn type_name_german() -> &'static str {
61        "Dienstleistungspreis"
62    }
63
64    fn type_name_english() -> &'static str {
65        "ServicePrice"
66    }
67
68    fn meta(&self) -> &Bo4eMeta {
69        &self.meta
70    }
71
72    fn meta_mut(&mut self) -> &mut Bo4eMeta {
73        &mut self.meta
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80
81    #[test]
82    fn test_installation_service() {
83        let price = ServicePrice {
84            service_type: Some(ServiceType::Disconnection),
85            value: Some(75.0),
86            currency: Some(Currency::Eur),
87            description: Some("Zählerinstallation".to_string()),
88            ..Default::default()
89        };
90
91        assert_eq!(price.service_type, Some(ServiceType::Disconnection));
92        assert_eq!(price.value, Some(75.0));
93    }
94
95    #[test]
96    fn test_default() {
97        let price = ServicePrice::default();
98        assert!(price.service_type.is_none());
99        assert!(price.value.is_none());
100    }
101
102    #[test]
103    fn test_roundtrip() {
104        let price = ServicePrice {
105            service_type: Some(ServiceType::ManualReadingMonthly),
106            value: Some(50.0),
107            currency: Some(Currency::Eur),
108            reference_unit: Some(Unit::Hour),
109            description: Some("Energieberatung".to_string()),
110            ..Default::default()
111        };
112
113        let json = serde_json::to_string(&price).unwrap();
114        let parsed: ServicePrice = serde_json::from_str(&json).unwrap();
115        assert_eq!(price, parsed);
116    }
117
118    #[test]
119    fn test_bo4e_object_impl() {
120        assert_eq!(ServicePrice::type_name_german(), "Dienstleistungspreis");
121        assert_eq!(ServicePrice::type_name_english(), "ServicePrice");
122    }
123}