lab_resource_manager/application/usecases/
create_resource_usage.rs

1use crate::application::error::ApplicationError;
2use crate::domain::aggregates::resource_usage::{
3    entity::ResourceUsage,
4    value_objects::{Resource, TimePeriod, UsageId},
5};
6use crate::domain::common::EmailAddress;
7use crate::domain::ports::repositories::ResourceUsageRepository;
8use crate::domain::services::ResourceConflictChecker;
9use std::sync::Arc;
10
11/// リソース使用予定を作成するユースケース
12pub struct CreateResourceUsageUseCase<R: ResourceUsageRepository> {
13    repository: Arc<R>,
14    conflict_checker: ResourceConflictChecker,
15}
16
17impl<R: ResourceUsageRepository> CreateResourceUsageUseCase<R> {
18    /// 新しいCreateResourceUsageUseCaseインスタンスを作成
19    ///
20    /// # Arguments
21    /// * `repository` - ResourceUsageリポジトリ
22    pub fn new(repository: Arc<R>) -> Self {
23        let conflict_checker = ResourceConflictChecker::new();
24        Self {
25            repository,
26            conflict_checker,
27        }
28    }
29
30    /// リソース使用予定を作成
31    ///
32    /// # Arguments
33    /// * `owner_email` - 所有者のメールアドレス
34    /// * `time_period` - 使用期間
35    /// * `resources` - 使用するリソースのリスト
36    /// * `notes` - 備考(オプション)
37    ///
38    /// # Returns
39    /// 作成されたResourceUsageのID
40    ///
41    /// # Errors
42    /// - 指定期間と重複するリソース使用がある場合
43    /// - リポジトリエラー
44    pub async fn execute(
45        &self,
46        owner_email: EmailAddress,
47        time_period: TimePeriod,
48        resources: Vec<Resource>,
49        notes: Option<String>,
50    ) -> Result<UsageId, ApplicationError> {
51        // 競合チェック
52        self.conflict_checker
53            .check_conflicts(self.repository.as_ref(), &time_period, &resources, None)
54            .await
55            .map_err(|e| match e {
56                crate::domain::services::resource_usage::errors::ConflictCheckError::Conflict(
57                    conflict_err,
58                ) => ApplicationError::ResourceConflict {
59                    resource_description: conflict_err.resource_description.clone(),
60                    conflicting_usage_id: conflict_err.conflicting_usage_id.as_str().to_string(),
61                },
62                crate::domain::services::resource_usage::errors::ConflictCheckError::Repository(
63                    repo_err,
64                ) => ApplicationError::Repository(repo_err),
65            })?;
66
67        // 新しいResourceUsageを作成(UUID自動生成)
68        let usage = ResourceUsage::new(owner_email, time_period, resources, notes)?;
69
70        // 保存
71        self.repository.save(&usage).await?;
72
73        // 生成されたIDを返す
74        Ok(usage.id().clone())
75    }
76}