Skip to main content

bo4e_core/bo/
network_location.rs

1//! Network location (Netzlokation) business object.
2//!
3//! Represents a location in the electricity or gas network.
4
5use serde::{Deserialize, Serialize};
6
7use crate::com::Address;
8use crate::enums::{Division, NetworkLevel};
9use crate::traits::{Bo4eMeta, Bo4eObject};
10
11/// A network location - a point in the electricity or gas network.
12///
13/// German: Netzlokation
14///
15/// A network location represents a physical point in the network
16/// infrastructure where energy flows.
17///
18/// # Example
19///
20/// ```rust
21/// use bo4e_core::bo::NetworkLocation;
22/// use bo4e_core::enums::Division;
23///
24/// let nelo = NetworkLocation {
25///     network_location_id: Some("NELO12345".to_string()),
26///     division: Some(Division::Electricity),
27///     ..Default::default()
28/// };
29/// ```
30#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
31#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
32#[cfg_attr(feature = "json-schema", schemars(rename = "Netzlokation"))]
33#[serde(rename_all = "camelCase")]
34pub struct NetworkLocation {
35    /// BO4E metadata
36    #[serde(flatten)]
37    pub meta: Bo4eMeta,
38
39    /// Network location ID (Netzlokations-ID)
40    #[serde(skip_serializing_if = "Option::is_none")]
41    #[cfg_attr(feature = "json-schema", schemars(rename = "netzlokationsId"))]
42    pub network_location_id: Option<String>,
43
44    /// Energy division (Sparte)
45    #[serde(skip_serializing_if = "Option::is_none")]
46    #[cfg_attr(feature = "json-schema", schemars(rename = "sparte"))]
47    pub division: Option<Division>,
48
49    /// Network level (Netzebene)
50    #[serde(skip_serializing_if = "Option::is_none")]
51    #[cfg_attr(feature = "json-schema", schemars(rename = "netzebene"))]
52    pub network_level: Option<NetworkLevel>,
53
54    /// Location address (Adresse)
55    #[serde(skip_serializing_if = "Option::is_none")]
56    #[cfg_attr(feature = "json-schema", schemars(rename = "adresse"))]
57    pub address: Option<Address>,
58
59    /// Network operator code (Netzbetreiber-Codenummer)
60    #[serde(skip_serializing_if = "Option::is_none")]
61    #[cfg_attr(feature = "json-schema", schemars(rename = "netzbetreiberCodenummer"))]
62    pub network_operator_code: Option<String>,
63
64    /// Description (Beschreibung)
65    #[serde(skip_serializing_if = "Option::is_none")]
66    #[cfg_attr(feature = "json-schema", schemars(rename = "beschreibung"))]
67    pub description: Option<String>,
68
69    /// Associated metering location IDs
70    #[serde(default, skip_serializing_if = "Vec::is_empty")]
71    #[cfg_attr(feature = "json-schema", schemars(rename = "messlokationsIds"))]
72    pub metering_location_ids: Vec<String>,
73
74    /// Associated technical resource IDs
75    #[serde(default, skip_serializing_if = "Vec::is_empty")]
76    #[cfg_attr(feature = "json-schema", schemars(rename = "technischeRessourceIds"))]
77    pub technical_resource_ids: Vec<String>,
78}
79
80impl Bo4eObject for NetworkLocation {
81    fn type_name_german() -> &'static str {
82        "Netzlokation"
83    }
84
85    fn type_name_english() -> &'static str {
86        "NetworkLocation"
87    }
88
89    fn meta(&self) -> &Bo4eMeta {
90        &self.meta
91    }
92
93    fn meta_mut(&mut self) -> &mut Bo4eMeta {
94        &mut self.meta
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    use super::*;
101
102    #[test]
103    fn test_network_location_creation() {
104        let nelo = NetworkLocation {
105            network_location_id: Some("NELO12345".to_string()),
106            division: Some(Division::Electricity),
107            ..Default::default()
108        };
109
110        assert_eq!(nelo.network_location_id, Some("NELO12345".to_string()));
111    }
112
113    #[test]
114    fn test_serialize() {
115        let nelo = NetworkLocation {
116            meta: Bo4eMeta::with_type("Netzlokation"),
117            network_location_id: Some("NELO12345".to_string()),
118            ..Default::default()
119        };
120
121        let json = serde_json::to_string(&nelo).unwrap();
122        assert!(json.contains(r#""_typ":"Netzlokation""#));
123    }
124
125    #[test]
126    fn test_roundtrip() {
127        let nelo = NetworkLocation {
128            meta: Bo4eMeta::with_type("Netzlokation"),
129            network_location_id: Some("NELO12345".to_string()),
130            division: Some(Division::Electricity),
131            network_level: Some(NetworkLevel::LowVoltage),
132            ..Default::default()
133        };
134
135        let json = serde_json::to_string(&nelo).unwrap();
136        let parsed: NetworkLocation = serde_json::from_str(&json).unwrap();
137        assert_eq!(nelo, parsed);
138    }
139
140    #[test]
141    fn test_bo4e_object_impl() {
142        assert_eq!(NetworkLocation::type_name_german(), "Netzlokation");
143        assert_eq!(NetworkLocation::type_name_english(), "NetworkLocation");
144    }
145}