Skip to main content

bo4e_core/com/
contact_method.rs

1//! Contact method (Kontaktweg) component.
2
3use serde::{Deserialize, Serialize};
4
5use crate::enums::ContactType;
6use crate::traits::{Bo4eMeta, Bo4eObject};
7
8/// Method of contact (email, phone, etc.).
9///
10/// Used to represent contact information for a person within business objects.
11///
12/// German: Kontaktweg
13///
14/// # Example
15///
16/// ```rust
17/// use bo4e_core::com::ContactMethod;
18/// use bo4e_core::enums::ContactType;
19///
20/// let contact = ContactMethod {
21///     contact_type: Some(ContactType::Email),
22///     contact_value: Some("info@example.com".to_string()),
23///     is_preferred: Some(true),
24///     ..Default::default()
25/// };
26/// ```
27#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
28#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
29#[cfg_attr(feature = "json-schema", schemars(rename = "Kontaktweg"))]
30#[serde(rename_all = "camelCase")]
31pub struct ContactMethod {
32    /// BO4E metadata
33    #[serde(flatten)]
34    pub meta: Bo4eMeta,
35
36    /// Type of contact (Kontaktart)
37    #[serde(skip_serializing_if = "Option::is_none")]
38    #[cfg_attr(feature = "json-schema", schemars(rename = "kontaktart"))]
39    pub contact_type: Option<ContactType>,
40
41    /// Contact value - phone number, email address, etc. (Kontaktwert)
42    #[serde(skip_serializing_if = "Option::is_none")]
43    #[cfg_attr(feature = "json-schema", schemars(rename = "kontaktwert"))]
44    pub contact_value: Option<String>,
45
46    /// Description/specification, e.g., "direct line", "switchboard" (Beschreibung)
47    #[serde(skip_serializing_if = "Option::is_none")]
48    #[cfg_attr(feature = "json-schema", schemars(rename = "beschreibung"))]
49    pub description: Option<String>,
50
51    /// Whether this is the preferred contact method (IstBevorzugterKontaktweg)
52    #[serde(skip_serializing_if = "Option::is_none")]
53    #[cfg_attr(feature = "json-schema", schemars(rename = "istBevorzugterKontaktweg"))]
54    pub is_preferred: Option<bool>,
55}
56
57impl Bo4eObject for ContactMethod {
58    fn type_name_german() -> &'static str {
59        "Kontaktweg"
60    }
61
62    fn type_name_english() -> &'static str {
63        "ContactMethod"
64    }
65
66    fn meta(&self) -> &Bo4eMeta {
67        &self.meta
68    }
69
70    fn meta_mut(&mut self) -> &mut Bo4eMeta {
71        &mut self.meta
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    #[test]
80    fn test_contact_method_default() {
81        let contact = ContactMethod::default();
82        assert!(contact.contact_type.is_none());
83        assert!(contact.contact_value.is_none());
84        assert!(contact.is_preferred.is_none());
85    }
86
87    #[test]
88    fn test_email_contact() {
89        let contact = ContactMethod {
90            contact_type: Some(ContactType::Email),
91            contact_value: Some("test@example.com".to_string()),
92            is_preferred: Some(true),
93            ..Default::default()
94        };
95
96        let json = serde_json::to_string(&contact).unwrap();
97        assert!(json.contains(r#""contactType":"E_MAIL""#));
98        assert!(json.contains(r#""contactValue":"test@example.com""#));
99        assert!(json.contains(r#""isPreferred":true"#));
100
101        let parsed: ContactMethod = serde_json::from_str(&json).unwrap();
102        assert_eq!(contact, parsed);
103    }
104
105    #[test]
106    fn test_phone_contact() {
107        let contact = ContactMethod {
108            contact_type: Some(ContactType::Phone),
109            contact_value: Some("+49 221 1234567".to_string()),
110            description: Some("Direct line".to_string()),
111            ..Default::default()
112        };
113
114        let json = serde_json::to_string(&contact).unwrap();
115        assert!(json.contains(r#""contactType":"TELEFON""#));
116        assert!(json.contains(r#""description":"Direct line""#));
117
118        let parsed: ContactMethod = serde_json::from_str(&json).unwrap();
119        assert_eq!(contact, parsed);
120    }
121
122    #[test]
123    fn test_contact_method_roundtrip() {
124        let contact = ContactMethod {
125            meta: Bo4eMeta::with_type("Kontaktweg"),
126            contact_type: Some(ContactType::Fax),
127            contact_value: Some("+49 221 1234568".to_string()),
128            description: Some("Fax number".to_string()),
129            is_preferred: Some(false),
130        };
131
132        let json = serde_json::to_string(&contact).unwrap();
133        let parsed: ContactMethod = serde_json::from_str(&json).unwrap();
134        assert_eq!(contact, parsed);
135    }
136
137    #[test]
138    fn test_bo4e_object_impl() {
139        assert_eq!(ContactMethod::type_name_german(), "Kontaktweg");
140        assert_eq!(ContactMethod::type_name_english(), "ContactMethod");
141    }
142}