mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 10:06:32 +08:00 
			
		
		
		
	feat(router): add filters for refunds (#1501)
Co-authored-by: Sampras Lopes <lsampras@protonmail.com>
This commit is contained in:
		| @ -24,6 +24,7 @@ use crate::{ | ||||
|     }, | ||||
|     utils::{self, OptionExt}, | ||||
| }; | ||||
|  | ||||
| // ********************************************** REFUND EXECUTE ********************************************** | ||||
|  | ||||
| #[instrument(skip_all)] | ||||
| @ -646,20 +647,24 @@ pub async fn refund_list( | ||||
|     req: api_models::refunds::RefundListRequest, | ||||
| ) -> RouterResponse<api_models::refunds::RefundListResponse> { | ||||
|     let limit = validator::validate_refund_list(req.limit)?; | ||||
|     let offset = req.offset.unwrap_or_default(); | ||||
|  | ||||
|     let refund_list = db | ||||
|         .filter_refund_by_constraints( | ||||
|             &merchant_account.merchant_id, | ||||
|             &req, | ||||
|             merchant_account.storage_scheme, | ||||
|             limit, | ||||
|             offset, | ||||
|         ) | ||||
|         .await | ||||
|         .change_context(errors::ApiErrorResponse::RefundNotFound)?; | ||||
|         .to_not_found_response(errors::ApiErrorResponse::RefundNotFound)?; | ||||
|  | ||||
|     let data: Vec<refunds::RefundResponse> = refund_list | ||||
|         .into_iter() | ||||
|         .map(ForeignInto::foreign_into) | ||||
|         .collect(); | ||||
|  | ||||
|     Ok(services::ApplicationResponse::Json( | ||||
|         api_models::refunds::RefundListResponse { | ||||
|             size: data.len(), | ||||
| @ -668,6 +673,25 @@ pub async fn refund_list( | ||||
|     )) | ||||
| } | ||||
|  | ||||
| #[instrument(skip_all)] | ||||
| #[cfg(feature = "olap")] | ||||
| pub async fn refund_filter_list( | ||||
|     db: &dyn db::StorageInterface, | ||||
|     merchant_account: domain::MerchantAccount, | ||||
|     req: api_models::refunds::TimeRange, | ||||
| ) -> RouterResponse<api_models::refunds::RefundListMetaData> { | ||||
|     let filter_list = db | ||||
|         .filter_refund_by_meta_constraints( | ||||
|             &merchant_account.merchant_id, | ||||
|             &req, | ||||
|             merchant_account.storage_scheme, | ||||
|         ) | ||||
|         .await | ||||
|         .to_not_found_response(errors::ApiErrorResponse::RefundNotFound)?; | ||||
|  | ||||
|     Ok(services::ApplicationResponse::Json(filter_list)) | ||||
| } | ||||
|  | ||||
| impl ForeignFrom<storage::Refund> for api::RefundResponse { | ||||
|     fn foreign_from(refund: storage::Refund) -> Self { | ||||
|         let refund = refund; | ||||
|  | ||||
| @ -10,6 +10,11 @@ use crate::{ | ||||
|     utils::{self, OptionExt}, | ||||
| }; | ||||
|  | ||||
| // Limit constraints for refunds list flow | ||||
| pub const LOWER_LIMIT: i64 = 1; | ||||
| pub const UPPER_LIMIT: i64 = 100; | ||||
| pub const DEFAULT_LIMIT: i64 = 10; | ||||
|  | ||||
| #[derive(Debug, thiserror::Error)] | ||||
| pub enum RefundValidationError { | ||||
|     #[error("The payment attempt was not successful")] | ||||
| @ -125,7 +130,7 @@ pub async fn validate_uniqueness_of_refund_id_against_merchant_id( | ||||
| pub fn validate_refund_list(limit: Option<i64>) -> CustomResult<i64, errors::ApiErrorResponse> { | ||||
|     match limit { | ||||
|         Some(limit_val) => { | ||||
|             if !(1..=100).contains(&limit_val) { | ||||
|             if !(LOWER_LIMIT..=UPPER_LIMIT).contains(&limit_val) { | ||||
|                 Err(errors::ApiErrorResponse::InvalidRequestData { | ||||
|                     message: "limit should be in between 1 and 100".to_string(), | ||||
|                 } | ||||
| @ -134,7 +139,7 @@ pub fn validate_refund_list(limit: Option<i64>) -> CustomResult<i64, errors::Api | ||||
|                 Ok(limit_val) | ||||
|             } | ||||
|         } | ||||
|         None => Ok(10), | ||||
|         None => Ok(DEFAULT_LIMIT), | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -1,11 +1,19 @@ | ||||
| #[cfg(feature = "olap")] | ||||
| use std::collections::HashSet; | ||||
|  | ||||
| use storage_models::{errors::DatabaseError, refund::RefundUpdateInternal}; | ||||
|  | ||||
| use super::MockDb; | ||||
| #[cfg(feature = "olap")] | ||||
| use crate::types::transformers::ForeignInto; | ||||
| use crate::{ | ||||
|     core::errors::{self, CustomResult}, | ||||
|     types::storage::{self as storage_types, enums}, | ||||
| }; | ||||
|  | ||||
| #[cfg(feature = "olap")] | ||||
| const MAX_LIMIT: usize = 100; | ||||
|  | ||||
| #[async_trait::async_trait] | ||||
| pub trait RefundInterface { | ||||
|     async fn find_refund_by_internal_reference_id_merchant_id( | ||||
| @ -64,7 +72,16 @@ pub trait RefundInterface { | ||||
|         refund_details: &api_models::refunds::RefundListRequest, | ||||
|         storage_scheme: enums::MerchantStorageScheme, | ||||
|         limit: i64, | ||||
|         offset: i64, | ||||
|     ) -> CustomResult<Vec<storage_models::refund::Refund>, errors::StorageError>; | ||||
|  | ||||
|     #[cfg(feature = "olap")] | ||||
|     async fn filter_refund_by_meta_constraints( | ||||
|         &self, | ||||
|         merchant_id: &str, | ||||
|         refund_details: &api_models::refunds::TimeRange, | ||||
|         storage_scheme: enums::MerchantStorageScheme, | ||||
|     ) -> CustomResult<api_models::refunds::RefundListMetaData, errors::StorageError>; | ||||
| } | ||||
|  | ||||
| #[cfg(not(feature = "kv_store"))] | ||||
| @ -189,6 +206,7 @@ mod storage { | ||||
|             refund_details: &api_models::refunds::RefundListRequest, | ||||
|             _storage_scheme: enums::MerchantStorageScheme, | ||||
|             limit: i64, | ||||
|             offset: i64, | ||||
|         ) -> CustomResult<Vec<storage_models::refund::Refund>, errors::StorageError> { | ||||
|             let conn = connection::pg_connection_read(self).await?; | ||||
|             <storage_models::refund::Refund as storage_types::RefundDbExt>::filter_by_constraints( | ||||
| @ -196,6 +214,25 @@ mod storage { | ||||
|                 merchant_id, | ||||
|                 refund_details, | ||||
|                 limit, | ||||
|                 offset, | ||||
|             ) | ||||
|             .await | ||||
|             .map_err(Into::into) | ||||
|             .into_report() | ||||
|         } | ||||
|  | ||||
|         #[cfg(feature = "olap")] | ||||
|         async fn filter_refund_by_meta_constraints( | ||||
|             &self, | ||||
|             merchant_id: &str, | ||||
|             refund_details: &api_models::refunds::TimeRange, | ||||
|             _storage_scheme: enums::MerchantStorageScheme, | ||||
|         ) -> CustomResult<api_models::refunds::RefundListMetaData, errors::StorageError> { | ||||
|             let conn = connection::pg_connection_read(self).await?; | ||||
|             <storage_models::refund::Refund as storage_types::RefundDbExt>::filter_by_meta_constraints( | ||||
|                 &conn, | ||||
|                 merchant_id, | ||||
|                 refund_details, | ||||
|             ) | ||||
|             .await | ||||
|             .map_err(Into::into) | ||||
| @ -584,11 +621,32 @@ mod storage { | ||||
|             refund_details: &api_models::refunds::RefundListRequest, | ||||
|             storage_scheme: enums::MerchantStorageScheme, | ||||
|             limit: i64, | ||||
|             offset: i64, | ||||
|         ) -> CustomResult<Vec<storage_models::refund::Refund>, errors::StorageError> { | ||||
|             match storage_scheme { | ||||
|                 enums::MerchantStorageScheme::PostgresOnly => { | ||||
|                     let conn = connection::pg_connection_read(self).await?; | ||||
|                     <storage_models::refund::Refund as storage_types::RefundDbExt>::filter_by_constraints(&conn, merchant_id, refund_details, limit) | ||||
|                     <storage_models::refund::Refund as storage_types::RefundDbExt>::filter_by_constraints(&conn, merchant_id, refund_details, limit, offset) | ||||
|                         .await | ||||
|                         .map_err(Into::into) | ||||
|                         .into_report() | ||||
|                 } | ||||
|  | ||||
|                 enums::MerchantStorageScheme::RedisKv => Err(errors::StorageError::KVError.into()), | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         #[cfg(feature = "olap")] | ||||
|         async fn filter_refund_by_meta_constraints( | ||||
|             &self, | ||||
|             merchant_id: &str, | ||||
|             refund_details: &api_models::refunds::TimeRange, | ||||
|             storage_scheme: enums::MerchantStorageScheme, | ||||
|         ) -> CustomResult<api_models::refunds::RefundListMetaData, errors::StorageError> { | ||||
|             match storage_scheme { | ||||
|                 enums::MerchantStorageScheme::PostgresOnly => { | ||||
|                     let conn = connection::pg_connection_read(self).await?; | ||||
|                     <storage_models::refund::Refund as storage_types::RefundDbExt>::filter_by_meta_constraints(&conn, merchant_id, refund_details) | ||||
|                         .await | ||||
|                         .map_err(Into::into) | ||||
|                         .into_report() | ||||
| @ -760,14 +818,64 @@ impl RefundInterface for MockDb { | ||||
|         _refund_details: &api_models::refunds::RefundListRequest, | ||||
|         _storage_scheme: enums::MerchantStorageScheme, | ||||
|         limit: i64, | ||||
|         offset: i64, | ||||
|     ) -> CustomResult<Vec<storage_models::refund::Refund>, errors::StorageError> { | ||||
|         let refunds = self.refunds.lock().await; | ||||
|  | ||||
|         Ok(refunds | ||||
|         Ok(self | ||||
|             .refunds | ||||
|             .lock() | ||||
|             .await | ||||
|             .iter() | ||||
|             .filter(|refund| refund.merchant_id == merchant_id) | ||||
|             .take(usize::try_from(limit).unwrap_or(usize::MAX)) | ||||
|             .skip(usize::try_from(offset).unwrap_or_default()) | ||||
|             .take(usize::try_from(limit).unwrap_or(MAX_LIMIT)) | ||||
|             .cloned() | ||||
|             .collect::<Vec<_>>()) | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "olap")] | ||||
|     async fn filter_refund_by_meta_constraints( | ||||
|         &self, | ||||
|         _merchant_id: &str, | ||||
|         refund_details: &api_models::refunds::TimeRange, | ||||
|         _storage_scheme: enums::MerchantStorageScheme, | ||||
|     ) -> CustomResult<api_models::refunds::RefundListMetaData, errors::StorageError> { | ||||
|         let refunds = self.refunds.lock().await; | ||||
|  | ||||
|         let start_time = refund_details.start_time; | ||||
|         let end_time = refund_details | ||||
|             .end_time | ||||
|             .unwrap_or_else(common_utils::date_time::now); | ||||
|  | ||||
|         let filtered_refunds = refunds | ||||
|             .iter() | ||||
|             .filter(|refund| refund.created_at >= start_time && refund.created_at <= end_time) | ||||
|             .cloned() | ||||
|             .collect::<Vec<storage_models::refund::Refund>>(); | ||||
|  | ||||
|         let mut refund_meta_data = api_models::refunds::RefundListMetaData { | ||||
|             connector: vec![], | ||||
|             currency: vec![], | ||||
|             status: vec![], | ||||
|         }; | ||||
|  | ||||
|         let mut unique_connectors = HashSet::new(); | ||||
|         let mut unique_currencies = HashSet::new(); | ||||
|         let mut unique_statuses = HashSet::new(); | ||||
|  | ||||
|         for refund in filtered_refunds.into_iter() { | ||||
|             unique_connectors.insert(refund.connector); | ||||
|  | ||||
|             let currency: api_models::enums::Currency = refund.currency.foreign_into(); | ||||
|             unique_currencies.insert(currency); | ||||
|  | ||||
|             let status: api_models::enums::RefundStatus = refund.refund_status.foreign_into(); | ||||
|             unique_statuses.insert(status); | ||||
|         } | ||||
|  | ||||
|         refund_meta_data.connector = unique_connectors.into_iter().collect(); | ||||
|         refund_meta_data.currency = unique_currencies.into_iter().collect(); | ||||
|         refund_meta_data.status = unique_statuses.into_iter().collect(); | ||||
|  | ||||
|         Ok(refund_meta_data) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -245,6 +245,7 @@ Never share your secret api keys. Keep them guarded and secure. | ||||
|         api_models::payments::RedirectResponse, | ||||
|         api_models::refunds::RefundListRequest, | ||||
|         api_models::refunds::RefundListResponse, | ||||
|         api_models::refunds::TimeRange, | ||||
|         api_models::mandates::MandateRevokedResponse, | ||||
|         api_models::mandates::MandateResponse, | ||||
|         api_models::mandates::MandateCardDetails, | ||||
|  | ||||
| @ -243,7 +243,9 @@ impl Refunds { | ||||
|  | ||||
|         #[cfg(feature = "olap")] | ||||
|         { | ||||
|             route = route.service(web::resource("/list").route(web::get().to(refunds_list))); | ||||
|             route = route | ||||
|                 .service(web::resource("/list").route(web::post().to(refunds_list))) | ||||
|                 .service(web::resource("/filter").route(web::post().to(refunds_filter_list))); | ||||
|         } | ||||
|         #[cfg(feature = "oltp")] | ||||
|         { | ||||
|  | ||||
| @ -179,17 +179,9 @@ pub async fn refunds_update( | ||||
| /// | ||||
| /// To list the refunds associated with a payment_id or with the merchant, if payment_id is not provided | ||||
| #[utoipa::path( | ||||
|     get, | ||||
|     post, | ||||
|     path = "/refunds/list", | ||||
|     params( | ||||
|         ("payment_id" = String, Query, description = "The identifier for the payment"), | ||||
|         ("limit" = i64, Query, description = "Limit on the number of objects to return"), | ||||
|         ("created" = PrimitiveDateTime, Query, description = "The time at which refund is created"), | ||||
|         ("created_lt" = PrimitiveDateTime, Query, description = "Time less than the refund created time"), | ||||
|         ("created_gt" = PrimitiveDateTime, Query, description = "Time greater than the refund created time"), | ||||
|         ("created_lte" = PrimitiveDateTime, Query, description = "Time less than or equals to the refund created time"), | ||||
|         ("created_gte" = PrimitiveDateTime, Query, description = "Time greater than or equals to the refund created time") | ||||
|     ), | ||||
|     request_body=RefundListRequest, | ||||
|     responses( | ||||
|         (status = 200, description = "List of refunds", body = RefundListResponse), | ||||
|     ), | ||||
| @ -199,11 +191,10 @@ pub async fn refunds_update( | ||||
| )] | ||||
| #[instrument(skip_all, fields(flow = ?Flow::RefundsList))] | ||||
| #[cfg(feature = "olap")] | ||||
| // #[get("/list")] | ||||
| pub async fn refunds_list( | ||||
|     state: web::Data<AppState>, | ||||
|     req: HttpRequest, | ||||
|     payload: web::Query<api_models::refunds::RefundListRequest>, | ||||
|     payload: web::Json<api_models::refunds::RefundListRequest>, | ||||
| ) -> HttpResponse { | ||||
|     let flow = Flow::RefundsList; | ||||
|     api::server_wrap( | ||||
| @ -216,3 +207,36 @@ pub async fn refunds_list( | ||||
|     ) | ||||
|     .await | ||||
| } | ||||
|  | ||||
| /// Refunds - Filter | ||||
| /// | ||||
| /// To list the refunds filters associated with list of connectors, currencies and payment statuses | ||||
| #[utoipa::path( | ||||
|     post, | ||||
|     path = "/refunds/filter", | ||||
|     request_body=TimeRange, | ||||
|     responses( | ||||
|         (status = 200, description = "List of filters", body = RefundListMetaData), | ||||
|     ), | ||||
|     tag = "Refunds", | ||||
|     operation_id = "List all filters for Refunds", | ||||
|     security(("api_key" = [])) | ||||
| )] | ||||
| #[instrument(skip_all, fields(flow = ?Flow::RefundsList))] | ||||
| #[cfg(feature = "olap")] | ||||
| pub async fn refunds_filter_list( | ||||
|     state: web::Data<AppState>, | ||||
|     req: HttpRequest, | ||||
|     payload: web::Json<api_models::refunds::TimeRange>, | ||||
| ) -> HttpResponse { | ||||
|     let flow = Flow::RefundsList; | ||||
|     api::server_wrap( | ||||
|         flow, | ||||
|         state.get_ref(), | ||||
|         &req, | ||||
|         payload.into_inner(), | ||||
|         |state, auth, req| refund_filter_list(&*state.store, auth.merchant_account, req), | ||||
|         &auth::ApiKeyAuth, | ||||
|     ) | ||||
|     .await | ||||
| } | ||||
|  | ||||
| @ -5,9 +5,13 @@ use error_stack::{IntoReport, ResultExt}; | ||||
| pub use storage_models::refund::{ | ||||
|     Refund, RefundCoreWorkflow, RefundNew, RefundUpdate, RefundUpdateInternal, | ||||
| }; | ||||
| use storage_models::{errors, schema::refund::dsl}; | ||||
| use storage_models::{ | ||||
|     enums::{Currency, RefundStatus}, | ||||
|     errors, | ||||
|     schema::refund::dsl, | ||||
| }; | ||||
|  | ||||
| use crate::{connection::PgPooledConn, logger}; | ||||
| use crate::{connection::PgPooledConn, logger, types::transformers::ForeignInto}; | ||||
|  | ||||
| #[cfg(feature = "kv_store")] | ||||
| impl crate::utils::storage_partitioning::KvStorePartition for Refund {} | ||||
| @ -19,7 +23,14 @@ pub trait RefundDbExt: Sized { | ||||
|         merchant_id: &str, | ||||
|         refund_list_details: &api_models::refunds::RefundListRequest, | ||||
|         limit: i64, | ||||
|         offset: i64, | ||||
|     ) -> CustomResult<Vec<Self>, errors::DatabaseError>; | ||||
|  | ||||
|     async fn filter_by_meta_constraints( | ||||
|         conn: &PgPooledConn, | ||||
|         merchant_id: &str, | ||||
|         refund_list_details: &api_models::refunds::TimeRange, | ||||
|     ) -> CustomResult<api_models::refunds::RefundListMetaData, errors::DatabaseError>; | ||||
| } | ||||
|  | ||||
| #[async_trait::async_trait] | ||||
| @ -29,6 +40,7 @@ impl RefundDbExt for Refund { | ||||
|         merchant_id: &str, | ||||
|         refund_list_details: &api_models::refunds::RefundListRequest, | ||||
|         limit: i64, | ||||
|         offset: i64, | ||||
|     ) -> CustomResult<Vec<Self>, errors::DatabaseError> { | ||||
|         let mut filter = <Self as HasTable>::table() | ||||
|             .filter(dsl::merchant_id.eq(merchant_id.to_owned())) | ||||
| @ -40,24 +52,36 @@ impl RefundDbExt for Refund { | ||||
|                 filter = filter.filter(dsl::payment_id.eq(pid.to_owned())); | ||||
|             } | ||||
|             None => { | ||||
|                 filter = filter.limit(limit); | ||||
|                 filter = filter.limit(limit).offset(offset); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         if let Some(created) = refund_list_details.created { | ||||
|             filter = filter.filter(dsl::created_at.eq(created)); | ||||
|         if let Some(time_range) = refund_list_details.time_range { | ||||
|             filter = filter.filter(dsl::created_at.ge(time_range.start_time)); | ||||
|  | ||||
|             if let Some(end_time) = time_range.end_time { | ||||
|                 filter = filter.filter(dsl::created_at.le(end_time)); | ||||
|             } | ||||
|         } | ||||
|         if let Some(created_lt) = refund_list_details.created_lt { | ||||
|             filter = filter.filter(dsl::created_at.lt(created_lt)); | ||||
|  | ||||
|         if let Some(connector) = refund_list_details.clone().connector { | ||||
|             filter = filter.filter(dsl::connector.eq_any(connector)); | ||||
|         } | ||||
|         if let Some(created_gt) = refund_list_details.created_gt { | ||||
|             filter = filter.filter(dsl::created_at.gt(created_gt)); | ||||
|  | ||||
|         if let Some(filter_currency) = &refund_list_details.currency { | ||||
|             let currency: Vec<Currency> = filter_currency | ||||
|                 .iter() | ||||
|                 .map(|currency| (*currency).foreign_into()) | ||||
|                 .collect(); | ||||
|             filter = filter.filter(dsl::currency.eq_any(currency)); | ||||
|         } | ||||
|         if let Some(created_lte) = refund_list_details.created_lte { | ||||
|             filter = filter.filter(dsl::created_at.le(created_lte)); | ||||
|         } | ||||
|         if let Some(created_gte) = refund_list_details.created_gte { | ||||
|             filter = filter.filter(dsl::created_at.gt(created_gte)); | ||||
|  | ||||
|         if let Some(filter_refund_status) = &refund_list_details.refund_status { | ||||
|             let refund_status: Vec<RefundStatus> = filter_refund_status | ||||
|                 .iter() | ||||
|                 .map(|refund_status| (*refund_status).foreign_into()) | ||||
|                 .collect(); | ||||
|             filter = filter.filter(dsl::refund_status.eq_any(refund_status)); | ||||
|         } | ||||
|  | ||||
|         logger::debug!(query = %diesel::debug_query::<diesel::pg::Pg, _>(&filter).to_string()); | ||||
| @ -69,4 +93,68 @@ impl RefundDbExt for Refund { | ||||
|             .change_context(errors::DatabaseError::NotFound) | ||||
|             .attach_printable_lazy(|| "Error filtering records by predicate") | ||||
|     } | ||||
|  | ||||
|     async fn filter_by_meta_constraints( | ||||
|         conn: &PgPooledConn, | ||||
|         merchant_id: &str, | ||||
|         refund_list_details: &api_models::refunds::TimeRange, | ||||
|     ) -> CustomResult<api_models::refunds::RefundListMetaData, errors::DatabaseError> { | ||||
|         let start_time = refund_list_details.start_time; | ||||
|  | ||||
|         let end_time = refund_list_details | ||||
|             .end_time | ||||
|             .unwrap_or_else(common_utils::date_time::now); | ||||
|  | ||||
|         let filter = <Self as HasTable>::table() | ||||
|             .filter(dsl::merchant_id.eq(merchant_id.to_owned())) | ||||
|             .order(dsl::modified_at.desc()) | ||||
|             .filter(dsl::created_at.ge(start_time)) | ||||
|             .filter(dsl::created_at.le(end_time)); | ||||
|  | ||||
|         let filter_connector: Vec<String> = filter | ||||
|             .clone() | ||||
|             .select(dsl::connector) | ||||
|             .distinct() | ||||
|             .order_by(dsl::connector.asc()) | ||||
|             .get_results_async(conn) | ||||
|             .await | ||||
|             .into_report() | ||||
|             .change_context(errors::DatabaseError::Others) | ||||
|             .attach_printable("Error filtering records by connector")?; | ||||
|  | ||||
|         let filter_currency: Vec<Currency> = filter | ||||
|             .clone() | ||||
|             .select(dsl::currency) | ||||
|             .distinct() | ||||
|             .order_by(dsl::currency.asc()) | ||||
|             .get_results_async(conn) | ||||
|             .await | ||||
|             .into_report() | ||||
|             .change_context(errors::DatabaseError::Others) | ||||
|             .attach_printable("Error filtering records by currency")?; | ||||
|  | ||||
|         let filter_status: Vec<RefundStatus> = filter | ||||
|             .select(dsl::refund_status) | ||||
|             .distinct() | ||||
|             .order_by(dsl::refund_status.asc()) | ||||
|             .get_results_async(conn) | ||||
|             .await | ||||
|             .into_report() | ||||
|             .change_context(errors::DatabaseError::Others) | ||||
|             .attach_printable("Error filtering records by refund status")?; | ||||
|  | ||||
|         let meta = api_models::refunds::RefundListMetaData { | ||||
|             connector: filter_connector, | ||||
|             currency: filter_currency | ||||
|                 .into_iter() | ||||
|                 .map(|curr| curr.foreign_into()) | ||||
|                 .collect(), | ||||
|             status: filter_status | ||||
|                 .into_iter() | ||||
|                 .map(|curr| curr.foreign_into()) | ||||
|                 .collect(), | ||||
|         }; | ||||
|  | ||||
|         Ok(meta) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -298,6 +298,12 @@ impl ForeignFrom<storage_enums::RefundStatus> for api_enums::RefundStatus { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl ForeignFrom<api_enums::RefundStatus> for storage_enums::RefundStatus { | ||||
|     fn foreign_from(status: api_enums::RefundStatus) -> Self { | ||||
|         frunk::labelled_convert_from(status) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl ForeignFrom<api_enums::CaptureMethod> for storage_enums::CaptureMethod { | ||||
|     fn foreign_from(capture_method: api_enums::CaptureMethod) -> Self { | ||||
|         frunk::labelled_convert_from(capture_method) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Apoorv Dixit
					Apoorv Dixit