koprogo_api/application/use_cases/
unit_use_cases.rs

1use crate::application::dto::{CreateUnitDto, PageRequest, UnitFilters, UnitResponseDto};
2use crate::application::ports::UnitRepository;
3use crate::domain::entities::Unit;
4use std::sync::Arc;
5use uuid::Uuid;
6
7pub struct UnitUseCases {
8    repository: Arc<dyn UnitRepository>,
9}
10
11impl UnitUseCases {
12    pub fn new(repository: Arc<dyn UnitRepository>) -> Self {
13        Self { repository }
14    }
15
16    pub async fn create_unit(&self, dto: CreateUnitDto) -> Result<UnitResponseDto, String> {
17        let organization_id = Uuid::parse_str(&dto.organization_id)
18            .map_err(|_| "Invalid organization_id format".to_string())?;
19        let building_id = Uuid::parse_str(&dto.building_id)
20            .map_err(|_| "Invalid building ID format".to_string())?;
21
22        let unit = Unit::new(
23            organization_id,
24            building_id,
25            dto.unit_number,
26            dto.unit_type,
27            dto.floor,
28            dto.surface_area,
29            dto.quota,
30        )?;
31
32        let created = self.repository.create(&unit).await?;
33        Ok(self.to_response_dto(&created))
34    }
35
36    pub async fn get_unit(&self, id: Uuid) -> Result<Option<UnitResponseDto>, String> {
37        let unit = self.repository.find_by_id(id).await?;
38        Ok(unit.map(|u| self.to_response_dto(&u)))
39    }
40
41    pub async fn list_units_by_building(
42        &self,
43        building_id: Uuid,
44    ) -> Result<Vec<UnitResponseDto>, String> {
45        let units = self.repository.find_by_building(building_id).await?;
46        Ok(units.iter().map(|u| self.to_response_dto(u)).collect())
47    }
48
49    pub async fn list_units_paginated(
50        &self,
51        page_request: &PageRequest,
52        organization_id: Option<Uuid>,
53    ) -> Result<(Vec<UnitResponseDto>, i64), String> {
54        let filters = UnitFilters {
55            organization_id,
56            ..Default::default()
57        };
58
59        let (units, total) = self
60            .repository
61            .find_all_paginated(page_request, &filters)
62            .await?;
63
64        let dtos = units.iter().map(|u| self.to_response_dto(u)).collect();
65        Ok((dtos, total))
66    }
67
68    pub async fn assign_owner(
69        &self,
70        unit_id: Uuid,
71        owner_id: Uuid,
72    ) -> Result<UnitResponseDto, String> {
73        let mut unit = self
74            .repository
75            .find_by_id(unit_id)
76            .await?
77            .ok_or_else(|| "Unit not found".to_string())?;
78
79        unit.assign_owner(owner_id);
80
81        let updated = self.repository.update(&unit).await?;
82        Ok(self.to_response_dto(&updated))
83    }
84
85    fn to_response_dto(&self, unit: &Unit) -> UnitResponseDto {
86        UnitResponseDto {
87            id: unit.id.to_string(),
88            building_id: unit.building_id.to_string(),
89            unit_number: unit.unit_number.clone(),
90            unit_type: unit.unit_type.clone(),
91            floor: unit.floor,
92            surface_area: unit.surface_area,
93            quota: unit.quota,
94            owner_id: unit.owner_id.map(|id| id.to_string()),
95        }
96    }
97}