1use chrono::NaiveDate;
4use serde::{Deserialize, Serialize};
5
6use crate::com::{Address, ContactMethod};
7use crate::enums::{Salutation, Title};
8use crate::traits::{Bo4eMeta, Bo4eObject};
9
10#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
28#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
29#[cfg_attr(feature = "json-schema", schemars(rename = "Person"))]
30#[serde(rename_all = "camelCase")]
31pub struct Person {
32 #[serde(flatten)]
34 pub meta: Bo4eMeta,
35
36 #[serde(skip_serializing_if = "Option::is_none")]
38 #[cfg_attr(feature = "json-schema", schemars(rename = "anrede"))]
39 pub salutation: Option<Salutation>,
40
41 #[serde(skip_serializing_if = "Option::is_none")]
43 #[cfg_attr(feature = "json-schema", schemars(rename = "titel"))]
44 pub title: Option<Title>,
45
46 #[serde(skip_serializing_if = "Option::is_none")]
48 #[cfg_attr(feature = "json-schema", schemars(rename = "vorname"))]
49 pub first_name: Option<String>,
50
51 #[serde(skip_serializing_if = "Option::is_none")]
53 #[cfg_attr(feature = "json-schema", schemars(rename = "nachname"))]
54 pub last_name: Option<String>,
55
56 #[serde(skip_serializing_if = "Option::is_none")]
58 #[cfg_attr(feature = "json-schema", schemars(rename = "namenszusatz"))]
59 pub name_suffix: Option<String>,
60
61 #[serde(skip_serializing_if = "Option::is_none")]
63 #[cfg_attr(feature = "json-schema", schemars(rename = "namenspraefix"))]
64 pub name_prefix: Option<String>,
65
66 #[serde(skip_serializing_if = "Option::is_none")]
68 #[cfg_attr(feature = "json-schema", schemars(rename = "firma"))]
69 pub company_name: Option<String>,
70
71 #[serde(skip_serializing_if = "Option::is_none")]
73 #[cfg_attr(feature = "json-schema", schemars(rename = "geburtsdatum"))]
74 pub birth_date: Option<NaiveDate>,
75
76 #[serde(skip_serializing_if = "Option::is_none")]
78 #[cfg_attr(feature = "json-schema", schemars(rename = "adresse"))]
79 pub address: Option<Address>,
80
81 #[serde(default, skip_serializing_if = "Vec::is_empty")]
83 #[cfg_attr(feature = "json-schema", schemars(rename = "kontaktwege"))]
84 pub contact_methods: Vec<ContactMethod>,
85}
86
87impl Bo4eObject for Person {
88 fn type_name_german() -> &'static str {
89 "Person"
90 }
91
92 fn type_name_english() -> &'static str {
93 "Person"
94 }
95
96 fn meta(&self) -> &Bo4eMeta {
97 &self.meta
98 }
99
100 fn meta_mut(&mut self) -> &mut Bo4eMeta {
101 &mut self.meta
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 #[test]
110 fn test_person_creation() {
111 let person = Person {
112 salutation: Some(Salutation::Mr),
113 first_name: Some("Max".to_string()),
114 last_name: Some("Mustermann".to_string()),
115 ..Default::default()
116 };
117
118 assert_eq!(person.first_name, Some("Max".to_string()));
119 assert_eq!(person.last_name, Some("Mustermann".to_string()));
120 }
121
122 #[test]
123 fn test_person_with_title() {
124 let person = Person {
125 salutation: Some(Salutation::Mr),
126 title: Some(Title::Dr),
127 first_name: Some("Hans".to_string()),
128 last_name: Some("Mueller".to_string()),
129 ..Default::default()
130 };
131
132 assert_eq!(person.title, Some(Title::Dr));
133 }
134
135 #[test]
136 fn test_serialize() {
137 let person = Person {
138 meta: Bo4eMeta::with_type("Person"),
139 salutation: Some(Salutation::Ms),
140 first_name: Some("Erika".to_string()),
141 last_name: Some("Musterfrau".to_string()),
142 ..Default::default()
143 };
144
145 let json = serde_json::to_string(&person).unwrap();
146 assert!(json.contains(r#""firstName":"Erika""#));
147 assert!(json.contains(r#""lastName":"Musterfrau""#));
148 }
149
150 #[test]
151 fn test_roundtrip() {
152 let person = Person {
153 meta: Bo4eMeta::with_type("Person"),
154 salutation: Some(Salutation::Mr),
155 title: Some(Title::ProfDr),
156 first_name: Some("Klaus".to_string()),
157 last_name: Some("Schmidt".to_string()),
158 name_suffix: Some("Jr.".to_string()),
159 company_name: Some("Schmidt GmbH".to_string()),
160 birth_date: Some(NaiveDate::from_ymd_opt(1970, 5, 15).unwrap()),
161 ..Default::default()
162 };
163
164 let json = serde_json::to_string(&person).unwrap();
165 let parsed: Person = serde_json::from_str(&json).unwrap();
166 assert_eq!(person, parsed);
167 }
168
169 #[test]
170 fn test_bo4e_object_impl() {
171 assert_eq!(Person::type_name_german(), "Person");
172 assert_eq!(Person::type_name_english(), "Person");
173 }
174}