mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 12:15:40 +08:00
feat(refunds): Profile level refunds aggregate (#5931)
This commit is contained in:
@ -1098,11 +1098,17 @@ pub async fn get_filters_for_refunds(
|
|||||||
pub async fn get_aggregates_for_refunds(
|
pub async fn get_aggregates_for_refunds(
|
||||||
state: SessionState,
|
state: SessionState,
|
||||||
merchant: domain::MerchantAccount,
|
merchant: domain::MerchantAccount,
|
||||||
|
profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
|
||||||
time_range: common_utils::types::TimeRange,
|
time_range: common_utils::types::TimeRange,
|
||||||
) -> RouterResponse<api_models::refunds::RefundAggregateResponse> {
|
) -> RouterResponse<api_models::refunds::RefundAggregateResponse> {
|
||||||
let db = state.store.as_ref();
|
let db = state.store.as_ref();
|
||||||
let refund_status_with_count = db
|
let refund_status_with_count = db
|
||||||
.get_refund_status_with_count(merchant.get_id(), &time_range, merchant.storage_scheme)
|
.get_refund_status_with_count(
|
||||||
|
merchant.get_id(),
|
||||||
|
profile_id_list,
|
||||||
|
&time_range,
|
||||||
|
merchant.storage_scheme,
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
.attach_printable("Failed to find status count")?;
|
.attach_printable("Failed to find status count")?;
|
||||||
|
|||||||
@ -2547,11 +2547,12 @@ impl RefundInterface for KafkaStore {
|
|||||||
async fn get_refund_status_with_count(
|
async fn get_refund_status_with_count(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: &id_type::MerchantId,
|
merchant_id: &id_type::MerchantId,
|
||||||
|
profile_id_list: Option<Vec<id_type::ProfileId>>,
|
||||||
constraints: &common_utils::types::TimeRange,
|
constraints: &common_utils::types::TimeRange,
|
||||||
storage_scheme: MerchantStorageScheme,
|
storage_scheme: MerchantStorageScheme,
|
||||||
) -> CustomResult<Vec<(common_enums::RefundStatus, i64)>, errors::StorageError> {
|
) -> CustomResult<Vec<(common_enums::RefundStatus, i64)>, errors::StorageError> {
|
||||||
self.diesel_store
|
self.diesel_store
|
||||||
.get_refund_status_with_count(merchant_id, constraints, storage_scheme)
|
.get_refund_status_with_count(merchant_id, profile_id_list, constraints, storage_scheme)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -88,6 +88,7 @@ pub trait RefundInterface {
|
|||||||
async fn get_refund_status_with_count(
|
async fn get_refund_status_with_count(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: &common_utils::id_type::MerchantId,
|
merchant_id: &common_utils::id_type::MerchantId,
|
||||||
|
profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
|
||||||
constraints: &common_utils::types::TimeRange,
|
constraints: &common_utils::types::TimeRange,
|
||||||
storage_scheme: enums::MerchantStorageScheme,
|
storage_scheme: enums::MerchantStorageScheme,
|
||||||
) -> CustomResult<Vec<(common_enums::RefundStatus, i64)>, errors::StorageError>;
|
) -> CustomResult<Vec<(common_enums::RefundStatus, i64)>, errors::StorageError>;
|
||||||
@ -265,11 +266,12 @@ mod storage {
|
|||||||
async fn get_refund_status_with_count(
|
async fn get_refund_status_with_count(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: &common_utils::id_type::MerchantId,
|
merchant_id: &common_utils::id_type::MerchantId,
|
||||||
|
profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
|
||||||
time_range: &api_models::payments::TimeRange,
|
time_range: &api_models::payments::TimeRange,
|
||||||
_storage_scheme: enums::MerchantStorageScheme,
|
_storage_scheme: enums::MerchantStorageScheme,
|
||||||
) -> CustomResult<Vec<(common_enums::RefundStatus, i64)>, errors::StorageError> {
|
) -> CustomResult<Vec<(common_enums::RefundStatus, i64)>, errors::StorageError> {
|
||||||
let conn = connection::pg_connection_read(self).await?;
|
let conn = connection::pg_connection_read(self).await?;
|
||||||
<diesel_models::refund::Refund as storage_types::RefundDbExt>::get_refund_status_with_count(&conn, merchant_id, time_range)
|
<diesel_models::refund::Refund as storage_types::RefundDbExt>::get_refund_status_with_count(&conn, merchant_id,profile_id_list, time_range)
|
||||||
.await
|
.await
|
||||||
.map_err(|error|report!(errors::StorageError::from(error)))
|
.map_err(|error|report!(errors::StorageError::from(error)))
|
||||||
}
|
}
|
||||||
@ -831,11 +833,12 @@ mod storage {
|
|||||||
async fn get_refund_status_with_count(
|
async fn get_refund_status_with_count(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: &common_utils::id_type::MerchantId,
|
merchant_id: &common_utils::id_type::MerchantId,
|
||||||
|
profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
|
||||||
constraints: &common_utils::types::TimeRange,
|
constraints: &common_utils::types::TimeRange,
|
||||||
_storage_scheme: enums::MerchantStorageScheme,
|
_storage_scheme: enums::MerchantStorageScheme,
|
||||||
) -> CustomResult<Vec<(common_enums::RefundStatus, i64)>, errors::StorageError> {
|
) -> CustomResult<Vec<(common_enums::RefundStatus, i64)>, errors::StorageError> {
|
||||||
let conn = connection::pg_connection_read(self).await?;
|
let conn = connection::pg_connection_read(self).await?;
|
||||||
<diesel_models::refund::Refund as storage_types::RefundDbExt>::get_refund_status_with_count(&conn, merchant_id, constraints)
|
<diesel_models::refund::Refund as storage_types::RefundDbExt>::get_refund_status_with_count(&conn, merchant_id,profile_id_list, constraints)
|
||||||
.await
|
.await
|
||||||
.map_err(|error| report!(errors::StorageError::from(error)))
|
.map_err(|error| report!(errors::StorageError::from(error)))
|
||||||
}
|
}
|
||||||
@ -1182,6 +1185,7 @@ impl RefundInterface for MockDb {
|
|||||||
async fn get_refund_status_with_count(
|
async fn get_refund_status_with_count(
|
||||||
&self,
|
&self,
|
||||||
_merchant_id: &common_utils::id_type::MerchantId,
|
_merchant_id: &common_utils::id_type::MerchantId,
|
||||||
|
profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
|
||||||
time_range: &common_utils::types::TimeRange,
|
time_range: &common_utils::types::TimeRange,
|
||||||
_storage_scheme: enums::MerchantStorageScheme,
|
_storage_scheme: enums::MerchantStorageScheme,
|
||||||
) -> CustomResult<Vec<(api_models::enums::RefundStatus, i64)>, errors::StorageError> {
|
) -> CustomResult<Vec<(api_models::enums::RefundStatus, i64)>, errors::StorageError> {
|
||||||
@ -1194,7 +1198,17 @@ impl RefundInterface for MockDb {
|
|||||||
|
|
||||||
let filtered_refunds = refunds
|
let filtered_refunds = refunds
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|refund| refund.created_at >= start_time && refund.created_at <= end_time)
|
.filter(|refund| {
|
||||||
|
refund.created_at >= start_time
|
||||||
|
&& refund.created_at <= end_time
|
||||||
|
&& profile_id_list
|
||||||
|
.as_ref()
|
||||||
|
.zip(refund.profile_id.as_ref())
|
||||||
|
.map(|(received_profile_list, received_profile_id)| {
|
||||||
|
received_profile_list.contains(received_profile_id)
|
||||||
|
})
|
||||||
|
.unwrap_or(true)
|
||||||
|
})
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect::<Vec<diesel_models::refund::Refund>>();
|
.collect::<Vec<diesel_models::refund::Refund>>();
|
||||||
|
|
||||||
|
|||||||
@ -1002,6 +1002,10 @@ impl Refunds {
|
|||||||
.service(web::resource("/filter").route(web::post().to(refunds_filter_list)))
|
.service(web::resource("/filter").route(web::post().to(refunds_filter_list)))
|
||||||
.service(web::resource("/v2/filter").route(web::get().to(get_refunds_filters)))
|
.service(web::resource("/v2/filter").route(web::get().to(get_refunds_filters)))
|
||||||
.service(web::resource("/aggregate").route(web::get().to(get_refunds_aggregates)))
|
.service(web::resource("/aggregate").route(web::get().to(get_refunds_aggregates)))
|
||||||
|
.service(
|
||||||
|
web::resource("/profile/aggregate")
|
||||||
|
.route(web::get().to(get_refunds_aggregate_profile)),
|
||||||
|
)
|
||||||
.service(
|
.service(
|
||||||
web::resource("/v2/profile/filter")
|
web::resource("/v2/profile/filter")
|
||||||
.route(web::get().to(get_refunds_filters_profile)),
|
.route(web::get().to(get_refunds_filters_profile)),
|
||||||
|
|||||||
@ -436,7 +436,7 @@ pub async fn get_refunds_aggregates(
|
|||||||
&req,
|
&req,
|
||||||
query_params,
|
query_params,
|
||||||
|state, auth: auth::AuthenticationData, req, _| {
|
|state, auth: auth::AuthenticationData, req, _| {
|
||||||
get_aggregates_for_refunds(state, auth.merchant_account, req)
|
get_aggregates_for_refunds(state, auth.merchant_account, None, req)
|
||||||
},
|
},
|
||||||
auth::auth_type(
|
auth::auth_type(
|
||||||
&auth::HeaderAuth(auth::ApiKeyAuth),
|
&auth::HeaderAuth(auth::ApiKeyAuth),
|
||||||
@ -473,3 +473,38 @@ pub async fn refunds_manual_update(
|
|||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip_all, fields(flow = ?Flow::RefundsAggregate))]
|
||||||
|
#[cfg(feature = "olap")]
|
||||||
|
pub async fn get_refunds_aggregate_profile(
|
||||||
|
state: web::Data<AppState>,
|
||||||
|
req: HttpRequest,
|
||||||
|
query_params: web::Query<common_utils::types::TimeRange>,
|
||||||
|
) -> HttpResponse {
|
||||||
|
let flow = Flow::RefundsAggregate;
|
||||||
|
let query_params = query_params.into_inner();
|
||||||
|
Box::pin(api::server_wrap(
|
||||||
|
flow,
|
||||||
|
state,
|
||||||
|
&req,
|
||||||
|
query_params,
|
||||||
|
|state, auth: auth::AuthenticationData, req, _| {
|
||||||
|
get_aggregates_for_refunds(
|
||||||
|
state,
|
||||||
|
auth.merchant_account,
|
||||||
|
auth.profile_id.map(|profile_id| vec![profile_id]),
|
||||||
|
req,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
auth::auth_type(
|
||||||
|
&auth::HeaderAuth(auth::ApiKeyAuth),
|
||||||
|
&auth::JWTAuth {
|
||||||
|
permission: Permission::RefundRead,
|
||||||
|
minimum_entity_level: EntityType::Profile,
|
||||||
|
},
|
||||||
|
req.headers(),
|
||||||
|
),
|
||||||
|
api_locking::LockAction::NotApplicable,
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|||||||
@ -41,6 +41,7 @@ pub trait RefundDbExt: Sized {
|
|||||||
async fn get_refund_status_with_count(
|
async fn get_refund_status_with_count(
|
||||||
conn: &PgPooledConn,
|
conn: &PgPooledConn,
|
||||||
merchant_id: &common_utils::id_type::MerchantId,
|
merchant_id: &common_utils::id_type::MerchantId,
|
||||||
|
profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
|
||||||
time_range: &common_utils::types::TimeRange,
|
time_range: &common_utils::types::TimeRange,
|
||||||
) -> CustomResult<Vec<(RefundStatus, i64)>, errors::DatabaseError>;
|
) -> CustomResult<Vec<(RefundStatus, i64)>, errors::DatabaseError>;
|
||||||
}
|
}
|
||||||
@ -299,6 +300,7 @@ impl RefundDbExt for Refund {
|
|||||||
async fn get_refund_status_with_count(
|
async fn get_refund_status_with_count(
|
||||||
conn: &PgPooledConn,
|
conn: &PgPooledConn,
|
||||||
merchant_id: &common_utils::id_type::MerchantId,
|
merchant_id: &common_utils::id_type::MerchantId,
|
||||||
|
profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
|
||||||
time_range: &common_utils::types::TimeRange,
|
time_range: &common_utils::types::TimeRange,
|
||||||
) -> CustomResult<Vec<(RefundStatus, i64)>, errors::DatabaseError> {
|
) -> CustomResult<Vec<(RefundStatus, i64)>, errors::DatabaseError> {
|
||||||
let mut query = <Self as HasTable>::table()
|
let mut query = <Self as HasTable>::table()
|
||||||
@ -307,6 +309,10 @@ impl RefundDbExt for Refund {
|
|||||||
.filter(dsl::merchant_id.eq(merchant_id.to_owned()))
|
.filter(dsl::merchant_id.eq(merchant_id.to_owned()))
|
||||||
.into_boxed();
|
.into_boxed();
|
||||||
|
|
||||||
|
if let Some(profile_id) = profile_id_list {
|
||||||
|
query = query.filter(dsl::profile_id.eq_any(profile_id));
|
||||||
|
}
|
||||||
|
|
||||||
query = query.filter(dsl::created_at.ge(time_range.start_time));
|
query = query.filter(dsl::created_at.ge(time_range.start_time));
|
||||||
|
|
||||||
query = match time_range.end_time {
|
query = match time_range.end_time {
|
||||||
|
|||||||
Reference in New Issue
Block a user