koprogo_api/application/ports/
payment_repository.rs

1use crate::domain::entities::{Payment, TransactionStatus};
2use async_trait::async_trait;
3use uuid::Uuid;
4
5#[async_trait]
6pub trait PaymentRepository: Send + Sync {
7    /// Create a new payment
8    async fn create(&self, payment: &Payment) -> Result<Payment, String>;
9
10    /// Find payment by ID
11    async fn find_by_id(&self, id: Uuid) -> Result<Option<Payment>, String>;
12
13    /// Find payment by Stripe payment intent ID
14    async fn find_by_stripe_payment_intent_id(
15        &self,
16        stripe_payment_intent_id: &str,
17    ) -> Result<Option<Payment>, String>;
18
19    /// Find payment by idempotency key (prevents duplicate charges)
20    async fn find_by_idempotency_key(
21        &self,
22        organization_id: Uuid,
23        idempotency_key: &str,
24    ) -> Result<Option<Payment>, String>;
25
26    /// Find all payments for an owner
27    async fn find_by_owner(&self, owner_id: Uuid) -> Result<Vec<Payment>, String>;
28
29    /// Find all payments for a building
30    async fn find_by_building(&self, building_id: Uuid) -> Result<Vec<Payment>, String>;
31
32    /// Find all payments for an expense
33    async fn find_by_expense(&self, expense_id: Uuid) -> Result<Vec<Payment>, String>;
34
35    /// Find all payments for an organization
36    async fn find_by_organization(&self, organization_id: Uuid) -> Result<Vec<Payment>, String>;
37
38    /// Find payments by status
39    async fn find_by_status(
40        &self,
41        organization_id: Uuid,
42        status: TransactionStatus,
43    ) -> Result<Vec<Payment>, String>;
44
45    /// Find payments by status and building
46    async fn find_by_building_and_status(
47        &self,
48        building_id: Uuid,
49        status: TransactionStatus,
50    ) -> Result<Vec<Payment>, String>;
51
52    /// Find pending payments (for background processing)
53    async fn find_pending(&self, organization_id: Uuid) -> Result<Vec<Payment>, String>;
54
55    /// Find failed payments (for retry or analysis)
56    async fn find_failed(&self, organization_id: Uuid) -> Result<Vec<Payment>, String>;
57
58    /// Update payment
59    async fn update(&self, payment: &Payment) -> Result<Payment, String>;
60
61    /// Delete payment (soft delete recommended in production)
62    async fn delete(&self, id: Uuid) -> Result<bool, String>;
63
64    /// Get total amount paid for an expense (sum of succeeded payments)
65    async fn get_total_paid_for_expense(&self, expense_id: Uuid) -> Result<i64, String>;
66
67    /// Get total amount paid by owner (sum of succeeded payments)
68    async fn get_total_paid_by_owner(&self, owner_id: Uuid) -> Result<i64, String>;
69
70    /// Get total amount paid for building (sum of succeeded payments)
71    async fn get_total_paid_for_building(&self, building_id: Uuid) -> Result<i64, String>;
72
73    /// Get payment statistics for owner
74    async fn get_owner_payment_stats(&self, owner_id: Uuid) -> Result<PaymentStats, String>;
75
76    /// Get payment statistics for building
77    async fn get_building_payment_stats(&self, building_id: Uuid) -> Result<PaymentStats, String>;
78}
79
80/// Payment statistics
81#[derive(Debug, Clone)]
82pub struct PaymentStats {
83    pub total_count: i64,
84    pub succeeded_count: i64,
85    pub failed_count: i64,
86    pub pending_count: i64,
87    pub total_amount_cents: i64,
88    pub total_succeeded_cents: i64,
89    pub total_refunded_cents: i64,
90    pub net_amount_cents: i64, // succeeded - refunded
91}