koprogo_api/domain/entities/
unit.rs1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
7pub enum UnitType {
8 Apartment,
9 Parking,
10 Cellar,
11 Commercial,
12 Other,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
17pub struct Unit {
18 pub id: Uuid,
19 pub organization_id: Uuid,
20 pub building_id: Uuid,
21 pub unit_number: String,
22 pub unit_type: UnitType,
23 pub floor: Option<i32>,
24 pub surface_area: f64, pub quota: f64, pub owner_id: Option<Uuid>,
27 pub created_at: DateTime<Utc>,
28 pub updated_at: DateTime<Utc>,
29}
30
31impl Unit {
32 pub fn new(
33 organization_id: Uuid,
34 building_id: Uuid,
35 unit_number: String,
36 unit_type: UnitType,
37 floor: Option<i32>,
38 surface_area: f64,
39 quota: f64,
40 ) -> Result<Self, String> {
41 if unit_number.is_empty() {
42 return Err("Unit number cannot be empty".to_string());
43 }
44 if surface_area <= 0.0 {
45 return Err("Surface area must be greater than 0".to_string());
46 }
47 if quota <= 0.0 || quota > 1000.0 {
48 return Err("Quota must be between 0 and 1000".to_string());
49 }
50
51 let now = Utc::now();
52 Ok(Self {
53 id: Uuid::new_v4(),
54 organization_id,
55 building_id,
56 unit_number,
57 unit_type,
58 floor,
59 surface_area,
60 quota,
61 owner_id: None,
62 created_at: now,
63 updated_at: now,
64 })
65 }
66
67 pub fn validate_update(&self) -> Result<(), String> {
68 if self.unit_number.is_empty() {
69 return Err("Unit number cannot be empty".to_string());
70 }
71 if self.surface_area <= 0.0 {
72 return Err("Surface area must be greater than 0".to_string());
73 }
74 if self.quota <= 0.0 || self.quota > 1000.0 {
75 return Err("Quota must be between 0 and 1000".to_string());
76 }
77 Ok(())
78 }
79
80 pub fn assign_owner(&mut self, owner_id: Uuid) {
81 self.owner_id = Some(owner_id);
82 self.updated_at = Utc::now();
83 }
84
85 pub fn remove_owner(&mut self) {
86 self.owner_id = None;
87 self.updated_at = Utc::now();
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn test_create_unit_success() {
97 let org_id = Uuid::new_v4();
98 let building_id = Uuid::new_v4();
99 let unit = Unit::new(
100 org_id,
101 building_id,
102 "A101".to_string(),
103 UnitType::Apartment,
104 Some(1),
105 75.5,
106 50.0,
107 );
108
109 assert!(unit.is_ok());
110 let unit = unit.unwrap();
111 assert_eq!(unit.organization_id, org_id);
112 assert_eq!(unit.unit_number, "A101");
113 assert_eq!(unit.surface_area, 75.5);
114 }
115
116 #[test]
117 fn test_create_unit_invalid_surface_fails() {
118 let org_id = Uuid::new_v4();
119 let building_id = Uuid::new_v4();
120 let unit = Unit::new(
121 org_id,
122 building_id,
123 "A101".to_string(),
124 UnitType::Apartment,
125 Some(1),
126 0.0,
127 50.0,
128 );
129
130 assert!(unit.is_err());
131 }
132
133 #[test]
134 fn test_assign_owner() {
135 let org_id = Uuid::new_v4();
136 let building_id = Uuid::new_v4();
137 let mut unit = Unit::new(
138 org_id,
139 building_id,
140 "A101".to_string(),
141 UnitType::Apartment,
142 Some(1),
143 75.5,
144 50.0,
145 )
146 .unwrap();
147
148 let owner_id = Uuid::new_v4();
149 unit.assign_owner(owner_id);
150
151 assert_eq!(unit.owner_id, Some(owner_id));
152 }
153}