mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 09:38:33 +08:00
feat(refunds_v2): Add refunds list flow in v2 apis (#7966)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@ -4,6 +4,7 @@ use api_models::{enums::Connector, refunds::RefundErrorDetails};
|
||||
use common_utils::{id_type, types as common_utils_types};
|
||||
use error_stack::{report, ResultExt};
|
||||
use hyperswitch_domain_models::{
|
||||
refunds::RefundListConstraints,
|
||||
router_data::{ErrorResponse, RouterData},
|
||||
router_data_v2::RefundFlowData,
|
||||
};
|
||||
@ -734,6 +735,56 @@ pub fn build_refund_update_for_rsync(
|
||||
}
|
||||
}
|
||||
|
||||
// ********************************************** Refund list **********************************************
|
||||
|
||||
/// If payment_id is provided, lists all the refunds associated with that particular payment_id
|
||||
/// If payment_id is not provided, lists the refunds associated with that particular merchant - to the limit specified,if no limits given, it is 10 by default
|
||||
#[instrument(skip_all)]
|
||||
#[cfg(feature = "olap")]
|
||||
pub async fn refund_list(
|
||||
state: SessionState,
|
||||
merchant_account: domain::MerchantAccount,
|
||||
profile: domain::Profile,
|
||||
req: refunds::RefundListRequest,
|
||||
) -> errors::RouterResponse<refunds::RefundListResponse> {
|
||||
let db = state.store;
|
||||
let limit = refunds_validator::validate_refund_list(req.limit)?;
|
||||
let offset = req.offset.unwrap_or_default();
|
||||
|
||||
let refund_list = db
|
||||
.filter_refund_by_constraints(
|
||||
merchant_account.get_id(),
|
||||
RefundListConstraints::from((req.clone(), profile.clone())),
|
||||
merchant_account.storage_scheme,
|
||||
limit,
|
||||
offset,
|
||||
)
|
||||
.await
|
||||
.to_not_found_response(errors::ApiErrorResponse::RefundNotFound)?;
|
||||
|
||||
let data: Vec<refunds::RefundResponse> = refund_list
|
||||
.into_iter()
|
||||
.map(refunds::RefundResponse::foreign_try_from)
|
||||
.collect::<Result<_, _>>()?;
|
||||
|
||||
let total_count = db
|
||||
.get_total_count_of_refunds(
|
||||
merchant_account.get_id(),
|
||||
RefundListConstraints::from((req, profile)),
|
||||
merchant_account.storage_scheme,
|
||||
)
|
||||
.await
|
||||
.to_not_found_response(errors::ApiErrorResponse::InternalServerError)?;
|
||||
|
||||
Ok(services::ApplicationResponse::Json(
|
||||
api_models::refunds::RefundListResponse {
|
||||
count: data.len(),
|
||||
total_count,
|
||||
data,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
// ********************************************** VALIDATIONS **********************************************
|
||||
|
||||
#[instrument(skip_all)]
|
||||
|
||||
@ -2844,6 +2844,26 @@ impl RefundInterface for KafkaStore {
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "refunds_v2"))]
|
||||
async fn filter_refund_by_constraints(
|
||||
&self,
|
||||
merchant_id: &id_type::MerchantId,
|
||||
refund_details: refunds::RefundListConstraints,
|
||||
storage_scheme: MerchantStorageScheme,
|
||||
limit: i64,
|
||||
offset: i64,
|
||||
) -> CustomResult<Vec<storage::Refund>, errors::StorageError> {
|
||||
self.diesel_store
|
||||
.filter_refund_by_constraints(
|
||||
merchant_id,
|
||||
refund_details,
|
||||
storage_scheme,
|
||||
limit,
|
||||
offset,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
any(feature = "v1", feature = "v2"),
|
||||
not(feature = "refunds_v2"),
|
||||
@ -2892,6 +2912,18 @@ impl RefundInterface for KafkaStore {
|
||||
.get_total_count_of_refunds(merchant_id, refund_details, storage_scheme)
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "refunds_v2"))]
|
||||
async fn get_total_count_of_refunds(
|
||||
&self,
|
||||
merchant_id: &id_type::MerchantId,
|
||||
refund_details: refunds::RefundListConstraints,
|
||||
storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<i64, errors::StorageError> {
|
||||
self.diesel_store
|
||||
.get_total_count_of_refunds(merchant_id, refund_details, storage_scheme)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
|
||||
@ -91,6 +91,16 @@ pub trait RefundInterface {
|
||||
offset: i64,
|
||||
) -> CustomResult<Vec<diesel_models::refund::Refund>, errors::StorageError>;
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "refunds_v2"))]
|
||||
async fn filter_refund_by_constraints(
|
||||
&self,
|
||||
merchant_id: &common_utils::id_type::MerchantId,
|
||||
refund_details: refunds::RefundListConstraints,
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
limit: i64,
|
||||
offset: i64,
|
||||
) -> CustomResult<Vec<diesel_models::refund::Refund>, errors::StorageError>;
|
||||
|
||||
#[cfg(all(
|
||||
any(feature = "v1", feature = "v2"),
|
||||
not(feature = "refunds_v2"),
|
||||
@ -127,6 +137,14 @@ pub trait RefundInterface {
|
||||
refund_details: &refunds::RefundListConstraints,
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> CustomResult<i64, errors::StorageError>;
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "refunds_v2"))]
|
||||
async fn get_total_count_of_refunds(
|
||||
&self,
|
||||
merchant_id: &common_utils::id_type::MerchantId,
|
||||
refund_details: refunds::RefundListConstraints,
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> CustomResult<i64, errors::StorageError>;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "kv_store"))]
|
||||
@ -925,6 +943,28 @@ mod storage {
|
||||
.map_err(|error| report!(errors::StorageError::from(error)))
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "refunds_v2"))]
|
||||
#[instrument(skip_all)]
|
||||
async fn filter_refund_by_constraints(
|
||||
&self,
|
||||
merchant_id: &common_utils::id_type::MerchantId,
|
||||
refund_details: refunds::RefundListConstraints,
|
||||
_storage_scheme: enums::MerchantStorageScheme,
|
||||
limit: i64,
|
||||
offset: i64,
|
||||
) -> CustomResult<Vec<diesel_models::refund::Refund>, errors::StorageError> {
|
||||
let conn = connection::pg_connection_read(self).await?;
|
||||
<diesel_models::refund::Refund as storage_types::RefundDbExt>::filter_by_constraints(
|
||||
&conn,
|
||||
merchant_id,
|
||||
refund_details,
|
||||
limit,
|
||||
offset,
|
||||
)
|
||||
.await
|
||||
.map_err(|error| report!(errors::StorageError::from(error)))
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
any(feature = "v1", feature = "v2"),
|
||||
not(feature = "refunds_v2"),
|
||||
@ -983,6 +1023,24 @@ mod storage {
|
||||
.await
|
||||
.map_err(|error| report!(errors::StorageError::from(error)))
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "refunds_v2"))]
|
||||
#[instrument(skip_all)]
|
||||
async fn get_total_count_of_refunds(
|
||||
&self,
|
||||
merchant_id: &common_utils::id_type::MerchantId,
|
||||
refund_details: refunds::RefundListConstraints,
|
||||
_storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> CustomResult<i64, errors::StorageError> {
|
||||
let conn = connection::pg_connection_read(self).await?;
|
||||
<diesel_models::refund::Refund as storage_types::RefundDbExt>::get_refunds_count(
|
||||
&conn,
|
||||
merchant_id,
|
||||
refund_details,
|
||||
)
|
||||
.await
|
||||
.map_err(|error| report!(errors::StorageError::from(error)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1369,6 +1427,115 @@ impl RefundInterface for MockDb {
|
||||
Ok(filtered_refunds)
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "refunds_v2", feature = "olap"))]
|
||||
async fn filter_refund_by_constraints(
|
||||
&self,
|
||||
merchant_id: &common_utils::id_type::MerchantId,
|
||||
refund_details: refunds::RefundListConstraints,
|
||||
_storage_scheme: enums::MerchantStorageScheme,
|
||||
limit: i64,
|
||||
offset: i64,
|
||||
) -> CustomResult<Vec<diesel_models::refund::Refund>, errors::StorageError> {
|
||||
let mut unique_connectors = HashSet::new();
|
||||
let mut unique_connector_ids = HashSet::new();
|
||||
let mut unique_currencies = HashSet::new();
|
||||
let mut unique_statuses = HashSet::new();
|
||||
|
||||
// Fill the hash sets with data from refund_details
|
||||
if let Some(connectors) = &refund_details.connector {
|
||||
connectors.iter().for_each(|connector| {
|
||||
unique_connectors.insert(connector);
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(connector_id_list) = &refund_details.connector_id_list {
|
||||
connector_id_list.iter().for_each(|unique_connector_id| {
|
||||
unique_connector_ids.insert(unique_connector_id);
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(currencies) = &refund_details.currency {
|
||||
currencies.iter().for_each(|currency| {
|
||||
unique_currencies.insert(currency);
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(refund_statuses) = &refund_details.refund_status {
|
||||
refund_statuses.iter().for_each(|refund_status| {
|
||||
unique_statuses.insert(refund_status);
|
||||
});
|
||||
}
|
||||
|
||||
let refunds = self.refunds.lock().await;
|
||||
let filtered_refunds = refunds
|
||||
.iter()
|
||||
.filter(|refund| refund.merchant_id == *merchant_id)
|
||||
.filter(|refund| {
|
||||
refund_details
|
||||
.payment_id
|
||||
.clone()
|
||||
.map_or(true, |id| id == refund.payment_id)
|
||||
})
|
||||
.filter(|refund| {
|
||||
refund_details
|
||||
.refund_id
|
||||
.clone()
|
||||
.map_or(true, |id| id == refund.id)
|
||||
})
|
||||
.filter(|refund| {
|
||||
refund
|
||||
.profile_id
|
||||
.as_ref()
|
||||
.is_some_and(|profile_id| profile_id == &refund_details.profile_id)
|
||||
})
|
||||
.filter(|refund| {
|
||||
refund.created_at
|
||||
>= refund_details.time_range.map_or(
|
||||
common_utils::date_time::now() - time::Duration::days(60),
|
||||
|range| range.start_time,
|
||||
)
|
||||
&& refund.created_at
|
||||
<= refund_details
|
||||
.time_range
|
||||
.map_or(common_utils::date_time::now(), |range| {
|
||||
range.end_time.unwrap_or_else(common_utils::date_time::now)
|
||||
})
|
||||
})
|
||||
.filter(|refund| {
|
||||
refund_details
|
||||
.amount_filter
|
||||
.as_ref()
|
||||
.map_or(true, |amount| {
|
||||
refund.refund_amount
|
||||
>= MinorUnit::new(amount.start_amount.unwrap_or(i64::MIN))
|
||||
&& refund.refund_amount
|
||||
<= MinorUnit::new(amount.end_amount.unwrap_or(i64::MAX))
|
||||
})
|
||||
})
|
||||
.filter(|refund| {
|
||||
unique_connectors.is_empty() || unique_connectors.contains(&refund.connector)
|
||||
})
|
||||
.filter(|refund| {
|
||||
unique_connector_ids.is_empty()
|
||||
|| refund
|
||||
.connector_id
|
||||
.as_ref()
|
||||
.is_some_and(|id| unique_connector_ids.contains(id))
|
||||
})
|
||||
.filter(|refund| {
|
||||
unique_currencies.is_empty() || unique_currencies.contains(&refund.currency)
|
||||
})
|
||||
.filter(|refund| {
|
||||
unique_statuses.is_empty() || unique_statuses.contains(&refund.refund_status)
|
||||
})
|
||||
.skip(usize::try_from(offset).unwrap_or_default())
|
||||
.take(usize::try_from(limit).unwrap_or(MAX_LIMIT))
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Ok(filtered_refunds)
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
any(feature = "v1", feature = "v2"),
|
||||
not(feature = "refunds_v2"),
|
||||
@ -1586,4 +1753,111 @@ impl RefundInterface for MockDb {
|
||||
|
||||
Ok(filtered_refunds_count)
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "refunds_v2", feature = "olap"))]
|
||||
async fn get_total_count_of_refunds(
|
||||
&self,
|
||||
merchant_id: &common_utils::id_type::MerchantId,
|
||||
refund_details: refunds::RefundListConstraints,
|
||||
_storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> CustomResult<i64, errors::StorageError> {
|
||||
let mut unique_connectors = HashSet::new();
|
||||
let mut unique_connector_ids = HashSet::new();
|
||||
let mut unique_currencies = HashSet::new();
|
||||
let mut unique_statuses = HashSet::new();
|
||||
|
||||
// Fill the hash sets with data from refund_details
|
||||
if let Some(connectors) = &refund_details.connector {
|
||||
connectors.iter().for_each(|connector| {
|
||||
unique_connectors.insert(connector);
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(connector_id_list) = &refund_details.connector_id_list {
|
||||
connector_id_list.iter().for_each(|unique_connector_id| {
|
||||
unique_connector_ids.insert(unique_connector_id);
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(currencies) = &refund_details.currency {
|
||||
currencies.iter().for_each(|currency| {
|
||||
unique_currencies.insert(currency);
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(refund_statuses) = &refund_details.refund_status {
|
||||
refund_statuses.iter().for_each(|refund_status| {
|
||||
unique_statuses.insert(refund_status);
|
||||
});
|
||||
}
|
||||
|
||||
let refunds = self.refunds.lock().await;
|
||||
let filtered_refunds = refunds
|
||||
.iter()
|
||||
.filter(|refund| refund.merchant_id == *merchant_id)
|
||||
.filter(|refund| {
|
||||
refund_details
|
||||
.payment_id
|
||||
.clone()
|
||||
.map_or(true, |id| id == refund.payment_id)
|
||||
})
|
||||
.filter(|refund| {
|
||||
refund_details
|
||||
.refund_id
|
||||
.clone()
|
||||
.map_or(true, |id| id == refund.id)
|
||||
})
|
||||
.filter(|refund| {
|
||||
refund
|
||||
.profile_id
|
||||
.as_ref()
|
||||
.is_some_and(|profile_id| profile_id == &refund_details.profile_id)
|
||||
})
|
||||
.filter(|refund| {
|
||||
refund.created_at
|
||||
>= refund_details.time_range.map_or(
|
||||
common_utils::date_time::now() - time::Duration::days(60),
|
||||
|range| range.start_time,
|
||||
)
|
||||
&& refund.created_at
|
||||
<= refund_details
|
||||
.time_range
|
||||
.map_or(common_utils::date_time::now(), |range| {
|
||||
range.end_time.unwrap_or_else(common_utils::date_time::now)
|
||||
})
|
||||
})
|
||||
.filter(|refund| {
|
||||
refund_details
|
||||
.amount_filter
|
||||
.as_ref()
|
||||
.map_or(true, |amount| {
|
||||
refund.refund_amount
|
||||
>= MinorUnit::new(amount.start_amount.unwrap_or(i64::MIN))
|
||||
&& refund.refund_amount
|
||||
<= MinorUnit::new(amount.end_amount.unwrap_or(i64::MAX))
|
||||
})
|
||||
})
|
||||
.filter(|refund| {
|
||||
unique_connectors.is_empty() || unique_connectors.contains(&refund.connector)
|
||||
})
|
||||
.filter(|refund| {
|
||||
unique_connector_ids.is_empty()
|
||||
|| refund
|
||||
.connector_id
|
||||
.as_ref()
|
||||
.is_some_and(|id| unique_connector_ids.contains(id))
|
||||
})
|
||||
.filter(|refund| {
|
||||
unique_currencies.is_empty() || unique_currencies.contains(&refund.currency)
|
||||
})
|
||||
.filter(|refund| {
|
||||
unique_statuses.is_empty() || unique_statuses.contains(&refund.refund_status)
|
||||
})
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let filtered_refunds_count = filtered_refunds.len().try_into().unwrap_or_default();
|
||||
|
||||
Ok(filtered_refunds_count)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1169,14 +1169,26 @@ impl Refunds {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "refunds_v2", feature = "oltp"))]
|
||||
#[cfg(all(
|
||||
feature = "v2",
|
||||
feature = "refunds_v2",
|
||||
any(feature = "olap", feature = "oltp")
|
||||
))]
|
||||
impl Refunds {
|
||||
pub fn server(state: AppState) -> Scope {
|
||||
let mut route = web::scope("/v2/refunds").app_data(web::Data::new(state));
|
||||
|
||||
route = route
|
||||
.service(web::resource("").route(web::post().to(refunds::refunds_create)))
|
||||
.service(web::resource("/{id}").route(web::get().to(refunds::refunds_retrieve)));
|
||||
#[cfg(feature = "olap")]
|
||||
{
|
||||
route =
|
||||
route.service(web::resource("/list").route(web::get().to(refunds::refunds_list)));
|
||||
}
|
||||
#[cfg(feature = "oltp")]
|
||||
{
|
||||
route = route
|
||||
.service(web::resource("").route(web::post().to(refunds::refunds_create)))
|
||||
.service(web::resource("/{id}").route(web::get().to(refunds::refunds_retrieve)));
|
||||
}
|
||||
|
||||
route
|
||||
}
|
||||
|
||||
@ -375,6 +375,37 @@ pub async fn refunds_list(
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "refunds_v2", feature = "olap"))]
|
||||
#[instrument(skip_all, fields(flow = ?Flow::RefundsList))]
|
||||
pub async fn refunds_list(
|
||||
state: web::Data<AppState>,
|
||||
req: HttpRequest,
|
||||
payload: web::Json<api_models::refunds::RefundListRequest>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::RefundsList;
|
||||
Box::pin(api::server_wrap(
|
||||
flow,
|
||||
state,
|
||||
&req,
|
||||
payload.into_inner(),
|
||||
|state, auth: auth::AuthenticationData, req, _| {
|
||||
refund_list(state, auth.merchant_account, auth.profile, req)
|
||||
},
|
||||
auth::auth_type(
|
||||
&auth::V2ApiKeyAuth {
|
||||
is_connected_allowed: false,
|
||||
is_platform_allowed: false,
|
||||
},
|
||||
&auth::JWTAuth {
|
||||
permission: Permission::MerchantRefundRead,
|
||||
},
|
||||
req.headers(),
|
||||
),
|
||||
api_locking::LockAction::NotApplicable,
|
||||
))
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
any(feature = "v1", feature = "v2"),
|
||||
not(feature = "refunds_v2"),
|
||||
|
||||
@ -3,8 +3,8 @@ pub use api_models::refunds::RefundRequest;
|
||||
#[cfg(all(feature = "v2", feature = "refunds_v2"))]
|
||||
pub use api_models::refunds::RefundsCreateRequest;
|
||||
pub use api_models::refunds::{
|
||||
RefundResponse, RefundStatus, RefundType, RefundUpdateRequest, RefundsRetrieveBody,
|
||||
RefundsRetrieveRequest,
|
||||
RefundListRequest, RefundListResponse, RefundResponse, RefundStatus, RefundType,
|
||||
RefundUpdateRequest, RefundsRetrieveBody, RefundsRetrieveRequest,
|
||||
};
|
||||
pub use hyperswitch_domain_models::router_flow_types::refunds::{Execute, RSync};
|
||||
pub use hyperswitch_interfaces::api::refunds::{Refund, RefundExecute, RefundSync};
|
||||
|
||||
@ -5,11 +5,14 @@ use diesel::{associations::HasTable, BoolExpressionMethods, ExpressionMethods, Q
|
||||
pub use diesel_models::refund::{
|
||||
Refund, RefundCoreWorkflow, RefundNew, RefundUpdate, RefundUpdateInternal,
|
||||
};
|
||||
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "refunds_v2")))]
|
||||
use diesel_models::schema::refund::dsl;
|
||||
#[cfg(all(feature = "v2", feature = "refunds_v2"))]
|
||||
use diesel_models::schema_v2::refund::dsl;
|
||||
use diesel_models::{
|
||||
enums::{Currency, RefundStatus},
|
||||
errors,
|
||||
query::generics::db_metrics,
|
||||
schema::refund::dsl,
|
||||
};
|
||||
use error_stack::ResultExt;
|
||||
use hyperswitch_domain_models::refunds;
|
||||
@ -27,6 +30,15 @@ pub trait RefundDbExt: Sized {
|
||||
offset: i64,
|
||||
) -> CustomResult<Vec<Self>, errors::DatabaseError>;
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "refunds_v2"))]
|
||||
async fn filter_by_constraints(
|
||||
conn: &PgPooledConn,
|
||||
merchant_id: &common_utils::id_type::MerchantId,
|
||||
refund_list_details: refunds::RefundListConstraints,
|
||||
limit: i64,
|
||||
offset: i64,
|
||||
) -> CustomResult<Vec<Self>, errors::DatabaseError>;
|
||||
|
||||
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "refunds_v2")))]
|
||||
async fn filter_by_meta_constraints(
|
||||
conn: &PgPooledConn,
|
||||
@ -48,6 +60,13 @@ pub trait RefundDbExt: Sized {
|
||||
profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
|
||||
time_range: &common_utils::types::TimeRange,
|
||||
) -> CustomResult<Vec<(RefundStatus, i64)>, errors::DatabaseError>;
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "refunds_v2"))]
|
||||
async fn get_refunds_count(
|
||||
conn: &PgPooledConn,
|
||||
merchant_id: &common_utils::id_type::MerchantId,
|
||||
refund_list_details: refunds::RefundListConstraints,
|
||||
) -> CustomResult<i64, errors::DatabaseError>;
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
@ -164,6 +183,82 @@ impl RefundDbExt for Refund {
|
||||
.attach_printable_lazy(|| "Error filtering records by predicate")
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "refunds_v2"))]
|
||||
async fn filter_by_constraints(
|
||||
conn: &PgPooledConn,
|
||||
merchant_id: &common_utils::id_type::MerchantId,
|
||||
refund_list_details: refunds::RefundListConstraints,
|
||||
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()))
|
||||
.order(dsl::modified_at.desc())
|
||||
.into_boxed();
|
||||
|
||||
if let Some(payment_id) = &refund_list_details.payment_id {
|
||||
filter = filter.filter(dsl::payment_id.eq(payment_id.to_owned()));
|
||||
}
|
||||
|
||||
if let Some(refund_id) = &refund_list_details.refund_id {
|
||||
filter = filter.filter(dsl::id.eq(refund_id.to_owned()));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
filter = match refund_list_details.amount_filter {
|
||||
Some(AmountFilter {
|
||||
start_amount: Some(start),
|
||||
end_amount: Some(end),
|
||||
}) => filter.filter(dsl::refund_amount.between(start, end)),
|
||||
Some(AmountFilter {
|
||||
start_amount: Some(start),
|
||||
end_amount: None,
|
||||
}) => filter.filter(dsl::refund_amount.ge(start)),
|
||||
Some(AmountFilter {
|
||||
start_amount: None,
|
||||
end_amount: Some(end),
|
||||
}) => filter.filter(dsl::refund_amount.le(end)),
|
||||
_ => filter,
|
||||
};
|
||||
|
||||
if let Some(connector) = refund_list_details.connector {
|
||||
filter = filter.filter(dsl::connector.eq_any(connector));
|
||||
}
|
||||
|
||||
if let Some(connector_id_list) = refund_list_details.connector_id_list {
|
||||
filter = filter.filter(dsl::connector_id.eq_any(connector_id_list));
|
||||
}
|
||||
|
||||
if let Some(filter_currency) = refund_list_details.currency {
|
||||
filter = filter.filter(dsl::currency.eq_any(filter_currency));
|
||||
}
|
||||
|
||||
if let Some(filter_refund_status) = refund_list_details.refund_status {
|
||||
filter = filter.filter(dsl::refund_status.eq_any(filter_refund_status));
|
||||
}
|
||||
|
||||
filter = filter.limit(limit).offset(offset);
|
||||
|
||||
logger::debug!(query = %diesel::debug_query::<diesel::pg::Pg, _>(&filter).to_string());
|
||||
|
||||
db_metrics::track_database_call::<<Self as HasTable>::Table, _, _>(
|
||||
filter.get_results_async(conn),
|
||||
db_metrics::DatabaseOperation::Filter,
|
||||
)
|
||||
.await
|
||||
.change_context(errors::DatabaseError::NotFound)
|
||||
.attach_printable_lazy(|| "Error filtering records by predicate")
|
||||
|
||||
// todo!()
|
||||
}
|
||||
|
||||
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "refunds_v2")))]
|
||||
async fn filter_by_meta_constraints(
|
||||
conn: &PgPooledConn,
|
||||
@ -309,6 +404,74 @@ impl RefundDbExt for Refund {
|
||||
.attach_printable_lazy(|| "Error filtering count of refunds")
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "refunds_v2"))]
|
||||
async fn get_refunds_count(
|
||||
conn: &PgPooledConn,
|
||||
merchant_id: &common_utils::id_type::MerchantId,
|
||||
refund_list_details: refunds::RefundListConstraints,
|
||||
) -> CustomResult<i64, errors::DatabaseError> {
|
||||
let mut filter = <Self as HasTable>::table()
|
||||
.count()
|
||||
.filter(dsl::merchant_id.eq(merchant_id.to_owned()))
|
||||
.into_boxed();
|
||||
|
||||
if let Some(payment_id) = &refund_list_details.payment_id {
|
||||
filter = filter.filter(dsl::payment_id.eq(payment_id.to_owned()));
|
||||
}
|
||||
|
||||
if let Some(refund_id) = &refund_list_details.refund_id {
|
||||
filter = filter.filter(dsl::id.eq(refund_id.to_owned()));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
filter = match refund_list_details.amount_filter {
|
||||
Some(AmountFilter {
|
||||
start_amount: Some(start),
|
||||
end_amount: Some(end),
|
||||
}) => filter.filter(dsl::refund_amount.between(start, end)),
|
||||
Some(AmountFilter {
|
||||
start_amount: Some(start),
|
||||
end_amount: None,
|
||||
}) => filter.filter(dsl::refund_amount.ge(start)),
|
||||
Some(AmountFilter {
|
||||
start_amount: None,
|
||||
end_amount: Some(end),
|
||||
}) => filter.filter(dsl::refund_amount.le(end)),
|
||||
_ => filter,
|
||||
};
|
||||
|
||||
if let Some(connector) = refund_list_details.connector {
|
||||
filter = filter.filter(dsl::connector.eq_any(connector));
|
||||
}
|
||||
|
||||
if let Some(connector_id_list) = refund_list_details.connector_id_list {
|
||||
filter = filter.filter(dsl::connector_id.eq_any(connector_id_list));
|
||||
}
|
||||
|
||||
if let Some(filter_currency) = refund_list_details.currency {
|
||||
filter = filter.filter(dsl::currency.eq_any(filter_currency));
|
||||
}
|
||||
|
||||
if let Some(filter_refund_status) = refund_list_details.refund_status {
|
||||
filter = filter.filter(dsl::refund_status.eq_any(filter_refund_status));
|
||||
}
|
||||
|
||||
logger::debug!(query = %diesel::debug_query::<diesel::pg::Pg, _>(&filter).to_string());
|
||||
|
||||
filter
|
||||
.get_result_async::<i64>(conn)
|
||||
.await
|
||||
.change_context(errors::DatabaseError::NotFound)
|
||||
.attach_printable_lazy(|| "Error filtering count of refunds")
|
||||
}
|
||||
|
||||
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "refunds_v2")))]
|
||||
async fn get_refund_status_with_count(
|
||||
conn: &PgPooledConn,
|
||||
|
||||
Reference in New Issue
Block a user