bo4e_core/com/
external_cost_position.rs1use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5
6use crate::enums::Unit;
7use crate::traits::{Bo4eMeta, Bo4eObject};
8
9use super::{Amount, Price};
10
11#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
27#[serde(rename_all = "camelCase")]
28pub struct ExternalCostPosition {
29 #[serde(flatten)]
31 pub meta: Bo4eMeta,
32
33 #[serde(skip_serializing_if = "Option::is_none")]
35 pub title: Option<String>,
36
37 #[serde(skip_serializing_if = "Option::is_none")]
39 pub amount: Option<Amount>,
40
41 #[serde(skip_serializing_if = "Option::is_none")]
43 pub article_description: Option<String>,
44
45 #[serde(skip_serializing_if = "Option::is_none")]
47 pub unit_price: Option<Price>,
48
49 #[serde(skip_serializing_if = "Option::is_none")]
51 pub start_date: Option<DateTime<Utc>>,
52
53 #[serde(skip_serializing_if = "Option::is_none")]
55 pub end_date: Option<DateTime<Utc>>,
56
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub quantity_value: Option<f64>,
60
61 #[serde(skip_serializing_if = "Option::is_none")]
63 pub quantity_unit: Option<Unit>,
64
65 #[serde(skip_serializing_if = "Option::is_none")]
67 pub external_reference: Option<String>,
68}
69
70impl Bo4eObject for ExternalCostPosition {
71 fn type_name_german() -> &'static str {
72 "Fremdkostenposition"
73 }
74
75 fn type_name_english() -> &'static str {
76 "ExternalCostPosition"
77 }
78
79 fn meta(&self) -> &Bo4eMeta {
80 &self.meta
81 }
82
83 fn meta_mut(&mut self) -> &mut Bo4eMeta {
84 &mut self.meta
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_external_cost_position() {
94 let position = ExternalCostPosition {
95 title: Some("Netzbetreiber ABC".to_string()),
96 article_description: Some("Netznutzungsentgelt".to_string()),
97 amount: Some(Amount::eur(120.0)),
98 quantity_value: Some(1500.0),
99 quantity_unit: Some(Unit::KilowattHour),
100 ..Default::default()
101 };
102
103 assert_eq!(position.title, Some("Netzbetreiber ABC".to_string()));
104 assert_eq!(position.quantity_value, Some(1500.0));
105 }
106
107 #[test]
108 fn test_default() {
109 let position = ExternalCostPosition::default();
110 assert!(position.title.is_none());
111 assert!(position.amount.is_none());
112 }
113
114 #[test]
115 fn test_roundtrip() {
116 let position = ExternalCostPosition {
117 title: Some("Messstellenbetreiber".to_string()),
118 amount: Some(Amount::eur(80.0)),
119 external_reference: Some("MSB-2024-001".to_string()),
120 ..Default::default()
121 };
122
123 let json = serde_json::to_string(&position).unwrap();
124 let parsed: ExternalCostPosition = serde_json::from_str(&json).unwrap();
125 assert_eq!(position, parsed);
126 }
127
128 #[test]
129 fn test_bo4e_object_impl() {
130 assert_eq!(
131 ExternalCostPosition::type_name_german(),
132 "Fremdkostenposition"
133 );
134 assert_eq!(
135 ExternalCostPosition::type_name_english(),
136 "ExternalCostPosition"
137 );
138 }
139}