use crate::application::error::ApplicationError;
use crate::domain::aggregates::resource_usage::{
entity::ResourceUsage,
value_objects::{Resource, TimePeriod, UsageId},
};
use crate::domain::common::EmailAddress;
use crate::domain::ports::repositories::ResourceUsageRepository;
use crate::domain::services::ResourceConflictChecker;
use std::sync::Arc;
pub struct CreateResourceUsageUseCase<R: ResourceUsageRepository> {
repository: Arc<R>,
conflict_checker: ResourceConflictChecker,
}
impl<R: ResourceUsageRepository> CreateResourceUsageUseCase<R> {
pub fn new(repository: Arc<R>) -> Self {
let conflict_checker = ResourceConflictChecker::new();
Self {
repository,
conflict_checker,
}
}
pub async fn execute(
&self,
owner_email: EmailAddress,
time_period: TimePeriod,
resources: Vec<Resource>,
notes: Option<String>,
) -> Result<UsageId, ApplicationError> {
self.conflict_checker
.check_conflicts(self.repository.as_ref(), &time_period, &resources, None)
.await
.map_err(|e| match e {
crate::domain::services::resource_usage::errors::ConflictCheckError::Conflict(
conflict_err,
) => ApplicationError::ResourceConflict {
resource_description: conflict_err.resource_description.clone(),
conflicting_usage_id: conflict_err.conflicting_usage_id.as_str().to_string(),
},
crate::domain::services::resource_usage::errors::ConflictCheckError::Repository(
repo_err,
) => ApplicationError::Repository(repo_err),
})?;
let usage = ResourceUsage::new(owner_email, time_period, resources, notes)?;
self.repository.save(&usage).await?;
Ok(usage.id().clone())
}
}