refactoring hexagonal and clean architecture
This commit is contained in:
+294
-32
@@ -3,28 +3,79 @@ use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AddressBook {
|
||||
pub id: Uuid,
|
||||
pub name: String,
|
||||
pub owner_id: String,
|
||||
pub description: Option<String>,
|
||||
pub color: Option<String>,
|
||||
pub is_public: bool,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
id: Uuid,
|
||||
name: String,
|
||||
owner_id: String,
|
||||
description: Option<String>,
|
||||
color: Option<String>,
|
||||
is_public: bool,
|
||||
created_at: DateTime<Utc>,
|
||||
updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl AddressBook {
|
||||
/// Creates a new AddressBook with generated id and timestamps
|
||||
pub fn new(
|
||||
name: String,
|
||||
owner_id: String,
|
||||
description: Option<String>,
|
||||
color: Option<String>,
|
||||
is_public: bool,
|
||||
) -> Self {
|
||||
let now = Utc::now();
|
||||
Self {
|
||||
id: Uuid::new_v4(),
|
||||
name,
|
||||
owner_id,
|
||||
description,
|
||||
color,
|
||||
is_public,
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
}
|
||||
|
||||
/// Reconstructs from persistence (no validation)
|
||||
pub fn from_raw(
|
||||
id: Uuid,
|
||||
name: String,
|
||||
owner_id: String,
|
||||
description: Option<String>,
|
||||
color: Option<String>,
|
||||
is_public: bool,
|
||||
created_at: DateTime<Utc>,
|
||||
updated_at: DateTime<Utc>,
|
||||
) -> Self {
|
||||
Self { id, name, owner_id, description, color, is_public, created_at, updated_at }
|
||||
}
|
||||
|
||||
// --- Getters ---
|
||||
pub fn id(&self) -> &Uuid { &self.id }
|
||||
pub fn name(&self) -> &str { &self.name }
|
||||
pub fn owner_id(&self) -> &str { &self.owner_id }
|
||||
pub fn description(&self) -> Option<&str> { self.description.as_deref() }
|
||||
pub fn color(&self) -> Option<&str> { self.color.as_deref() }
|
||||
pub fn is_public(&self) -> bool { self.is_public }
|
||||
pub fn created_at(&self) -> &DateTime<Utc> { &self.created_at }
|
||||
pub fn updated_at(&self) -> &DateTime<Utc> { &self.updated_at }
|
||||
|
||||
// --- Setters for mutable operations ---
|
||||
pub fn set_name(&mut self, name: String) { self.name = name; self.updated_at = Utc::now(); }
|
||||
pub fn set_description(&mut self, description: Option<String>) { self.description = description; self.updated_at = Utc::now(); }
|
||||
pub fn set_color(&mut self, color: Option<String>) { self.color = color; self.updated_at = Utc::now(); }
|
||||
pub fn set_is_public(&mut self, is_public: bool) { self.is_public = is_public; self.updated_at = Utc::now(); }
|
||||
pub fn set_updated_at(&mut self, updated_at: DateTime<Utc>) { self.updated_at = updated_at; }
|
||||
}
|
||||
|
||||
impl Default for AddressBook {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
id: Uuid::new_v4(),
|
||||
name: "Default Address Book".to_string(),
|
||||
owner_id: "default".to_string(),
|
||||
description: None,
|
||||
color: None,
|
||||
is_public: false,
|
||||
created_at: Utc::now(),
|
||||
updated_at: Utc::now(),
|
||||
}
|
||||
Self::new(
|
||||
"Default Address Book".to_string(),
|
||||
"default".to_string(),
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +106,192 @@ pub struct Address {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Contact {
|
||||
id: Uuid,
|
||||
address_book_id: Uuid,
|
||||
uid: String,
|
||||
full_name: Option<String>,
|
||||
first_name: Option<String>,
|
||||
last_name: Option<String>,
|
||||
nickname: Option<String>,
|
||||
email: Vec<Email>,
|
||||
phone: Vec<Phone>,
|
||||
address: Vec<Address>,
|
||||
organization: Option<String>,
|
||||
title: Option<String>,
|
||||
notes: Option<String>,
|
||||
photo_url: Option<String>,
|
||||
birthday: Option<NaiveDate>,
|
||||
anniversary: Option<NaiveDate>,
|
||||
vcard: String,
|
||||
etag: String,
|
||||
created_at: DateTime<Utc>,
|
||||
updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl Contact {
|
||||
/// Creates a new Contact with generated id, uid, etag and timestamps
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
address_book_id: Uuid,
|
||||
full_name: Option<String>,
|
||||
first_name: Option<String>,
|
||||
last_name: Option<String>,
|
||||
nickname: Option<String>,
|
||||
email: Vec<Email>,
|
||||
phone: Vec<Phone>,
|
||||
address: Vec<Address>,
|
||||
organization: Option<String>,
|
||||
title: Option<String>,
|
||||
notes: Option<String>,
|
||||
photo_url: Option<String>,
|
||||
birthday: Option<NaiveDate>,
|
||||
anniversary: Option<NaiveDate>,
|
||||
vcard: String,
|
||||
) -> Self {
|
||||
let now = Utc::now();
|
||||
Self {
|
||||
id: Uuid::new_v4(),
|
||||
address_book_id,
|
||||
uid: format!("{}@oxicloud", Uuid::new_v4()),
|
||||
full_name,
|
||||
first_name,
|
||||
last_name,
|
||||
nickname,
|
||||
email,
|
||||
phone,
|
||||
address,
|
||||
organization,
|
||||
title,
|
||||
notes,
|
||||
photo_url,
|
||||
birthday,
|
||||
anniversary,
|
||||
vcard,
|
||||
etag: Uuid::new_v4().to_string(),
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
}
|
||||
|
||||
/// Reconstructs from persistence (no validation)
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn from_raw(
|
||||
id: Uuid,
|
||||
address_book_id: Uuid,
|
||||
uid: String,
|
||||
full_name: Option<String>,
|
||||
first_name: Option<String>,
|
||||
last_name: Option<String>,
|
||||
nickname: Option<String>,
|
||||
email: Vec<Email>,
|
||||
phone: Vec<Phone>,
|
||||
address: Vec<Address>,
|
||||
organization: Option<String>,
|
||||
title: Option<String>,
|
||||
notes: Option<String>,
|
||||
photo_url: Option<String>,
|
||||
birthday: Option<NaiveDate>,
|
||||
anniversary: Option<NaiveDate>,
|
||||
vcard: String,
|
||||
etag: String,
|
||||
created_at: DateTime<Utc>,
|
||||
updated_at: DateTime<Utc>,
|
||||
) -> Self {
|
||||
Self {
|
||||
id, address_book_id, uid, full_name, first_name, last_name, nickname,
|
||||
email, phone, address, organization, title, notes, photo_url,
|
||||
birthday, anniversary, vcard, etag, created_at, updated_at,
|
||||
}
|
||||
}
|
||||
|
||||
// --- Getters ---
|
||||
pub fn id(&self) -> &Uuid { &self.id }
|
||||
pub fn address_book_id(&self) -> &Uuid { &self.address_book_id }
|
||||
pub fn uid(&self) -> &str { &self.uid }
|
||||
pub fn full_name(&self) -> Option<&str> { self.full_name.as_deref() }
|
||||
pub fn first_name(&self) -> Option<&str> { self.first_name.as_deref() }
|
||||
pub fn last_name(&self) -> Option<&str> { self.last_name.as_deref() }
|
||||
pub fn nickname(&self) -> Option<&str> { self.nickname.as_deref() }
|
||||
pub fn email(&self) -> &[Email] { &self.email }
|
||||
pub fn phone(&self) -> &[Phone] { &self.phone }
|
||||
pub fn address(&self) -> &[Address] { &self.address }
|
||||
pub fn organization(&self) -> Option<&str> { self.organization.as_deref() }
|
||||
pub fn title(&self) -> Option<&str> { self.title.as_deref() }
|
||||
pub fn notes(&self) -> Option<&str> { self.notes.as_deref() }
|
||||
pub fn photo_url(&self) -> Option<&str> { self.photo_url.as_deref() }
|
||||
pub fn birthday(&self) -> Option<&NaiveDate> { self.birthday.as_ref() }
|
||||
pub fn anniversary(&self) -> Option<&NaiveDate> { self.anniversary.as_ref() }
|
||||
pub fn vcard(&self) -> &str { &self.vcard }
|
||||
pub fn etag(&self) -> &str { &self.etag }
|
||||
pub fn created_at(&self) -> &DateTime<Utc> { &self.created_at }
|
||||
pub fn updated_at(&self) -> &DateTime<Utc> { &self.updated_at }
|
||||
|
||||
// --- Owned getters for persistence layer bind() calls ---
|
||||
pub fn full_name_owned(&self) -> Option<String> { self.full_name.clone() }
|
||||
pub fn first_name_owned(&self) -> Option<String> { self.first_name.clone() }
|
||||
pub fn last_name_owned(&self) -> Option<String> { self.last_name.clone() }
|
||||
pub fn nickname_owned(&self) -> Option<String> { self.nickname.clone() }
|
||||
pub fn organization_owned(&self) -> Option<String> { self.organization.clone() }
|
||||
pub fn title_owned(&self) -> Option<String> { self.title.clone() }
|
||||
pub fn notes_owned(&self) -> Option<String> { self.notes.clone() }
|
||||
pub fn photo_url_owned(&self) -> Option<String> { self.photo_url.clone() }
|
||||
|
||||
// --- Setters for mutable operations (contact_service.rs needs these) ---
|
||||
pub fn set_full_name(&mut self, v: Option<String>) { self.full_name = v; }
|
||||
pub fn set_first_name(&mut self, v: Option<String>) { self.first_name = v; }
|
||||
pub fn set_last_name(&mut self, v: Option<String>) { self.last_name = v; }
|
||||
pub fn set_nickname(&mut self, v: Option<String>) { self.nickname = v; }
|
||||
pub fn set_organization(&mut self, v: Option<String>) { self.organization = v; }
|
||||
pub fn set_title(&mut self, v: Option<String>) { self.title = v; }
|
||||
pub fn set_notes(&mut self, v: Option<String>) { self.notes = v; }
|
||||
pub fn set_photo_url(&mut self, v: Option<String>) { self.photo_url = v; }
|
||||
pub fn set_birthday(&mut self, v: Option<NaiveDate>) { self.birthday = v; }
|
||||
pub fn set_anniversary(&mut self, v: Option<NaiveDate>) { self.anniversary = v; }
|
||||
pub fn set_vcard(&mut self, vcard: String) { self.vcard = vcard; }
|
||||
pub fn set_etag(&mut self, etag: String) { self.etag = etag; }
|
||||
pub fn set_updated_at(&mut self, updated_at: DateTime<Utc>) { self.updated_at = updated_at; }
|
||||
pub fn set_address_book_id(&mut self, id: Uuid) { self.address_book_id = id; }
|
||||
pub fn set_uid(&mut self, uid: String) { self.uid = uid; }
|
||||
|
||||
// --- Collection mutators ---
|
||||
pub fn push_email(&mut self, e: Email) { self.email.push(e); }
|
||||
pub fn push_phone(&mut self, p: Phone) { self.phone.push(p); }
|
||||
pub fn set_email(&mut self, email: Vec<Email>) { self.email = email; }
|
||||
pub fn set_phone(&mut self, phone: Vec<Phone>) { self.phone = phone; }
|
||||
pub fn set_address(&mut self, address: Vec<Address>) { self.address = address; }
|
||||
pub fn email_is_empty(&self) -> bool { self.email.is_empty() }
|
||||
pub fn phone_is_empty(&self) -> bool { self.phone.is_empty() }
|
||||
|
||||
// --- Consuming methods for ownership transfer ---
|
||||
pub fn into_email(self) -> Vec<Email> { self.email }
|
||||
pub fn into_parts(self) -> ContactParts {
|
||||
ContactParts {
|
||||
id: self.id,
|
||||
address_book_id: self.address_book_id,
|
||||
uid: self.uid,
|
||||
full_name: self.full_name,
|
||||
first_name: self.first_name,
|
||||
last_name: self.last_name,
|
||||
nickname: self.nickname,
|
||||
email: self.email,
|
||||
phone: self.phone,
|
||||
address: self.address,
|
||||
organization: self.organization,
|
||||
title: self.title,
|
||||
notes: self.notes,
|
||||
photo_url: self.photo_url,
|
||||
birthday: self.birthday,
|
||||
anniversary: self.anniversary,
|
||||
vcard: self.vcard,
|
||||
etag: self.etag,
|
||||
created_at: self.created_at,
|
||||
updated_at: self.updated_at,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds all Contact fields by value, for when ownership transfer is needed
|
||||
pub struct ContactParts {
|
||||
pub id: Uuid,
|
||||
pub address_book_id: Uuid,
|
||||
pub uid: String,
|
||||
@@ -79,6 +316,7 @@ pub struct Contact {
|
||||
|
||||
impl Default for Contact {
|
||||
fn default() -> Self {
|
||||
let now = Utc::now();
|
||||
Self {
|
||||
id: Uuid::new_v4(),
|
||||
address_book_id: Uuid::new_v4(),
|
||||
@@ -98,29 +336,53 @@ impl Default for Contact {
|
||||
anniversary: None,
|
||||
vcard: "BEGIN:VCARD\nVERSION:3.0\nEND:VCARD".to_string(),
|
||||
etag: Uuid::new_v4().to_string(),
|
||||
created_at: Utc::now(),
|
||||
updated_at: Utc::now(),
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ContactGroup {
|
||||
pub id: Uuid,
|
||||
pub address_book_id: Uuid,
|
||||
pub name: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
id: Uuid,
|
||||
address_book_id: Uuid,
|
||||
name: String,
|
||||
created_at: DateTime<Utc>,
|
||||
updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl ContactGroup {
|
||||
/// Creates a new ContactGroup with generated id and timestamps
|
||||
pub fn new(address_book_id: Uuid, name: String) -> Self {
|
||||
let now = Utc::now();
|
||||
Self { id: Uuid::new_v4(), address_book_id, name, created_at: now, updated_at: now }
|
||||
}
|
||||
|
||||
/// Reconstructs from persistence
|
||||
pub fn from_raw(
|
||||
id: Uuid,
|
||||
address_book_id: Uuid,
|
||||
name: String,
|
||||
created_at: DateTime<Utc>,
|
||||
updated_at: DateTime<Utc>,
|
||||
) -> Self {
|
||||
Self { id, address_book_id, name, created_at, updated_at }
|
||||
}
|
||||
|
||||
// --- Getters ---
|
||||
pub fn id(&self) -> &Uuid { &self.id }
|
||||
pub fn address_book_id(&self) -> &Uuid { &self.address_book_id }
|
||||
pub fn name(&self) -> &str { &self.name }
|
||||
pub fn created_at(&self) -> &DateTime<Utc> { &self.created_at }
|
||||
pub fn updated_at(&self) -> &DateTime<Utc> { &self.updated_at }
|
||||
|
||||
// --- Setters ---
|
||||
pub fn set_name(&mut self, name: String) { self.name = name; self.updated_at = Utc::now(); }
|
||||
pub fn set_updated_at(&mut self, updated_at: DateTime<Utc>) { self.updated_at = updated_at; }
|
||||
}
|
||||
|
||||
impl Default for ContactGroup {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
id: Uuid::new_v4(),
|
||||
address_book_id: Uuid::new_v4(),
|
||||
name: "New Group".to_string(),
|
||||
created_at: Utc::now(),
|
||||
updated_at: Utc::now(),
|
||||
}
|
||||
ContactGroup::new(Uuid::new_v4(), "New Group".to_string())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user