koprogo_api/application/use_cases/
payment_method_use_cases.rs1use crate::application::dto::{
2 CreatePaymentMethodRequest, PaymentMethodResponse, UpdatePaymentMethodRequest,
3};
4use crate::application::ports::PaymentMethodRepository;
5use crate::domain::entities::payment_method::{PaymentMethod, PaymentMethodType};
6use std::sync::Arc;
7use uuid::Uuid;
8
9pub struct PaymentMethodUseCases {
10 payment_method_repository: Arc<dyn PaymentMethodRepository>,
11}
12
13impl PaymentMethodUseCases {
14 pub fn new(payment_method_repository: Arc<dyn PaymentMethodRepository>) -> Self {
15 Self {
16 payment_method_repository,
17 }
18 }
19
20 pub async fn create_payment_method(
24 &self,
25 organization_id: Uuid,
26 request: CreatePaymentMethodRequest,
27 ) -> Result<PaymentMethodResponse, String> {
28 let payment_method = PaymentMethod::new(
29 organization_id,
30 request.owner_id,
31 request.method_type,
32 request.stripe_payment_method_id,
33 request.stripe_customer_id,
34 request.display_label,
35 request.is_default,
36 )?;
37
38 let mut payment_method = payment_method;
40 if let Some(metadata) = request.metadata {
41 payment_method.set_metadata(metadata);
42 }
43
44 if let Some(expires_at) = request.expires_at {
46 payment_method.set_expiry(expires_at)?;
47 }
48
49 let created = self
50 .payment_method_repository
51 .create(&payment_method)
52 .await?;
53
54 if created.is_default {
56 let _ = self
57 .payment_method_repository
58 .set_as_default(created.id, created.owner_id)
59 .await?;
60 }
61
62 Ok(PaymentMethodResponse::from(created))
63 }
64
65 pub async fn get_payment_method(
67 &self,
68 id: Uuid,
69 ) -> Result<Option<PaymentMethodResponse>, String> {
70 match self.payment_method_repository.find_by_id(id).await? {
71 Some(method) => Ok(Some(PaymentMethodResponse::from(method))),
72 None => Ok(None),
73 }
74 }
75
76 pub async fn get_payment_method_by_stripe_id(
78 &self,
79 stripe_payment_method_id: &str,
80 ) -> Result<Option<PaymentMethodResponse>, String> {
81 match self
82 .payment_method_repository
83 .find_by_stripe_payment_method_id(stripe_payment_method_id)
84 .await?
85 {
86 Some(method) => Ok(Some(PaymentMethodResponse::from(method))),
87 None => Ok(None),
88 }
89 }
90
91 pub async fn list_owner_payment_methods(
93 &self,
94 owner_id: Uuid,
95 ) -> Result<Vec<PaymentMethodResponse>, String> {
96 let methods = self
97 .payment_method_repository
98 .find_by_owner(owner_id)
99 .await?;
100 Ok(methods
101 .into_iter()
102 .map(PaymentMethodResponse::from)
103 .collect())
104 }
105
106 pub async fn list_active_owner_payment_methods(
108 &self,
109 owner_id: Uuid,
110 ) -> Result<Vec<PaymentMethodResponse>, String> {
111 let methods = self
112 .payment_method_repository
113 .find_active_by_owner(owner_id)
114 .await?;
115 Ok(methods
116 .into_iter()
117 .map(PaymentMethodResponse::from)
118 .collect())
119 }
120
121 pub async fn get_default_payment_method(
123 &self,
124 owner_id: Uuid,
125 ) -> Result<Option<PaymentMethodResponse>, String> {
126 match self
127 .payment_method_repository
128 .find_default_by_owner(owner_id)
129 .await?
130 {
131 Some(method) => Ok(Some(PaymentMethodResponse::from(method))),
132 None => Ok(None),
133 }
134 }
135
136 pub async fn list_organization_payment_methods(
138 &self,
139 organization_id: Uuid,
140 ) -> Result<Vec<PaymentMethodResponse>, String> {
141 let methods = self
142 .payment_method_repository
143 .find_by_organization(organization_id)
144 .await?;
145 Ok(methods
146 .into_iter()
147 .map(PaymentMethodResponse::from)
148 .collect())
149 }
150
151 pub async fn list_payment_methods_by_type(
153 &self,
154 owner_id: Uuid,
155 method_type: PaymentMethodType,
156 ) -> Result<Vec<PaymentMethodResponse>, String> {
157 let methods = self
158 .payment_method_repository
159 .find_by_owner_and_type(owner_id, method_type)
160 .await?;
161 Ok(methods
162 .into_iter()
163 .map(PaymentMethodResponse::from)
164 .collect())
165 }
166
167 pub async fn update_payment_method(
169 &self,
170 id: Uuid,
171 request: UpdatePaymentMethodRequest,
172 ) -> Result<PaymentMethodResponse, String> {
173 let mut payment_method = self
174 .payment_method_repository
175 .find_by_id(id)
176 .await?
177 .ok_or_else(|| "Payment method not found".to_string())?;
178
179 if let Some(display_label) = request.display_label {
181 if display_label.trim().is_empty() {
182 return Err("Display label cannot be empty".to_string());
183 }
184 payment_method.display_label = display_label;
185 payment_method.updated_at = chrono::Utc::now();
186 }
187
188 if let Some(metadata) = request.metadata {
190 payment_method.set_metadata(metadata);
191 }
192
193 if let Some(is_default) = request.is_default {
195 if is_default && !payment_method.is_default {
196 return Ok(PaymentMethodResponse::from(
198 self.payment_method_repository
199 .set_as_default(id, payment_method.owner_id)
200 .await?,
201 ));
202 } else if !is_default && payment_method.is_default {
203 payment_method.unset_default();
205 }
206 }
207
208 let updated = self
209 .payment_method_repository
210 .update(&payment_method)
211 .await?;
212 Ok(PaymentMethodResponse::from(updated))
213 }
214
215 pub async fn set_as_default(
217 &self,
218 id: Uuid,
219 owner_id: Uuid,
220 ) -> Result<PaymentMethodResponse, String> {
221 let payment_method = self
222 .payment_method_repository
223 .set_as_default(id, owner_id)
224 .await?;
225 Ok(PaymentMethodResponse::from(payment_method))
226 }
227
228 pub async fn deactivate_payment_method(
230 &self,
231 id: Uuid,
232 ) -> Result<PaymentMethodResponse, String> {
233 let mut payment_method = self
234 .payment_method_repository
235 .find_by_id(id)
236 .await?
237 .ok_or_else(|| "Payment method not found".to_string())?;
238
239 payment_method.deactivate()?;
240
241 let updated = self
242 .payment_method_repository
243 .update(&payment_method)
244 .await?;
245 Ok(PaymentMethodResponse::from(updated))
246 }
247
248 pub async fn reactivate_payment_method(
250 &self,
251 id: Uuid,
252 ) -> Result<PaymentMethodResponse, String> {
253 let mut payment_method = self
254 .payment_method_repository
255 .find_by_id(id)
256 .await?
257 .ok_or_else(|| "Payment method not found".to_string())?;
258
259 payment_method.reactivate()?;
260
261 let updated = self
262 .payment_method_repository
263 .update(&payment_method)
264 .await?;
265 Ok(PaymentMethodResponse::from(updated))
266 }
267
268 pub async fn delete_payment_method(&self, id: Uuid) -> Result<bool, String> {
270 self.payment_method_repository.delete(id).await
271 }
272
273 pub async fn count_active_payment_methods(&self, owner_id: Uuid) -> Result<i64, String> {
275 self.payment_method_repository
276 .count_active_by_owner(owner_id)
277 .await
278 }
279
280 pub async fn has_active_payment_methods(&self, owner_id: Uuid) -> Result<bool, String> {
282 self.payment_method_repository
283 .has_active_payment_methods(owner_id)
284 .await
285 }
286}