bo4e_core/com/
tariff_price_position.rs1use serde::{Deserialize, Serialize};
4
5use crate::enums::{CalculationMethod, PriceType, Unit};
6use crate::traits::{Bo4eMeta, Bo4eObject};
7
8use super::TariffPrice;
9
10#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
27#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
28#[cfg_attr(feature = "json-schema", schemars(rename = "Tarifpreisposition"))]
29#[serde(rename_all = "camelCase")]
30pub struct TariffPricePosition {
31 #[serde(flatten)]
33 pub meta: Bo4eMeta,
34
35 #[serde(skip_serializing_if = "Option::is_none")]
37 #[cfg_attr(feature = "json-schema", schemars(rename = "bezeichnung"))]
38 pub description: Option<String>,
39
40 #[serde(skip_serializing_if = "Option::is_none")]
42 #[cfg_attr(feature = "json-schema", schemars(rename = "preistyp"))]
43 pub price_type: Option<PriceType>,
44
45 #[serde(skip_serializing_if = "Option::is_none")]
47 #[cfg_attr(feature = "json-schema", schemars(rename = "bezugseinheit"))]
48 pub reference_unit: Option<Unit>,
49
50 #[serde(skip_serializing_if = "Option::is_none")]
52 #[cfg_attr(feature = "json-schema", schemars(rename = "berechnungsmethode"))]
53 pub calculation_method: Option<CalculationMethod>,
54
55 #[serde(default, skip_serializing_if = "Vec::is_empty")]
57 #[cfg_attr(feature = "json-schema", schemars(rename = "tarifpreise"))]
58 pub prices: Vec<TariffPrice>,
59
60 #[serde(skip_serializing_if = "Option::is_none")]
62 #[cfg_attr(feature = "json-schema", schemars(rename = "artikelId"))]
63 pub article_id: Option<String>,
64}
65
66impl Bo4eObject for TariffPricePosition {
67 fn type_name_german() -> &'static str {
68 "Tarifpreisposition"
69 }
70
71 fn type_name_english() -> &'static str {
72 "TariffPricePosition"
73 }
74
75 fn meta(&self) -> &Bo4eMeta {
76 &self.meta
77 }
78
79 fn meta_mut(&mut self) -> &mut Bo4eMeta {
80 &mut self.meta
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87 use crate::enums::Currency;
88
89 #[test]
90 fn test_tariff_price_position() {
91 let position = TariffPricePosition {
92 description: Some("Arbeitspreis HT/NT".to_string()),
93 price_type: Some(PriceType::WorkingPriceSingleTariff),
94 reference_unit: Some(Unit::KilowattHour),
95 prices: vec![
96 TariffPrice {
97 description: Some("HT".to_string()),
98 value: Some(30.5),
99 currency: Some(Currency::Eur),
100 ..Default::default()
101 },
102 TariffPrice {
103 description: Some("NT".to_string()),
104 value: Some(22.0),
105 currency: Some(Currency::Eur),
106 ..Default::default()
107 },
108 ],
109 ..Default::default()
110 };
111
112 assert_eq!(position.prices.len(), 2);
113 }
114
115 #[test]
116 fn test_default() {
117 let position = TariffPricePosition::default();
118 assert!(position.description.is_none());
119 assert!(position.prices.is_empty());
120 }
121
122 #[test]
123 fn test_roundtrip() {
124 let position = TariffPricePosition {
125 description: Some("Grundpreis".to_string()),
126 price_type: Some(PriceType::BasePrice),
127 article_id: Some("GP-001".to_string()),
128 ..Default::default()
129 };
130
131 let json = serde_json::to_string(&position).unwrap();
132 let parsed: TariffPricePosition = serde_json::from_str(&json).unwrap();
133 assert_eq!(position, parsed);
134 }
135
136 #[test]
137 fn test_bo4e_object_impl() {
138 assert_eq!(
139 TariffPricePosition::type_name_german(),
140 "Tarifpreisposition"
141 );
142 assert_eq!(
143 TariffPricePosition::type_name_english(),
144 "TariffPricePosition"
145 );
146 }
147}