koprogo_api/application/use_cases/
owner_contribution_use_cases.rs1use crate::application::ports::OwnerContributionRepository;
2use crate::domain::entities::{ContributionPaymentMethod, ContributionType, OwnerContribution};
3use chrono::{DateTime, Utc};
4use std::sync::Arc;
5use uuid::Uuid;
6
7pub struct OwnerContributionUseCases {
8 repository: Arc<dyn OwnerContributionRepository>,
9}
10
11impl OwnerContributionUseCases {
12 pub fn new(repository: Arc<dyn OwnerContributionRepository>) -> Self {
13 Self { repository }
14 }
15
16 #[allow(clippy::too_many_arguments)]
18 pub async fn create_contribution(
19 &self,
20 organization_id: Uuid,
21 owner_id: Uuid,
22 unit_id: Option<Uuid>,
23 description: String,
24 amount: f64,
25 contribution_type: ContributionType,
26 contribution_date: DateTime<Utc>,
27 account_code: Option<String>,
28 ) -> Result<OwnerContribution, String> {
29 let contribution = OwnerContribution::new(
31 organization_id,
32 owner_id,
33 unit_id,
34 description,
35 amount,
36 contribution_type,
37 contribution_date,
38 account_code,
39 )?;
40
41 self.repository.create(&contribution).await
43 }
44
45 pub async fn record_payment(
47 &self,
48 contribution_id: Uuid,
49 payment_date: DateTime<Utc>,
50 payment_method: ContributionPaymentMethod,
51 payment_reference: Option<String>,
52 ) -> Result<OwnerContribution, String> {
53 let mut contribution = self
55 .repository
56 .find_by_id(contribution_id)
57 .await?
58 .ok_or_else(|| format!("Contribution not found: {}", contribution_id))?;
59
60 contribution.mark_as_paid(payment_date, payment_method, payment_reference);
62
63 self.repository.update(&contribution).await
65 }
66
67 pub async fn get_contribution(
69 &self,
70 contribution_id: Uuid,
71 ) -> Result<Option<OwnerContribution>, String> {
72 self.repository.find_by_id(contribution_id).await
73 }
74
75 pub async fn get_contributions_by_organization(
77 &self,
78 organization_id: Uuid,
79 ) -> Result<Vec<OwnerContribution>, String> {
80 self.repository.find_by_organization(organization_id).await
81 }
82
83 pub async fn get_contributions_by_owner(
85 &self,
86 owner_id: Uuid,
87 ) -> Result<Vec<OwnerContribution>, String> {
88 self.repository.find_by_owner(owner_id).await
89 }
90
91 pub async fn get_outstanding_contributions(
93 &self,
94 owner_id: Uuid,
95 ) -> Result<Vec<OwnerContribution>, String> {
96 let contributions = self.repository.find_by_owner(owner_id).await?;
97
98 Ok(contributions.into_iter().filter(|c| !c.is_paid()).collect())
100 }
101
102 pub async fn get_overdue_contributions(
104 &self,
105 owner_id: Uuid,
106 ) -> Result<Vec<OwnerContribution>, String> {
107 let contributions = self.repository.find_by_owner(owner_id).await?;
108
109 Ok(contributions
111 .into_iter()
112 .filter(|c| c.is_overdue())
113 .collect())
114 }
115
116 pub async fn get_outstanding_amount(&self, owner_id: Uuid) -> Result<f64, String> {
118 let outstanding = self.get_outstanding_contributions(owner_id).await?;
119 Ok(outstanding.iter().map(|c| c.amount).sum())
120 }
121}