bo4e_core/com/
price_guarantee.rs

1//! Price guarantee (Preisgarantie) component.
2
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6use crate::enums::PriceGuaranteeType;
7use crate::traits::{Bo4eMeta, Bo4eObject};
8
9/// A price guarantee specifying which price components are fixed.
10///
11/// German: Preisgarantie
12///
13/// # Example
14///
15/// ```rust
16/// use bo4e_core::com::PriceGuarantee;
17/// use bo4e_core::enums::PriceGuaranteeType;
18///
19/// let guarantee = PriceGuarantee {
20///     guarantee_type: Some(PriceGuaranteeType::AllComponentsGross),
21///     description: Some("12-month price guarantee".to_string()),
22///     ..Default::default()
23/// };
24/// ```
25#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
26#[serde(rename_all = "camelCase")]
27pub struct PriceGuarantee {
28    /// BO4E metadata
29    #[serde(flatten)]
30    pub meta: Bo4eMeta,
31
32    /// Type of price guarantee (Preisgarantietyp)
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub guarantee_type: Option<PriceGuaranteeType>,
35
36    /// Start of validity period (Zeitliche Gültigkeit - Von)
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub valid_from: Option<DateTime<Utc>>,
39
40    /// End of validity period (Zeitliche Gültigkeit - Bis)
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub valid_until: Option<DateTime<Utc>>,
43
44    /// Description of the guarantee (Beschreibung)
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub description: Option<String>,
47}
48
49impl Bo4eObject for PriceGuarantee {
50    fn type_name_german() -> &'static str {
51        "Preisgarantie"
52    }
53
54    fn type_name_english() -> &'static str {
55        "PriceGuarantee"
56    }
57
58    fn meta(&self) -> &Bo4eMeta {
59        &self.meta
60    }
61
62    fn meta_mut(&mut self) -> &mut Bo4eMeta {
63        &mut self.meta
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn test_complete_price_guarantee() {
73        let guarantee = PriceGuarantee {
74            guarantee_type: Some(PriceGuaranteeType::AllComponentsGross),
75            description: Some("Full price guarantee for 12 months".to_string()),
76            ..Default::default()
77        };
78
79        assert_eq!(
80            guarantee.guarantee_type,
81            Some(PriceGuaranteeType::AllComponentsGross)
82        );
83    }
84
85    #[test]
86    fn test_energy_price_guarantee() {
87        let guarantee = PriceGuarantee {
88            guarantee_type: Some(PriceGuaranteeType::EnergyPriceOnly),
89            description: Some("Energy price guaranteed".to_string()),
90            ..Default::default()
91        };
92
93        assert_eq!(
94            guarantee.guarantee_type,
95            Some(PriceGuaranteeType::EnergyPriceOnly)
96        );
97    }
98
99    #[test]
100    fn test_default() {
101        let guarantee = PriceGuarantee::default();
102        assert!(guarantee.guarantee_type.is_none());
103        assert!(guarantee.valid_from.is_none());
104        assert!(guarantee.valid_until.is_none());
105        assert!(guarantee.description.is_none());
106    }
107
108    #[test]
109    fn test_serialize() {
110        let guarantee = PriceGuarantee {
111            guarantee_type: Some(PriceGuaranteeType::AllComponentsGross),
112            description: Some("Test guarantee".to_string()),
113            ..Default::default()
114        };
115
116        let json = serde_json::to_string(&guarantee).unwrap();
117        assert!(json.contains(r#""guaranteeType":"ALLE_PREISBESTANDTEILE_BRUTTO""#));
118        assert!(json.contains(r#""description":"Test guarantee""#));
119    }
120
121    #[test]
122    fn test_roundtrip() {
123        let guarantee = PriceGuarantee {
124            guarantee_type: Some(PriceGuaranteeType::EnergyPriceOnly),
125            description: Some("Energy price fixed".to_string()),
126            valid_from: Some(
127                DateTime::parse_from_rfc3339("2024-01-01T00:00:00Z")
128                    .unwrap()
129                    .into(),
130            ),
131            valid_until: Some(
132                DateTime::parse_from_rfc3339("2024-12-31T23:59:59Z")
133                    .unwrap()
134                    .into(),
135            ),
136            ..Default::default()
137        };
138
139        let json = serde_json::to_string(&guarantee).unwrap();
140        let parsed: PriceGuarantee = serde_json::from_str(&json).unwrap();
141        assert_eq!(guarantee, parsed);
142    }
143
144    #[test]
145    fn test_bo4e_object_impl() {
146        assert_eq!(PriceGuarantee::type_name_german(), "Preisgarantie");
147        assert_eq!(PriceGuarantee::type_name_english(), "PriceGuarantee");
148    }
149}