Skip to main content

bo4e_core/com/
external_reference.rs

1//! External reference (ExterneReferenz) component.
2
3use serde::{Deserialize, Serialize};
4
5use crate::traits::{Bo4eMeta, Bo4eObject};
6
7/// Reference to an external system.
8///
9/// Used to link BO4E objects to identifiers in other systems (e.g., SAP, CRM).
10///
11/// German: ExterneReferenz
12///
13/// # Example
14///
15/// ```rust
16/// use bo4e_core::com::ExternalReference;
17///
18/// let ext_ref = ExternalReference::new("SAP", "4711");
19/// assert_eq!(ext_ref.external_ref_name, Some("SAP".to_string()));
20/// assert_eq!(ext_ref.external_ref_value, Some("4711".to_string()));
21/// ```
22#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
23#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
24#[cfg_attr(feature = "json-schema", schemars(rename = "ExterneReferenz"))]
25#[serde(rename_all = "camelCase")]
26pub struct ExternalReference {
27    /// BO4E metadata
28    #[serde(flatten)]
29    pub meta: Bo4eMeta,
30
31    /// Name of the external system (ExRefName)
32    #[serde(skip_serializing_if = "Option::is_none")]
33    #[cfg_attr(feature = "json-schema", schemars(rename = "exRefName"))]
34    pub external_ref_name: Option<String>,
35
36    /// Value/ID in the external system (ExRefWert)
37    #[serde(skip_serializing_if = "Option::is_none")]
38    #[cfg_attr(feature = "json-schema", schemars(rename = "exRefWert"))]
39    pub external_ref_value: Option<String>,
40}
41
42impl Bo4eObject for ExternalReference {
43    fn type_name_german() -> &'static str {
44        "ExterneReferenz"
45    }
46
47    fn type_name_english() -> &'static str {
48        "ExternalReference"
49    }
50
51    fn meta(&self) -> &Bo4eMeta {
52        &self.meta
53    }
54
55    fn meta_mut(&mut self) -> &mut Bo4eMeta {
56        &mut self.meta
57    }
58}
59
60impl ExternalReference {
61    /// Create a new external reference.
62    ///
63    /// # Arguments
64    ///
65    /// * `system` - Name of the external system
66    /// * `value` - The identifier/value in that system
67    pub fn new(system: impl Into<String>, value: impl Into<String>) -> Self {
68        Self {
69            external_ref_name: Some(system.into()),
70            external_ref_value: Some(value.into()),
71            ..Default::default()
72        }
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79
80    #[test]
81    fn test_external_reference_default() {
82        let ext_ref = ExternalReference::default();
83        assert!(ext_ref.external_ref_name.is_none());
84        assert!(ext_ref.external_ref_value.is_none());
85    }
86
87    #[test]
88    fn test_sap_reference() {
89        let ext_ref = ExternalReference::new("SAP", "4711");
90        assert_eq!(ext_ref.external_ref_name, Some("SAP".to_string()));
91        assert_eq!(ext_ref.external_ref_value, Some("4711".to_string()));
92    }
93
94    #[test]
95    fn test_serialize() {
96        let ext_ref = ExternalReference::new("CRM", "CUST-12345");
97        let json = serde_json::to_string(&ext_ref).unwrap();
98        assert!(json.contains(r#""externalRefName":"CRM""#));
99        assert!(json.contains(r#""externalRefValue":"CUST-12345""#));
100    }
101
102    #[test]
103    fn test_external_reference_roundtrip() {
104        let ext_ref = ExternalReference {
105            meta: Bo4eMeta::with_type("ExterneReferenz"),
106            external_ref_name: Some("ERP".to_string()),
107            external_ref_value: Some("ORDER-2024-001".to_string()),
108        };
109
110        let json = serde_json::to_string(&ext_ref).unwrap();
111        let parsed: ExternalReference = serde_json::from_str(&json).unwrap();
112        assert_eq!(ext_ref, parsed);
113    }
114
115    #[test]
116    fn test_bo4e_object_impl() {
117        assert_eq!(ExternalReference::type_name_german(), "ExterneReferenz");
118        assert_eq!(ExternalReference::type_name_english(), "ExternalReference");
119    }
120}