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#[serde(rename_all = "camelCase")]
25pub struct RegionalPriceTier {
26    /// BO4E metadata
27    #[serde(flatten)]
28    pub meta: Bo4eMeta,
29
30    /// Region code (postal code, network area, etc.) (Regionscode)
31    #[serde(skip_serializing_if = "Option::is_none")]
32    pub region_code: Option<String>,
33
34    /// Price tiers for this region (Preisstaffeln)
35    #[serde(default, skip_serializing_if = "Vec::is_empty")]
36    pub tiers: Vec<PriceTier>,
37}
38
39impl Bo4eObject for RegionalPriceTier {
40    fn type_name_german() -> &'static str {
41        "RegionalePreisstaffel"
42    }
43
44    fn type_name_english() -> &'static str {
45        "RegionalPriceTier"
46    }
47
48    fn meta(&self) -> &Bo4eMeta {
49        &self.meta
50    }
51
52    fn meta_mut(&mut self) -> &mut Bo4eMeta {
53        &mut self.meta
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn test_regional_tier() {
63        let tier = RegionalPriceTier {
64            region_code: Some("50667".to_string()),
65            tiers: vec![PriceTier {
66                lower_limit: Some(0.0),
67                upper_limit: Some(1000.0),
68                unit_price: Some(0.28),
69                ..Default::default()
70            }],
71            ..Default::default()
72        };
73
74        assert_eq!(tier.region_code, Some("50667".to_string()));
75        assert_eq!(tier.tiers.len(), 1);
76    }
77
78    #[test]
79    fn test_default() {
80        let tier = RegionalPriceTier::default();
81        assert!(tier.region_code.is_none());
82        assert!(tier.tiers.is_empty());
83    }
84
85    #[test]
86    fn test_roundtrip() {
87        let tier = RegionalPriceTier {
88            region_code: Some("NRW-001".to_string()),
89            tiers: vec![PriceTier {
90                unit_price: Some(0.30),
91                tier_number: Some(1),
92                ..Default::default()
93            }],
94            ..Default::default()
95        };
96
97        let json = serde_json::to_string(&tier).unwrap();
98        let parsed: RegionalPriceTier = serde_json::from_str(&json).unwrap();
99        assert_eq!(tier, parsed);
100    }
101
102    #[test]
103    fn test_bo4e_object_impl() {
104        assert_eq!(
105            RegionalPriceTier::type_name_german(),
106            "RegionalePreisstaffel"
107        );
108        assert_eq!(RegionalPriceTier::type_name_english(), "RegionalPriceTier");
109    }
110}