koprogo_api/domain/entities/
owner.rs1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
7pub struct Owner {
8 pub id: Uuid,
9 pub organization_id: Uuid,
10 pub user_id: Option<Uuid>, pub first_name: String,
12 pub last_name: String,
13 pub email: String,
14 pub phone: Option<String>,
15 pub address: String,
16 pub city: String,
17 pub postal_code: String,
18 pub country: String,
19 pub created_at: DateTime<Utc>,
20 pub updated_at: DateTime<Utc>,
21}
22
23impl Owner {
24 #[allow(clippy::too_many_arguments)]
25 pub fn new(
26 organization_id: Uuid,
27 first_name: String,
28 last_name: String,
29 email: String,
30 phone: Option<String>,
31 address: String,
32 city: String,
33 postal_code: String,
34 country: String,
35 ) -> Result<Self, String> {
36 if first_name.is_empty() {
37 return Err("First name cannot be empty".to_string());
38 }
39 if last_name.is_empty() {
40 return Err("Last name cannot be empty".to_string());
41 }
42 if !Self::is_valid_email(&email) {
43 return Err("Invalid email format".to_string());
44 }
45
46 let now = Utc::now();
47 Ok(Self {
48 id: Uuid::new_v4(),
49 organization_id,
50 user_id: None, first_name,
52 last_name,
53 email,
54 phone,
55 address,
56 city,
57 postal_code,
58 country,
59 created_at: now,
60 updated_at: now,
61 })
62 }
63
64 fn is_valid_email(email: &str) -> bool {
65 email.contains('@') && email.contains('.')
66 }
67
68 pub fn full_name(&self) -> String {
69 format!("{} {}", self.first_name, self.last_name)
70 }
71
72 pub fn update_contact(&mut self, email: String, phone: Option<String>) -> Result<(), String> {
73 if !Self::is_valid_email(&email) {
74 return Err("Invalid email format".to_string());
75 }
76 self.email = email;
77 self.phone = phone;
78 self.updated_at = Utc::now();
79 Ok(())
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn test_create_owner_success() {
89 let org_id = Uuid::new_v4();
90 let owner = Owner::new(
91 org_id,
92 "Jean".to_string(),
93 "Dupont".to_string(),
94 "jean.dupont@example.com".to_string(),
95 Some("+33612345678".to_string()),
96 "123 Rue de la Paix".to_string(),
97 "Paris".to_string(),
98 "75001".to_string(),
99 "France".to_string(),
100 );
101
102 assert!(owner.is_ok());
103 let owner = owner.unwrap();
104 assert_eq!(owner.organization_id, org_id);
105 assert_eq!(owner.full_name(), "Jean Dupont");
106 }
107
108 #[test]
109 fn test_create_owner_invalid_email_fails() {
110 let org_id = Uuid::new_v4();
111 let owner = Owner::new(
112 org_id,
113 "Jean".to_string(),
114 "Dupont".to_string(),
115 "invalid-email".to_string(),
116 None,
117 "123 Rue de la Paix".to_string(),
118 "Paris".to_string(),
119 "75001".to_string(),
120 "France".to_string(),
121 );
122
123 assert!(owner.is_err());
124 assert_eq!(owner.unwrap_err(), "Invalid email format");
125 }
126
127 #[test]
128 fn test_update_contact() {
129 let org_id = Uuid::new_v4();
130 let mut owner = Owner::new(
131 org_id,
132 "Jean".to_string(),
133 "Dupont".to_string(),
134 "jean.dupont@example.com".to_string(),
135 None,
136 "123 Rue de la Paix".to_string(),
137 "Paris".to_string(),
138 "75001".to_string(),
139 "France".to_string(),
140 )
141 .unwrap();
142
143 let result = owner.update_contact(
144 "new.email@example.com".to_string(),
145 Some("+33699999999".to_string()),
146 );
147
148 assert!(result.is_ok());
149 assert_eq!(owner.email, "new.email@example.com");
150 }
151}