Skip to main content

koprogo_api/application/dto/
payment_dto.rs

1use crate::domain::entities::{Payment, PaymentMethodType, TransactionStatus};
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6/// Payment response DTO
7#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
8pub struct PaymentResponse {
9    pub id: Uuid,
10    pub organization_id: Uuid,
11    pub building_id: Uuid,
12    pub owner_id: Uuid,
13    pub expense_id: Option<Uuid>,
14    pub contribution_id: Option<Uuid>,
15    pub amount_cents: i64,
16    pub currency: String,
17    pub status: TransactionStatus,
18    pub payment_method_type: PaymentMethodType,
19    pub stripe_payment_intent_id: Option<String>,
20    pub stripe_customer_id: Option<String>,
21    pub payment_method_id: Option<Uuid>,
22    pub idempotency_key: String,
23    pub description: Option<String>,
24    pub metadata: Option<String>,
25    pub failure_reason: Option<String>,
26    pub refunded_amount_cents: i64,
27    pub net_amount_cents: i64, // amount_cents - refunded_amount_cents
28    pub succeeded_at: Option<DateTime<Utc>>,
29    pub failed_at: Option<DateTime<Utc>>,
30    pub cancelled_at: Option<DateTime<Utc>>,
31    pub created_at: DateTime<Utc>,
32    pub updated_at: DateTime<Utc>,
33}
34
35impl From<Payment> for PaymentResponse {
36    fn from(payment: Payment) -> Self {
37        let net_amount_cents = payment.get_net_amount_cents();
38
39        Self {
40            id: payment.id,
41            organization_id: payment.organization_id,
42            building_id: payment.building_id,
43            owner_id: payment.owner_id,
44            expense_id: payment.expense_id,
45            contribution_id: payment.contribution_id,
46            amount_cents: payment.amount_cents,
47            currency: payment.currency,
48            status: payment.status,
49            payment_method_type: payment.payment_method_type,
50            stripe_payment_intent_id: payment.stripe_payment_intent_id,
51            stripe_customer_id: payment.stripe_customer_id,
52            payment_method_id: payment.payment_method_id,
53            idempotency_key: payment.idempotency_key,
54            description: payment.description,
55            metadata: payment.metadata,
56            failure_reason: payment.failure_reason,
57            refunded_amount_cents: payment.refunded_amount_cents,
58            net_amount_cents,
59            succeeded_at: payment.succeeded_at,
60            failed_at: payment.failed_at,
61            cancelled_at: payment.cancelled_at,
62            created_at: payment.created_at,
63            updated_at: payment.updated_at,
64        }
65    }
66}
67
68/// Create payment request DTO
69///
70/// `deny_unknown_fields` : un `POST /payments` portant `contribution_id`
71/// repondait 201 en jetant le champ, laissant croire que la quote-part venait
72/// d'etre soldee. Le champ existe desormais ; tout AUTRE champ inconnu
73/// (`currency`, `stripe_payment_intent_id`, que le client TypeScript envoyait
74/// sans qu'ils existent cote serveur) produit un 400 explicite plutot qu'une
75/// perte silencieuse.
76#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
77#[serde(deny_unknown_fields)]
78pub struct CreatePaymentRequest {
79    pub building_id: Uuid,
80    pub owner_id: Uuid,
81    pub expense_id: Option<Uuid>,
82    /// Quote-part soldee par ce paiement. La contribution ne passe a `paid`
83    /// qu'a la reussite du paiement, pas a sa creation.
84    #[serde(default)]
85    pub contribution_id: Option<Uuid>,
86    pub amount_cents: i64,
87    pub payment_method_type: PaymentMethodType,
88    pub payment_method_id: Option<Uuid>, // If using saved payment method
89    pub description: Option<String>,
90    pub metadata: Option<String>,
91}
92
93/// Refund payment request DTO
94#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
95pub struct RefundPaymentRequest {
96    pub amount_cents: i64,
97    pub reason: Option<String>,
98}
99
100/// Payment statistics response DTO
101#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
102pub struct PaymentStatsResponse {
103    pub total_count: i64,
104    pub succeeded_count: i64,
105    pub failed_count: i64,
106    pub pending_count: i64,
107    pub total_amount_cents: i64,
108    pub total_succeeded_cents: i64,
109    pub total_refunded_cents: i64,
110    pub net_amount_cents: i64,
111}