Skip to main content

koprogo_api/application/ports/
payment_reminder_repository.rs

1use crate::application::error::AppError;
2use crate::domain::entities::{PaymentReminder, ReminderLevel, ReminderStatus};
3use async_trait::async_trait;
4use chrono::{DateTime, Utc};
5use rust_decimal::Decimal;
6use uuid::Uuid;
7
8/// Repository trait for payment reminder persistence operations
9#[async_trait]
10pub trait PaymentReminderRepository: Send + Sync {
11    /// Create a new payment reminder
12    async fn create(&self, reminder: &PaymentReminder) -> Result<PaymentReminder, AppError>;
13
14    /// Find a reminder by ID
15    async fn find_by_id(&self, id: Uuid) -> Result<Option<PaymentReminder>, AppError>;
16
17    /// Find all reminders for a specific expense
18    async fn find_by_expense(&self, expense_id: Uuid) -> Result<Vec<PaymentReminder>, AppError>;
19
20    /// Find all reminders for a specific owner
21    async fn find_by_owner(&self, owner_id: Uuid) -> Result<Vec<PaymentReminder>, AppError>;
22
23    /// Find all reminders for an organization
24    async fn find_by_organization(
25        &self,
26        organization_id: Uuid,
27    ) -> Result<Vec<PaymentReminder>, AppError>;
28
29    /// Find all reminders with a specific status
30    async fn find_by_status(
31        &self,
32        status: ReminderStatus,
33    ) -> Result<Vec<PaymentReminder>, AppError>;
34
35    /// Find all reminders with a specific status for an organization
36    async fn find_by_organization_and_status(
37        &self,
38        organization_id: Uuid,
39        status: ReminderStatus,
40    ) -> Result<Vec<PaymentReminder>, AppError>;
41
42    /// Find all pending reminders that should be sent (status = Pending)
43    async fn find_pending_reminders(&self) -> Result<Vec<PaymentReminder>, AppError>;
44
45    /// Find all sent reminders that need escalation (sent > 15 days ago)
46    async fn find_reminders_needing_escalation(
47        &self,
48        cutoff_date: DateTime<Utc>,
49    ) -> Result<Vec<PaymentReminder>, AppError>;
50
51    /// Find the latest reminder for a specific expense
52    async fn find_latest_by_expense(
53        &self,
54        expense_id: Uuid,
55    ) -> Result<Option<PaymentReminder>, AppError>;
56
57    /// Find all active (non-paid, non-cancelled) reminders for an owner
58    async fn find_active_by_owner(&self, owner_id: Uuid) -> Result<Vec<PaymentReminder>, AppError>;
59
60    /// Get statistics: count reminders by status for an organization
61    async fn count_by_status(
62        &self,
63        organization_id: Uuid,
64    ) -> Result<Vec<(ReminderStatus, i64)>, AppError>;
65
66    /// Get statistics: total amount owed by organization
67    async fn get_total_owed_by_organization(
68        &self,
69        organization_id: Uuid,
70    ) -> Result<Decimal, AppError>;
71
72    /// Get statistics: total penalties by organization
73    async fn get_total_penalties_by_organization(
74        &self,
75        organization_id: Uuid,
76    ) -> Result<Decimal, AppError>;
77
78    /// Get overdue expenses without reminders (for automated detection)
79    /// Returns list of (expense_id, owner_id, days_overdue, amount)
80    async fn find_overdue_expenses_without_reminders(
81        &self,
82        organization_id: Uuid,
83        min_days_overdue: i64,
84    ) -> Result<Vec<(Uuid, Uuid, i64, Decimal)>, AppError>;
85
86    /// Update a reminder
87    async fn update(&self, reminder: &PaymentReminder) -> Result<PaymentReminder, AppError>;
88
89    /// Delete a reminder
90    async fn delete(&self, id: Uuid) -> Result<bool, AppError>;
91
92    /// Get payment recovery dashboard data for an organization
93    /// Returns: (total_owed, total_penalties, reminder_count_by_level)
94    async fn get_dashboard_stats(
95        &self,
96        organization_id: Uuid,
97    ) -> Result<(Decimal, Decimal, Vec<(ReminderLevel, i64)>), AppError>;
98}