Skip to main content

bo4e_core/com/
regional_price_tier.rs

1//! Regional price tier (RegionalePreisstaffel) component.
2
3use serde::{Deserialize, Serialize};
4
5use crate::traits::{Bo4eMeta, Bo4eObject};
6
7use super::PriceTier;
8
9/// A price tier that applies to a specific region.
10///
11/// German: RegionalePreisstaffel
12///
13/// # Example
14///
15/// ```rust
16/// use bo4e_core::com::{RegionalPriceTier, PriceTier};
17///
18/// let regional_tier = RegionalPriceTier {
19///     region_code: Some("50667".to_string()),
20///     ..Default::default()
21/// };
22/// ```
23#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
24#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
25#[cfg_attr(feature = "json-schema", schemars(rename = "RegionalePreisstaffel"))]
26#[serde(rename_all = "camelCase")]
27pub struct RegionalPriceTier {
28    /// BO4E metadata
29    #[serde(flatten)]
30    pub meta: Bo4eMeta,
31
32    /// Region code (postal code, network area, etc.) (Regionscode)
33    #[serde(skip_serializing_if = "Option::is_none")]
34    #[cfg_attr(feature = "json-schema", schemars(rename = "regionscode"))]
35    pub region_code: Option<String>,
36
37    /// Price tiers for this region (Preisstaffeln)
38    #[serde(default, skip_serializing_if = "Vec::is_empty")]
39    #[cfg_attr(feature = "json-schema", schemars(rename = "preisstaffeln"))]
40    pub tiers: Vec<PriceTier>,
41}
42
43impl Bo4eObject for RegionalPriceTier {
44    fn type_name_german() -> &'static str {
45        "RegionalePreisstaffel"
46    }
47
48    fn type_name_english() -> &'static str {
49        "RegionalPriceTier"
50    }
51
52    fn meta(&self) -> &Bo4eMeta {
53        &self.meta
54    }
55
56    fn meta_mut(&mut self) -> &mut Bo4eMeta {
57        &mut self.meta
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn test_regional_tier() {
67        let tier = RegionalPriceTier {
68            region_code: Some("50667".to_string()),
69            tiers: vec![PriceTier {
70                lower_limit: Some(0.0),
71                upper_limit: Some(1000.0),
72                unit_price: Some(0.28),
73                ..Default::default()
74            }],
75            ..Default::default()
76        };
77
78        assert_eq!(tier.region_code, Some("50667".to_string()));
79        assert_eq!(tier.tiers.len(), 1);
80    }
81
82    #[test]
83    fn test_default() {
84        let tier = RegionalPriceTier::default();
85        assert!(tier.region_code.is_none());
86        assert!(tier.tiers.is_empty());
87    }
88
89    #[test]
90    fn test_roundtrip() {
91        let tier = RegionalPriceTier {
92            region_code: Some("NRW-001".to_string()),
93            tiers: vec![PriceTier {
94                unit_price: Some(0.30),
95                tier_number: Some(1),
96                ..Default::default()
97            }],
98            ..Default::default()
99        };
100
101        let json = serde_json::to_string(&tier).unwrap();
102        let parsed: RegionalPriceTier = serde_json::from_str(&json).unwrap();
103        assert_eq!(tier, parsed);
104    }
105
106    #[test]
107    fn test_bo4e_object_impl() {
108        assert_eq!(
109            RegionalPriceTier::type_name_german(),
110            "RegionalePreisstaffel"
111        );
112        assert_eq!(RegionalPriceTier::type_name_english(), "RegionalPriceTier");
113    }
114}