koprogo_api/domain/entities/
unit.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5/// Type de lot (appartement, cave, parking, etc.)
6#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
7pub enum UnitType {
8    Apartment,
9    Parking,
10    Cellar,
11    Commercial,
12    Other,
13}
14
15/// Représente un lot dans la copropriété
16#[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, // en m²
25    pub quota: f64,        // Quote-part en millièmes
26    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}