use crate::application::error::ApplicationError;
use crate::domain::aggregates::resource_usage::value_objects::{TimePeriod, UsageId};
use crate::domain::common::EmailAddress;
use crate::domain::ports::repositories::{RepositoryError, ResourceUsageRepository};
use crate::domain::services::{
AuthorizationPolicy, ResourceConflictChecker, ResourceUsageAuthorizationPolicy,
};
use std::sync::Arc;
pub struct UpdateResourceUsageUseCase<R: ResourceUsageRepository> {
repository: Arc<R>,
authorization_policy: ResourceUsageAuthorizationPolicy,
conflict_checker: ResourceConflictChecker,
}
impl<R: ResourceUsageRepository> UpdateResourceUsageUseCase<R> {
pub fn new(repository: Arc<R>) -> Self {
let authorization_policy = ResourceUsageAuthorizationPolicy::new();
let conflict_checker = ResourceConflictChecker::new();
Self {
repository,
authorization_policy,
conflict_checker,
}
}
pub async fn execute(
&self,
id: &UsageId,
owner_email: &EmailAddress,
new_time_period: Option<TimePeriod>,
new_notes: Option<String>,
) -> Result<(), ApplicationError> {
let mut usage = self
.repository
.find_by_id(id)
.await?
.ok_or(ApplicationError::Repository(RepositoryError::NotFound))?;
self.authorization_policy
.authorize_update(owner_email, &usage)
.map_err(|e| ApplicationError::Unauthorized(e.to_string()))?;
if let Some(new_period) = new_time_period {
self.conflict_checker
.check_conflicts(
self.repository.as_ref(),
&new_period,
usage.resources(),
Some(usage.id()),
)
.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),
})?;
usage.update_time_period(new_period);
}
if let Some(notes) = new_notes {
usage.update_notes(notes);
}
self.repository.save(&usage).await?;
Ok(())
}
}