mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-27 19:46:48 +08:00
feat(payments): add amount and connector id filter in list (#4354)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@ -3394,6 +3394,8 @@ pub struct PaymentListFilterConstraints {
|
||||
pub limit: u32,
|
||||
/// The starting point within a list of objects
|
||||
pub offset: Option<u32>,
|
||||
/// The amount to filter payments list
|
||||
pub amount_filter: Option<AmountFilter>,
|
||||
/// The time range for which objects are needed. TimeRange has two fields start_time and end_time from which objects can be filtered as per required scenarios (created_at, time less than, greater than etc).
|
||||
#[serde(flatten)]
|
||||
pub time_range: Option<TimeRange>,
|
||||
@ -3409,6 +3411,8 @@ pub struct PaymentListFilterConstraints {
|
||||
pub payment_method_type: Option<Vec<enums::PaymentMethodType>>,
|
||||
/// The list of authentication types to filter payments list
|
||||
pub authentication_type: Option<Vec<enums::AuthenticationType>>,
|
||||
/// The list of merchant connector ids to filter payments list for selected label
|
||||
pub merchant_connector_id: Option<Vec<String>>,
|
||||
}
|
||||
#[derive(Clone, Debug, serde::Serialize)]
|
||||
pub struct PaymentListFilters {
|
||||
@ -3440,6 +3444,12 @@ pub struct PaymentListFiltersV2 {
|
||||
pub authentication_type: Vec<enums::AuthenticationType>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
pub struct AmountFilter {
|
||||
pub start_amount: Option<i64>,
|
||||
pub end_amount: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq, Hash, ToSchema,
|
||||
)]
|
||||
|
||||
@ -22,7 +22,7 @@ pub static FRM_CONFIGS_EG: &str = r#"
|
||||
/// Maximum limit for payments list get api
|
||||
pub const PAYMENTS_LIST_MAX_LIMIT_V1: u32 = 100;
|
||||
/// Maximum limit for payments list post api with filters
|
||||
pub const PAYMENTS_LIST_MAX_LIMIT_V2: u32 = 20;
|
||||
pub const PAYMENTS_LIST_MAX_LIMIT_V2: u32 = 50;
|
||||
/// Default limit for payments list API
|
||||
pub fn default_payments_list_limit() -> u32 {
|
||||
10
|
||||
|
||||
@ -99,6 +99,7 @@ pub trait PaymentAttemptInterface {
|
||||
payment_method: Option<Vec<storage_enums::PaymentMethod>>,
|
||||
payment_method_type: Option<Vec<storage_enums::PaymentMethodType>>,
|
||||
authentication_type: Option<Vec<storage_enums::AuthenticationType>>,
|
||||
merchant_connector_id: Option<Vec<String>>,
|
||||
storage_scheme: storage_enums::MerchantStorageScheme,
|
||||
) -> error_stack::Result<i64, errors::StorageError>;
|
||||
}
|
||||
|
||||
@ -430,12 +430,14 @@ pub struct PaymentIntentListParams {
|
||||
pub offset: u32,
|
||||
pub starting_at: Option<PrimitiveDateTime>,
|
||||
pub ending_at: Option<PrimitiveDateTime>,
|
||||
pub amount_filter: Option<api_models::payments::AmountFilter>,
|
||||
pub connector: Option<Vec<api_models::enums::Connector>>,
|
||||
pub currency: Option<Vec<storage_enums::Currency>>,
|
||||
pub status: Option<Vec<storage_enums::IntentStatus>>,
|
||||
pub payment_method: Option<Vec<storage_enums::PaymentMethod>>,
|
||||
pub payment_method_type: Option<Vec<storage_enums::PaymentMethodType>>,
|
||||
pub authentication_type: Option<Vec<storage_enums::AuthenticationType>>,
|
||||
pub merchant_connector_id: Option<Vec<String>>,
|
||||
pub profile_id: Option<String>,
|
||||
pub customer_id: Option<String>,
|
||||
pub starting_after_id: Option<String>,
|
||||
@ -449,12 +451,14 @@ impl From<api_models::payments::PaymentListConstraints> for PaymentIntentFetchCo
|
||||
offset: 0,
|
||||
starting_at: value.created_gte.or(value.created_gt).or(value.created),
|
||||
ending_at: value.created_lte.or(value.created_lt).or(value.created),
|
||||
amount_filter: None,
|
||||
connector: None,
|
||||
currency: None,
|
||||
status: None,
|
||||
payment_method: None,
|
||||
payment_method_type: None,
|
||||
authentication_type: None,
|
||||
merchant_connector_id: None,
|
||||
profile_id: None,
|
||||
customer_id: value.customer_id,
|
||||
starting_after_id: value.starting_after,
|
||||
@ -470,12 +474,14 @@ impl From<api_models::payments::TimeRange> for PaymentIntentFetchConstraints {
|
||||
offset: 0,
|
||||
starting_at: Some(value.start_time),
|
||||
ending_at: value.end_time,
|
||||
amount_filter: None,
|
||||
connector: None,
|
||||
currency: None,
|
||||
status: None,
|
||||
payment_method: None,
|
||||
payment_method_type: None,
|
||||
authentication_type: None,
|
||||
merchant_connector_id: None,
|
||||
profile_id: None,
|
||||
customer_id: None,
|
||||
starting_after_id: None,
|
||||
@ -494,12 +500,14 @@ impl From<api_models::payments::PaymentListFilterConstraints> for PaymentIntentF
|
||||
offset: value.offset.unwrap_or_default(),
|
||||
starting_at: value.time_range.map(|t| t.start_time),
|
||||
ending_at: value.time_range.and_then(|t| t.end_time),
|
||||
amount_filter: value.amount_filter,
|
||||
connector: value.connector,
|
||||
currency: value.currency,
|
||||
status: value.status,
|
||||
payment_method: value.payment_method,
|
||||
payment_method_type: value.payment_method_type,
|
||||
authentication_type: value.authentication_type,
|
||||
merchant_connector_id: value.merchant_connector_id,
|
||||
profile_id: value.profile_id,
|
||||
customer_id: value.customer_id,
|
||||
starting_after_id: None,
|
||||
|
||||
@ -309,6 +309,8 @@ impl PaymentAttempt {
|
||||
filter_authentication_type,
|
||||
))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn get_total_count_of_attempts(
|
||||
conn: &PgPooledConn,
|
||||
merchant_id: &str,
|
||||
@ -317,6 +319,7 @@ impl PaymentAttempt {
|
||||
payment_method: Option<Vec<enums::PaymentMethod>>,
|
||||
payment_method_type: Option<Vec<enums::PaymentMethodType>>,
|
||||
authentication_type: Option<Vec<enums::AuthenticationType>>,
|
||||
merchant_connector_id: Option<Vec<String>>,
|
||||
) -> StorageResult<i64> {
|
||||
let mut filter = <Self as HasTable>::table()
|
||||
.count()
|
||||
@ -324,19 +327,22 @@ impl PaymentAttempt {
|
||||
.filter(dsl::attempt_id.eq_any(active_attempt_ids.to_owned()))
|
||||
.into_boxed();
|
||||
|
||||
if let Some(connector) = connector.clone() {
|
||||
if let Some(connector) = connector {
|
||||
filter = filter.filter(dsl::connector.eq_any(connector));
|
||||
}
|
||||
|
||||
if let Some(payment_method) = payment_method.clone() {
|
||||
if let Some(payment_method) = payment_method {
|
||||
filter = filter.filter(dsl::payment_method.eq_any(payment_method));
|
||||
}
|
||||
if let Some(payment_method_type) = payment_method_type.clone() {
|
||||
if let Some(payment_method_type) = payment_method_type {
|
||||
filter = filter.filter(dsl::payment_method_type.eq_any(payment_method_type));
|
||||
}
|
||||
if let Some(authentication_type) = authentication_type.clone() {
|
||||
if let Some(authentication_type) = authentication_type {
|
||||
filter = filter.filter(dsl::authentication_type.eq_any(authentication_type));
|
||||
}
|
||||
if let Some(merchant_connector_id) = merchant_connector_id {
|
||||
filter = filter.filter(dsl::merchant_connector_id.eq_any(merchant_connector_id))
|
||||
}
|
||||
router_env::logger::debug!(query = %debug_query::<Pg, _>(&filter).to_string());
|
||||
|
||||
db_metrics::track_database_call::<<Self as HasTable>::Table, _, _>(
|
||||
|
||||
@ -2579,6 +2579,7 @@ pub async fn apply_filters_on_payments(
|
||||
constraints.payment_method,
|
||||
constraints.payment_method_type,
|
||||
constraints.authentication_type,
|
||||
constraints.merchant_connector_id,
|
||||
merchant.storage_scheme,
|
||||
)
|
||||
.await
|
||||
|
||||
@ -1258,6 +1258,7 @@ impl PaymentAttemptInterface for KafkaStore {
|
||||
payment_method: Option<Vec<common_enums::PaymentMethod>>,
|
||||
payment_method_type: Option<Vec<common_enums::PaymentMethodType>>,
|
||||
authentication_type: Option<Vec<common_enums::AuthenticationType>>,
|
||||
merchant_connector_id: Option<Vec<String>>,
|
||||
storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<i64, errors::DataStorageError> {
|
||||
self.diesel_store
|
||||
@ -1268,6 +1269,7 @@ impl PaymentAttemptInterface for KafkaStore {
|
||||
payment_method,
|
||||
payment_method_type,
|
||||
authentication_type,
|
||||
merchant_connector_id,
|
||||
storage_scheme,
|
||||
)
|
||||
.await
|
||||
|
||||
@ -922,14 +922,10 @@ pub async fn payments_list_by_filter(
|
||||
state,
|
||||
&req,
|
||||
payload,
|
||||
|state, auth, req, _| {
|
||||
|state, auth: auth::AuthenticationData, req, _| {
|
||||
payments::apply_filters_on_payments(state, auth.merchant_account, req)
|
||||
},
|
||||
auth::auth_type(
|
||||
&auth::ApiKeyAuth,
|
||||
&auth::JWTAuth(Permission::PaymentRead),
|
||||
req.headers(),
|
||||
),
|
||||
api_locking::LockAction::NotApplicable,
|
||||
)
|
||||
.await
|
||||
@ -948,12 +944,10 @@ pub async fn get_filters_for_payments(
|
||||
state,
|
||||
&req,
|
||||
payload,
|
||||
|state, auth, req, _| payments::get_filters_for_payments(state, auth.merchant_account, req),
|
||||
auth::auth_type(
|
||||
&auth::ApiKeyAuth,
|
||||
|state, auth: auth::AuthenticationData, req, _| {
|
||||
payments::get_filters_for_payments(state, auth.merchant_account, req)
|
||||
},
|
||||
&auth::JWTAuth(Permission::PaymentRead),
|
||||
req.headers(),
|
||||
),
|
||||
api_locking::LockAction::NotApplicable,
|
||||
)
|
||||
.await
|
||||
@ -971,12 +965,10 @@ pub async fn get_payment_filters(
|
||||
state,
|
||||
&req,
|
||||
(),
|
||||
|state, auth, _, _| payments::get_payment_filters(state, auth.merchant_account),
|
||||
auth::auth_type(
|
||||
&auth::ApiKeyAuth,
|
||||
|state, auth: auth::AuthenticationData, _, _| {
|
||||
payments::get_payment_filters(state, auth.merchant_account)
|
||||
},
|
||||
&auth::JWTAuth(Permission::PaymentRead),
|
||||
req.headers(),
|
||||
),
|
||||
api_locking::LockAction::NotApplicable,
|
||||
)
|
||||
.await
|
||||
|
||||
@ -42,6 +42,7 @@ impl PaymentAttemptInterface for MockDb {
|
||||
_payment_method: Option<Vec<PaymentMethod>>,
|
||||
_payment_method_type: Option<Vec<PaymentMethodType>>,
|
||||
_authentication_type: Option<Vec<AuthenticationType>>,
|
||||
_merchanat_connector_id: Option<Vec<String>>,
|
||||
_storage_scheme: storage_enums::MerchantStorageScheme,
|
||||
) -> CustomResult<i64, StorageError> {
|
||||
Err(StorageError::MockDbError)?
|
||||
|
||||
@ -292,6 +292,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
|
||||
payment_method: Option<Vec<PaymentMethod>>,
|
||||
payment_method_type: Option<Vec<PaymentMethodType>>,
|
||||
authentication_type: Option<Vec<AuthenticationType>>,
|
||||
merchant_connector_id: Option<Vec<String>>,
|
||||
_storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<i64, errors::StorageError> {
|
||||
let conn = self
|
||||
@ -314,6 +315,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
|
||||
payment_method,
|
||||
payment_method_type,
|
||||
authentication_type,
|
||||
merchant_connector_id,
|
||||
)
|
||||
.await
|
||||
.map_err(|er| {
|
||||
@ -1021,6 +1023,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
|
||||
payment_method: Option<Vec<PaymentMethod>>,
|
||||
payment_method_type: Option<Vec<PaymentMethodType>>,
|
||||
authentication_type: Option<Vec<AuthenticationType>>,
|
||||
merchant_connector_id: Option<Vec<String>>,
|
||||
storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<i64, errors::StorageError> {
|
||||
self.router_store
|
||||
@ -1031,6 +1034,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
|
||||
payment_method,
|
||||
payment_method_type,
|
||||
authentication_type,
|
||||
merchant_connector_id,
|
||||
storage_scheme,
|
||||
)
|
||||
.await
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
#[cfg(feature = "olap")]
|
||||
use api_models::payments::AmountFilter;
|
||||
#[cfg(feature = "olap")]
|
||||
use async_bb8_diesel::{AsyncConnection, AsyncRunQueryDsl};
|
||||
#[cfg(feature = "olap")]
|
||||
use common_utils::errors::ReportSwitchExt;
|
||||
use common_utils::{date_time, ext_traits::Encode};
|
||||
#[cfg(feature = "olap")]
|
||||
use data_models::payments::payment_intent::PaymentIntentFetchConstraints;
|
||||
@ -549,8 +553,6 @@ impl<T: DatabaseStore> PaymentIntentInterface for crate::RouterStore<T> {
|
||||
constraints: &PaymentIntentFetchConstraints,
|
||||
storage_scheme: MerchantStorageScheme,
|
||||
) -> error_stack::Result<Vec<(PaymentIntent, PaymentAttempt)>, StorageError> {
|
||||
use common_utils::errors::ReportSwitchExt;
|
||||
|
||||
let conn = connection::pg_connection_read(self).await.switch()?;
|
||||
let conn = async_bb8_diesel::Connection::as_async_conn(&conn);
|
||||
let mut query = DieselPaymentIntent::table()
|
||||
@ -615,9 +617,26 @@ impl<T: DatabaseStore> PaymentIntentInterface for crate::RouterStore<T> {
|
||||
|
||||
query = query.offset(params.offset.into());
|
||||
|
||||
if let Some(currency) = ¶ms.currency {
|
||||
query = query.filter(pi_dsl::currency.eq_any(currency.clone()));
|
||||
}
|
||||
query = match params.amount_filter {
|
||||
Some(AmountFilter {
|
||||
start_amount: Some(start),
|
||||
end_amount: Some(end),
|
||||
}) => query.filter(pi_dsl::amount.between(start, end)),
|
||||
Some(AmountFilter {
|
||||
start_amount: Some(start),
|
||||
end_amount: None,
|
||||
}) => query.filter(pi_dsl::amount.ge(start)),
|
||||
Some(AmountFilter {
|
||||
start_amount: None,
|
||||
end_amount: Some(end),
|
||||
}) => query.filter(pi_dsl::amount.le(end)),
|
||||
_ => query,
|
||||
};
|
||||
|
||||
query = match ¶ms.currency {
|
||||
Some(currency) => query.filter(pi_dsl::currency.eq_any(currency.clone())),
|
||||
None => query,
|
||||
};
|
||||
|
||||
let connectors = params
|
||||
.connector
|
||||
@ -653,6 +672,13 @@ impl<T: DatabaseStore> PaymentIntentInterface for crate::RouterStore<T> {
|
||||
None => query,
|
||||
};
|
||||
|
||||
query = match ¶ms.merchant_connector_id {
|
||||
Some(merchant_connector_id) => query.filter(
|
||||
pa_dsl::merchant_connector_id.eq_any(merchant_connector_id.clone()),
|
||||
),
|
||||
None => query,
|
||||
};
|
||||
|
||||
query
|
||||
}
|
||||
};
|
||||
@ -690,8 +716,6 @@ impl<T: DatabaseStore> PaymentIntentInterface for crate::RouterStore<T> {
|
||||
constraints: &PaymentIntentFetchConstraints,
|
||||
_storage_scheme: MerchantStorageScheme,
|
||||
) -> error_stack::Result<Vec<String>, StorageError> {
|
||||
use common_utils::errors::ReportSwitchExt;
|
||||
|
||||
let conn = connection::pg_connection_read(self).await.switch()?;
|
||||
let conn = async_bb8_diesel::Connection::as_async_conn(&conn);
|
||||
let mut query = DieselPaymentIntent::table()
|
||||
@ -722,6 +746,22 @@ impl<T: DatabaseStore> PaymentIntentInterface for crate::RouterStore<T> {
|
||||
None => query,
|
||||
};
|
||||
|
||||
query = match params.amount_filter {
|
||||
Some(AmountFilter {
|
||||
start_amount: Some(start),
|
||||
end_amount: Some(end),
|
||||
}) => query.filter(pi_dsl::amount.between(start, end)),
|
||||
Some(AmountFilter {
|
||||
start_amount: Some(start),
|
||||
end_amount: None,
|
||||
}) => query.filter(pi_dsl::amount.ge(start)),
|
||||
Some(AmountFilter {
|
||||
start_amount: None,
|
||||
end_amount: Some(end),
|
||||
}) => query.filter(pi_dsl::amount.le(end)),
|
||||
_ => query,
|
||||
};
|
||||
|
||||
query = match ¶ms.currency {
|
||||
Some(currency) => query.filter(pi_dsl::currency.eq_any(currency.clone())),
|
||||
None => query,
|
||||
|
||||
Reference in New Issue
Block a user