lab_resource_manager/application/usecases/
update_resource_usage.rs1use crate::application::error::ApplicationError;
2use crate::domain::aggregates::resource_usage::value_objects::{TimePeriod, UsageId};
3use crate::domain::common::EmailAddress;
4use crate::domain::ports::repositories::{RepositoryError, ResourceUsageRepository};
5use crate::domain::services::{
6 AuthorizationPolicy, ResourceConflictChecker, ResourceUsageAuthorizationPolicy,
7};
8use std::sync::Arc;
9
10pub struct UpdateResourceUsageUseCase<R: ResourceUsageRepository> {
12 repository: Arc<R>,
13 authorization_policy: ResourceUsageAuthorizationPolicy,
14 conflict_checker: ResourceConflictChecker,
15}
16
17impl<R: ResourceUsageRepository> UpdateResourceUsageUseCase<R> {
18 pub fn new(repository: Arc<R>) -> Self {
23 let authorization_policy = ResourceUsageAuthorizationPolicy::new();
24 let conflict_checker = ResourceConflictChecker::new();
25 Self {
26 repository,
27 authorization_policy,
28 conflict_checker,
29 }
30 }
31
32 pub async fn execute(
49 &self,
50 id: &UsageId,
51 owner_email: &EmailAddress,
52 new_time_period: Option<TimePeriod>,
53 new_notes: Option<String>,
54 ) -> Result<(), ApplicationError> {
55 let mut usage = self
57 .repository
58 .find_by_id(id)
59 .await?
60 .ok_or(ApplicationError::Repository(RepositoryError::NotFound))?;
61
62 self.authorization_policy
64 .authorize_update(owner_email, &usage)
65 .map_err(|e| ApplicationError::Unauthorized(e.to_string()))?;
66
67 if let Some(new_period) = new_time_period {
69 self.conflict_checker
71 .check_conflicts(
72 self.repository.as_ref(),
73 &new_period,
74 usage.resources(),
75 Some(usage.id()),
76 )
77 .await
78 .map_err(|e| match e {
79 crate::domain::services::resource_usage::errors::ConflictCheckError::Conflict(
80 conflict_err,
81 ) => ApplicationError::ResourceConflict {
82 resource_description: conflict_err.resource_description.clone(),
83 conflicting_usage_id: conflict_err.conflicting_usage_id.as_str().to_string(),
84 },
85 crate::domain::services::resource_usage::errors::ConflictCheckError::Repository(
86 repo_err,
87 ) => ApplicationError::Repository(repo_err),
88 })?;
89
90 usage.update_time_period(new_period);
91 }
92
93 if let Some(notes) = new_notes {
95 usage.update_notes(notes);
96 }
97
98 self.repository.save(&usage).await?;
100
101 Ok(())
102 }
103}