Skip to main content

bo4e_core/com/
contract_conditions.rs

1//! Contract conditions (Vertragskonditionen) component.
2
3use serde::{Deserialize, Serialize};
4
5use crate::traits::{Bo4eMeta, Bo4eObject};
6
7/// Contract conditions for contracts and tariffs.
8///
9/// German: Vertragskonditionen
10///
11/// # Example
12///
13/// ```rust
14/// use bo4e_core::com::ContractConditions;
15///
16/// let conditions = ContractConditions {
17///     description: Some("Standard conditions for gas supply".to_string()),
18///     installment_count: Some(12),
19///     ..Default::default()
20/// };
21/// ```
22#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
23#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
24#[cfg_attr(feature = "json-schema", schemars(rename = "Vertragskonditionen"))]
25#[serde(rename_all = "camelCase")]
26pub struct ContractConditions {
27    /// BO4E metadata
28    #[serde(flatten)]
29    pub meta: Bo4eMeta,
30
31    /// Free text description of conditions (Beschreibung)
32    #[serde(skip_serializing_if = "Option::is_none")]
33    #[cfg_attr(feature = "json-schema", schemars(rename = "beschreibung"))]
34    pub description: Option<String>,
35
36    /// Number of agreed installments per year, e.g., 12 (AnzahlAbschlaege)
37    #[serde(skip_serializing_if = "Option::is_none")]
38    #[cfg_attr(feature = "json-schema", schemars(rename = "anzahlAbschlaege"))]
39    pub installment_count: Option<i32>,
40
41    // Note: The following fields would typically reference Zeitraum COM type.
42    // Using simplified string representations for now.
43    /// Contract duration (Vertragslaufzeit) - ISO 8601 duration or description
44    #[serde(skip_serializing_if = "Option::is_none")]
45    #[cfg_attr(feature = "json-schema", schemars(rename = "vertragslaufzeit"))]
46    pub contract_duration: Option<String>,
47
48    /// Notice period for termination (Kündigungsfrist)
49    #[serde(skip_serializing_if = "Option::is_none")]
50    #[cfg_attr(feature = "json-schema", schemars(rename = "kuendigungsfrist"))]
51    pub notice_period: Option<String>,
52
53    /// Automatic extension period if not terminated (Vertragsverlängerung)
54    #[serde(skip_serializing_if = "Option::is_none")]
55    #[cfg_attr(feature = "json-schema", schemars(rename = "vertragsverlaengerung"))]
56    pub extension_period: Option<String>,
57
58    /// Installment cycle (Abschlagszyklus)
59    #[serde(skip_serializing_if = "Option::is_none")]
60    #[cfg_attr(feature = "json-schema", schemars(rename = "abschlagszyklus"))]
61    pub installment_cycle: Option<String>,
62}
63
64impl Bo4eObject for ContractConditions {
65    fn type_name_german() -> &'static str {
66        "Vertragskonditionen"
67    }
68
69    fn type_name_english() -> &'static str {
70        "ContractConditions"
71    }
72
73    fn meta(&self) -> &Bo4eMeta {
74        &self.meta
75    }
76
77    fn meta_mut(&mut self) -> &mut Bo4eMeta {
78        &mut self.meta
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    fn test_contract_conditions_default() {
88        let conditions = ContractConditions::default();
89        assert!(conditions.description.is_none());
90        assert!(conditions.installment_count.is_none());
91    }
92
93    #[test]
94    fn test_contract_conditions_serialize() {
95        let conditions = ContractConditions {
96            description: Some("Standard electricity conditions".to_string()),
97            installment_count: Some(12),
98            contract_duration: Some("P12M".to_string()),
99            notice_period: Some("P6W".to_string()),
100            ..Default::default()
101        };
102
103        let json = serde_json::to_string(&conditions).unwrap();
104        assert!(json.contains(r#""description":"Standard electricity conditions""#));
105        assert!(json.contains(r#""installmentCount":12"#));
106        assert!(json.contains(r#""contractDuration":"P12M""#));
107    }
108
109    #[test]
110    fn test_contract_conditions_roundtrip() {
111        let conditions = ContractConditions {
112            meta: Bo4eMeta::with_type("Vertragskonditionen"),
113            description: Some("Premium gas tariff conditions".to_string()),
114            installment_count: Some(6),
115            contract_duration: Some("P24M".to_string()),
116            notice_period: Some("P3M".to_string()),
117            extension_period: Some("P12M".to_string()),
118            installment_cycle: Some("P2M".to_string()),
119        };
120
121        let json = serde_json::to_string(&conditions).unwrap();
122        let parsed: ContractConditions = serde_json::from_str(&json).unwrap();
123        assert_eq!(conditions, parsed);
124    }
125
126    #[test]
127    fn test_bo4e_object_impl() {
128        assert_eq!(
129            ContractConditions::type_name_german(),
130            "Vertragskonditionen"
131        );
132        assert_eq!(
133            ContractConditions::type_name_english(),
134            "ContractConditions"
135        );
136    }
137}