refactor(payment_attempt_v2): add payment attempt v2 domain and diesel models (#6027)

Co-authored-by: hrithikesh026 <hrithikesh.vm@juspay.in>
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Narayan Bhat
2024-09-27 18:52:40 +05:30
committed by GitHub
parent 354f5306e7
commit c7bb9ccda3
56 changed files with 2643 additions and 2050 deletions

View File

@ -15,7 +15,6 @@ olap = ["hyperswitch_domain_models/olap"]
payouts = ["hyperswitch_domain_models/payouts"]
v1 = ["api_models/v1", "diesel_models/v1", "hyperswitch_domain_models/v1"]
v2 = ["api_models/v2", "diesel_models/v2", "hyperswitch_domain_models/v2"]
payment_v2 = ["hyperswitch_domain_models/payment_v2", "diesel_models/payment_v2"]
customer_v2 = ["api_models/customer_v2", "diesel_models/customer_v2", "hyperswitch_domain_models/customer_v2"]
payment_methods_v2 = ["diesel_models/payment_methods_v2", "api_models/payment_methods_v2", "hyperswitch_domain_models/payment_methods_v2"]

View File

@ -329,7 +329,7 @@ impl UniqueConstraints for diesel_models::Address {
}
}
#[cfg(all(feature = "v2", feature = "payment_v2"))]
#[cfg(feature = "v2")]
impl UniqueConstraints for diesel_models::PaymentIntent {
fn unique_constraints(&self) -> Vec<String> {
vec![self.id.get_string_repr().to_owned()]
@ -340,7 +340,7 @@ impl UniqueConstraints for diesel_models::PaymentIntent {
}
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
impl UniqueConstraints for diesel_models::PaymentIntent {
#[cfg(feature = "v1")]
fn unique_constraints(&self) -> Vec<String> {
@ -361,6 +361,7 @@ impl UniqueConstraints for diesel_models::PaymentIntent {
}
}
#[cfg(feature = "v1")]
impl UniqueConstraints for diesel_models::PaymentAttempt {
fn unique_constraints(&self) -> Vec<String> {
vec![format!(

View File

@ -1,23 +1,23 @@
use api_models::enums::{AuthenticationType, Connector, PaymentMethod, PaymentMethodType};
use common_utils::errors::CustomResult;
#[cfg(all(feature = "v2", feature = "payment_v2"))]
#[cfg(feature = "v2")]
use common_utils::types::keymanager::KeyManagerState;
use diesel_models::enums as storage_enums;
#[cfg(all(feature = "v2", feature = "payment_v2"))]
#[cfg(feature = "v2")]
use hyperswitch_domain_models::merchant_key_store::MerchantKeyStore;
#[cfg(feature = "v1")]
use hyperswitch_domain_models::payments::payment_attempt::PaymentAttemptNew;
use hyperswitch_domain_models::{
errors::StorageError,
payments::payment_attempt::{
PaymentAttempt, PaymentAttemptInterface, PaymentAttemptNew, PaymentAttemptUpdate,
},
payments::payment_attempt::{PaymentAttempt, PaymentAttemptInterface, PaymentAttemptUpdate},
};
use super::MockDb;
#[cfg(feature = "v1")]
use crate::DataModelExt;
#[async_trait::async_trait]
impl PaymentAttemptInterface for MockDb {
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
async fn find_payment_attempt_by_payment_id_merchant_id_attempt_id(
&self,
_payment_id: &common_utils::id_type::PaymentId,
@ -29,7 +29,7 @@ impl PaymentAttemptInterface for MockDb {
Err(StorageError::MockDbError)?
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(all(feature = "v1", feature = "olap"))]
async fn get_filters_for_payments(
&self,
_pi: &[hyperswitch_domain_models::payments::PaymentIntent],
@ -42,15 +42,15 @@ impl PaymentAttemptInterface for MockDb {
Err(StorageError::MockDbError)?
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(all(feature = "v1", feature = "olap"))]
async fn get_total_count_of_filtered_payment_attempts(
&self,
_merchant_id: &common_utils::id_type::MerchantId,
_active_attempt_ids: &[String],
_connector: Option<Vec<Connector>>,
_payment_method: Option<Vec<PaymentMethod>>,
_payment_method_type: Option<Vec<PaymentMethodType>>,
_authentication_type: Option<Vec<AuthenticationType>>,
_connector: Option<Vec<api_models::enums::Connector>>,
_payment_method: Option<Vec<common_enums::PaymentMethod>>,
_payment_method_type: Option<Vec<common_enums::PaymentMethodType>>,
_authentication_type: Option<Vec<common_enums::AuthenticationType>>,
_merchanat_connector_id: Option<Vec<common_utils::id_type::MerchantConnectorAccountId>>,
_time_range: Option<common_utils::types::TimeRange>,
_profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
@ -59,7 +59,7 @@ impl PaymentAttemptInterface for MockDb {
Err(StorageError::MockDbError)?
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
async fn find_payment_attempt_by_attempt_id_merchant_id(
&self,
_attempt_id: &str,
@ -70,20 +70,19 @@ impl PaymentAttemptInterface for MockDb {
Err(StorageError::MockDbError)?
}
#[cfg(all(feature = "v2", feature = "payment_v2"))]
async fn find_payment_attempt_by_attempt_id_merchant_id(
#[cfg(feature = "v2")]
async fn find_payment_attempt_by_id(
&self,
_key_manager_state: &KeyManagerState,
_merchant_key_store: &MerchantKeyStore,
_attempt_id: &str,
_merchant_id: &common_utils::id_type::MerchantId,
_storage_scheme: storage_enums::MerchantStorageScheme,
) -> CustomResult<PaymentAttempt, StorageError> {
) -> error_stack::Result<PaymentAttempt, StorageError> {
// [#172]: Implement function for `MockDb`
Err(StorageError::MockDbError)?
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
async fn find_payment_attempt_by_preprocessing_id_merchant_id(
&self,
_preprocessing_id: &str,
@ -94,7 +93,7 @@ impl PaymentAttemptInterface for MockDb {
Err(StorageError::MockDbError)?
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
async fn find_payment_attempt_by_merchant_id_connector_txn_id(
&self,
_merchant_id: &common_utils::id_type::MerchantId,
@ -105,7 +104,7 @@ impl PaymentAttemptInterface for MockDb {
Err(StorageError::MockDbError)?
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
async fn find_attempts_by_merchant_id_payment_id(
&self,
_merchant_id: &common_utils::id_type::MerchantId,
@ -116,7 +115,7 @@ impl PaymentAttemptInterface for MockDb {
Err(StorageError::MockDbError)?
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[allow(clippy::panic)]
async fn insert_payment_attempt(
&self,
@ -194,7 +193,7 @@ impl PaymentAttemptInterface for MockDb {
Ok(payment_attempt)
}
#[cfg(all(feature = "v2", feature = "payment_v2"))]
#[cfg(feature = "v2")]
#[allow(clippy::panic)]
async fn insert_payment_attempt(
&self,
@ -207,7 +206,7 @@ impl PaymentAttemptInterface for MockDb {
Err(StorageError::MockDbError)?
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
// safety: only used for testing
#[allow(clippy::unwrap_used)]
async fn update_payment_attempt_with_attempt_id(
@ -232,7 +231,7 @@ impl PaymentAttemptInterface for MockDb {
Ok(item.clone())
}
#[cfg(all(feature = "v2", feature = "payment_v2"))]
#[cfg(feature = "v2")]
async fn update_payment_attempt_with_attempt_id(
&self,
_key_manager_state: &KeyManagerState,
@ -245,7 +244,7 @@ impl PaymentAttemptInterface for MockDb {
Err(StorageError::MockDbError)?
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
async fn find_payment_attempt_by_connector_transaction_id_payment_id_merchant_id(
&self,
_connector_transaction_id: &str,
@ -257,7 +256,7 @@ impl PaymentAttemptInterface for MockDb {
Err(StorageError::MockDbError)?
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
// safety: only used for testing
#[allow(clippy::unwrap_used)]
async fn find_payment_attempt_last_successful_attempt_by_payment_id_merchant_id(
@ -278,7 +277,7 @@ impl PaymentAttemptInterface for MockDb {
.unwrap())
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[allow(clippy::unwrap_used)]
async fn find_payment_attempt_last_successful_or_partially_captured_attempt_by_payment_id_merchant_id(
&self,

View File

@ -6,7 +6,6 @@ use hyperswitch_domain_models::{
errors::StorageError,
merchant_key_store::MerchantKeyStore,
payments::{
payment_attempt::PaymentAttempt,
payment_intent::{PaymentIntentInterface, PaymentIntentUpdate},
PaymentIntent,
},
@ -16,11 +15,7 @@ use super::MockDb;
#[async_trait::async_trait]
impl PaymentIntentInterface for MockDb {
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_v2"),
feature = "olap"
))]
#[cfg(all(feature = "v1", feature = "olap"))]
async fn filter_payment_intent_by_constraints(
&self,
_state: &KeyManagerState,
@ -32,11 +27,8 @@ impl PaymentIntentInterface for MockDb {
// [#172]: Implement function for `MockDb`
Err(StorageError::MockDbError)?
}
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_v2"),
feature = "olap"
))]
#[cfg(all(feature = "v1", feature = "olap"))]
async fn filter_payment_intents_by_time_range_constraints(
&self,
_state: &KeyManagerState,
@ -48,11 +40,8 @@ impl PaymentIntentInterface for MockDb {
// [#172]: Implement function for `MockDb`
Err(StorageError::MockDbError)?
}
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_v2"),
feature = "olap"
))]
#[cfg(all(feature = "v1", feature = "olap"))]
async fn get_intent_status_with_count(
&self,
_merchant_id: &common_utils::id_type::MerchantId,
@ -62,11 +51,8 @@ impl PaymentIntentInterface for MockDb {
// [#172]: Implement function for `MockDb`
Err(StorageError::MockDbError)?
}
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_v2"),
feature = "olap"
))]
#[cfg(all(feature = "v1", feature = "olap"))]
async fn get_filtered_active_attempt_ids_for_total_count(
&self,
_merchant_id: &common_utils::id_type::MerchantId,
@ -76,11 +62,8 @@ impl PaymentIntentInterface for MockDb {
// [#172]: Implement function for `MockDb`
Err(StorageError::MockDbError)?
}
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_v2"),
feature = "olap"
))]
#[cfg(all(feature = "v1", feature = "olap"))]
async fn get_filtered_payment_intents_attempt(
&self,
_state: &KeyManagerState,
@ -88,7 +71,13 @@ impl PaymentIntentInterface for MockDb {
_constraints: &hyperswitch_domain_models::payments::payment_intent::PaymentIntentFetchConstraints,
_key_store: &MerchantKeyStore,
_storage_scheme: storage_enums::MerchantStorageScheme,
) -> error_stack::Result<Vec<(PaymentIntent, PaymentAttempt)>, StorageError> {
) -> error_stack::Result<
Vec<(
PaymentIntent,
hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt,
)>,
StorageError,
> {
// [#172]: Implement function for `MockDb`
Err(StorageError::MockDbError)?
}
@ -141,7 +130,7 @@ impl PaymentIntentInterface for MockDb {
Ok(payment_intent.clone())
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
// safety: only used for testing
#[allow(clippy::unwrap_used)]
async fn find_payment_intent_by_payment_id_merchant_id(
@ -163,7 +152,7 @@ impl PaymentIntentInterface for MockDb {
.unwrap())
}
#[cfg(all(feature = "v2", feature = "payment_v2"))]
#[cfg(feature = "v2")]
async fn find_payment_intent_by_id(
&self,
_state: &KeyManagerState,
@ -181,24 +170,4 @@ impl PaymentIntentInterface for MockDb {
Ok(payment_intent.clone())
}
async fn get_active_payment_attempt(
&self,
payment: &mut PaymentIntent,
_storage_scheme: storage_enums::MerchantStorageScheme,
) -> error_stack::Result<PaymentAttempt, StorageError> {
match payment.active_attempt.clone() {
hyperswitch_domain_models::RemoteStorageObject::ForeignID(id) => {
let attempts = self.payment_attempts.lock().await;
let attempt = attempts
.iter()
.find(|pa| pa.attempt_id == id && pa.merchant_id == payment.merchant_id)
.ok_or(StorageError::ValueNotFound("Attempt not found".to_string()))?;
payment.active_attempt = attempt.clone().into();
Ok(attempt.clone())
}
hyperswitch_domain_models::RemoteStorageObject::Object(pa) => Ok(pa.clone()),
}
}
}

View File

@ -1,5 +1,4 @@
use api_models::enums::{AuthenticationType, Connector, PaymentMethod, PaymentMethodType};
#[cfg(all(feature = "v2", feature = "payment_v2"))]
#[cfg(feature = "v2")]
use common_utils::types::keymanager::KeyManagerState;
use common_utils::{errors::CustomResult, fallback_reverse_lookup_not_found};
use diesel_models::{
@ -15,21 +14,21 @@ use diesel_models::{
reverse_lookup::{ReverseLookup, ReverseLookupNew},
};
use error_stack::ResultExt;
#[cfg(feature = "v2")]
use hyperswitch_domain_models::{
behaviour::{Conversion, ReverseConversion},
merchant_key_store::MerchantKeyStore,
};
use hyperswitch_domain_models::{
behaviour::Conversion,
errors,
mandates::{MandateAmountData, MandateDataType, MandateDetails},
payments::{
payment_attempt::{
PaymentAttempt, PaymentAttemptInterface, PaymentAttemptNew, PaymentAttemptUpdate,
PaymentListFilters,
},
PaymentIntent,
payments::payment_attempt::{
PaymentAttempt, PaymentAttemptInterface, PaymentAttemptNew, PaymentAttemptUpdate,
},
};
#[cfg(all(feature = "v2", feature = "payment_v2"))]
#[cfg(feature = "olap")]
use hyperswitch_domain_models::{
behaviour::ReverseConversion, merchant_key_store::MerchantKeyStore,
payments::payment_attempt::PaymentListFilters, payments::PaymentIntent,
};
use redis_interface::HsetnxReply;
use router_env::{instrument, tracing};
@ -45,7 +44,7 @@ use crate::{
#[async_trait::async_trait]
impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn insert_payment_attempt(
&self,
@ -64,7 +63,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
.map(PaymentAttempt::from_storage_model)
}
#[cfg(all(feature = "v2", feature = "payment_v2"))]
#[cfg(feature = "v2")]
#[instrument(skip_all)]
async fn insert_payment_attempt(
&self,
@ -93,7 +92,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
.change_context(errors::StorageError::DecryptionError)
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn update_payment_attempt_with_attempt_id(
&self,
@ -112,7 +111,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
.map(PaymentAttempt::from_storage_model)
}
#[cfg(all(feature = "v2", feature = "payment_v2"))]
#[cfg(feature = "v2")]
#[instrument(skip_all)]
async fn update_payment_attempt_with_attempt_id(
&self,
@ -145,7 +144,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
.change_context(errors::StorageError::DecryptionError)
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_payment_attempt_by_connector_transaction_id_payment_id_merchant_id(
&self,
@ -169,7 +168,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
.map(PaymentAttempt::from_storage_model)
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_payment_attempt_last_successful_attempt_by_payment_id_merchant_id(
&self,
@ -191,7 +190,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
.map(PaymentAttempt::from_storage_model)
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_payment_attempt_last_successful_or_partially_captured_attempt_by_payment_id_merchant_id(
&self,
@ -213,7 +212,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
.map(PaymentAttempt::from_storage_model)
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_payment_attempt_by_merchant_id_connector_txn_id(
&self,
@ -235,7 +234,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
.map(PaymentAttempt::from_storage_model)
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_payment_attempt_by_payment_id_merchant_id_attempt_id(
&self,
@ -260,7 +259,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
.map(PaymentAttempt::from_storage_model)
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(all(feature = "v1", feature = "olap"))]
#[instrument(skip_all)]
async fn get_filters_for_payments(
&self,
@ -268,6 +267,8 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
merchant_id: &common_utils::id_type::MerchantId,
_storage_scheme: MerchantStorageScheme,
) -> CustomResult<PaymentListFilters, errors::StorageError> {
use hyperswitch_domain_models::behaviour::Conversion;
let conn = pg_connection_read(self).await?;
let intents = futures::future::try_join_all(pi.iter().cloned().map(|pi| async {
Conversion::convert(pi)
@ -301,7 +302,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
)
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_payment_attempt_by_preprocessing_id_merchant_id(
&self,
@ -324,7 +325,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
.map(PaymentAttempt::from_storage_model)
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_attempts_by_merchant_id_payment_id(
&self,
@ -346,7 +347,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
})
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_payment_attempt_by_attempt_id_merchant_id(
&self,
@ -365,19 +366,18 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
.map(PaymentAttempt::from_storage_model)
}
#[cfg(all(feature = "v2", feature = "payment_v2"))]
#[cfg(feature = "v2")]
#[instrument(skip_all)]
async fn find_payment_attempt_by_attempt_id_merchant_id(
async fn find_payment_attempt_by_id(
&self,
key_manager_state: &KeyManagerState,
merchant_key_store: &MerchantKeyStore,
attempt_id: &str,
merchant_id: &common_utils::id_type::MerchantId,
_storage_scheme: MerchantStorageScheme,
) -> CustomResult<PaymentAttempt, errors::StorageError> {
) -> error_stack::Result<PaymentAttempt, errors::StorageError> {
let conn = pg_connection_read(self).await?;
DieselPaymentAttempt::find_by_merchant_id_attempt_id(&conn, merchant_id, attempt_id)
DieselPaymentAttempt::find_by_id(&conn, attempt_id)
.await
.map_err(|er| {
let new_err = diesel_error_to_data_error(er.current_context());
@ -392,16 +392,16 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
.change_context(errors::StorageError::DecryptionError)
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(all(feature = "v1", feature = "olap"))]
#[instrument(skip_all)]
async fn get_total_count_of_filtered_payment_attempts(
&self,
merchant_id: &common_utils::id_type::MerchantId,
active_attempt_ids: &[String],
connector: Option<Vec<Connector>>,
payment_method: Option<Vec<PaymentMethod>>,
payment_method_type: Option<Vec<PaymentMethodType>>,
authentication_type: Option<Vec<AuthenticationType>>,
connector: Option<Vec<api_models::enums::Connector>>,
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<common_utils::id_type::MerchantConnectorAccountId>>,
time_range: Option<common_utils::types::TimeRange>,
profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
@ -441,7 +441,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for RouterStore<T> {
#[async_trait::async_trait]
impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn insert_payment_attempt(
&self,
@ -590,7 +590,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
}
}
#[cfg(all(feature = "v2", feature = "payment_v2"))]
#[cfg(feature = "v2")]
#[instrument(skip_all)]
async fn insert_payment_attempt(
&self,
@ -610,7 +610,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
.await
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn update_payment_attempt_with_attempt_id(
&self,
@ -734,7 +734,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
}
}
#[cfg(all(feature = "v2", feature = "payment_v2"))]
#[cfg(feature = "v2")]
#[instrument(skip_all)]
async fn update_payment_attempt_with_attempt_id(
&self,
@ -756,7 +756,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
.await
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_payment_attempt_by_connector_transaction_id_payment_id_merchant_id(
&self,
@ -816,7 +816,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
}
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_payment_attempt_last_successful_attempt_by_payment_id_merchant_id(
&self,
@ -875,7 +875,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
}
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_payment_attempt_last_successful_or_partially_captured_attempt_by_payment_id_merchant_id(
&self,
@ -937,7 +937,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
}
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_payment_attempt_by_merchant_id_connector_txn_id(
&self,
@ -1006,7 +1006,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
}
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_payment_attempt_by_payment_id_merchant_id_attempt_id(
&self,
@ -1060,7 +1060,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
}
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_payment_attempt_by_attempt_id_merchant_id(
&self,
@ -1126,29 +1126,27 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
}
}
#[cfg(all(feature = "v2", feature = "payment_v2"))]
#[cfg(feature = "v2")]
#[instrument(skip_all)]
async fn find_payment_attempt_by_attempt_id_merchant_id(
async fn find_payment_attempt_by_id(
&self,
key_manager_state: &KeyManagerState,
merchant_key_store: &MerchantKeyStore,
attempt_id: &str,
merchant_id: &common_utils::id_type::MerchantId,
storage_scheme: MerchantStorageScheme,
) -> error_stack::Result<PaymentAttempt, errors::StorageError> {
// Ignoring storage scheme for v2 implementation
self.router_store
.find_payment_attempt_by_attempt_id_merchant_id(
.find_payment_attempt_by_id(
key_manager_state,
merchant_key_store,
attempt_id,
merchant_id,
storage_scheme,
)
.await
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_payment_attempt_by_preprocessing_id_merchant_id(
&self,
@ -1217,7 +1215,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
}
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_attempts_by_merchant_id_payment_id(
&self,
@ -1267,7 +1265,7 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
}
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(all(feature = "v1", feature = "olap"))]
#[instrument(skip_all)]
async fn get_filters_for_payments(
&self,
@ -1280,16 +1278,16 @@ impl<T: DatabaseStore> PaymentAttemptInterface for KVRouterStore<T> {
.await
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(all(feature = "v1", feature = "olap"))]
#[instrument(skip_all)]
async fn get_total_count_of_filtered_payment_attempts(
&self,
merchant_id: &common_utils::id_type::MerchantId,
active_attempt_ids: &[String],
connector: Option<Vec<Connector>>,
payment_method: Option<Vec<PaymentMethod>>,
payment_method_type: Option<Vec<PaymentMethodType>>,
authentication_type: Option<Vec<AuthenticationType>>,
connector: Option<Vec<api_models::enums::Connector>>,
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<common_utils::id_type::MerchantConnectorAccountId>>,
time_range: Option<common_utils::types::TimeRange>,
profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
@ -1375,159 +1373,7 @@ impl DataModelExt for MandateDataType {
}
}
#[cfg(all(feature = "v2", feature = "payment_v2"))]
impl DataModelExt for PaymentAttempt {
type StorageModel = DieselPaymentAttempt;
fn to_storage_model(self) -> Self::StorageModel {
DieselPaymentAttempt {
payment_id: self.payment_id,
merchant_id: self.merchant_id,
attempt_id: self.attempt_id,
status: self.status,
amount: self.amount,
net_amount: Some(self.net_amount),
currency: self.currency,
save_to_locker: self.save_to_locker,
connector: self.connector,
error_message: self.error_message,
offer_amount: self.offer_amount,
surcharge_amount: self.surcharge_amount,
tax_amount: self.tax_amount,
payment_method_id: self.payment_method_id,
payment_method: self.payment_method,
connector_transaction_id: self.connector_transaction_id,
capture_method: self.capture_method,
capture_on: self.capture_on,
confirm: self.confirm,
authentication_type: self.authentication_type,
created_at: self.created_at,
modified_at: self.modified_at,
last_synced: self.last_synced,
cancellation_reason: self.cancellation_reason,
amount_to_capture: self.amount_to_capture,
mandate_id: self.mandate_id,
browser_info: self.browser_info,
error_code: self.error_code,
payment_token: self.payment_token,
connector_metadata: self.connector_metadata,
payment_experience: self.payment_experience,
payment_method_type: self.payment_method_type,
card_network: self
.payment_method_data
.as_ref()
.and_then(|data| data.as_object())
.and_then(|card| card.get("card"))
.and_then(|data| data.as_object())
.and_then(|card| card.get("card_network"))
.and_then(|network| network.as_str())
.map(|network| network.to_string()),
payment_method_data: self.payment_method_data,
business_sub_label: self.business_sub_label,
straight_through_algorithm: self.straight_through_algorithm,
preprocessing_step_id: self.preprocessing_step_id,
mandate_details: self.mandate_details.map(|d| d.to_storage_model()),
error_reason: self.error_reason,
multiple_capture_count: self.multiple_capture_count,
connector_response_reference_id: self.connector_response_reference_id,
amount_capturable: self.amount_capturable,
updated_by: self.updated_by,
authentication_data: self.authentication_data,
encoded_data: self.encoded_data,
merchant_connector_id: self.merchant_connector_id,
unified_code: self.unified_code,
unified_message: self.unified_message,
external_three_ds_authentication_attempted: self
.external_three_ds_authentication_attempted,
authentication_connector: self.authentication_connector,
authentication_id: self.authentication_id,
mandate_data: self.mandate_data.map(|d| d.to_storage_model()),
payment_method_billing_address_id: self.payment_method_billing_address_id,
fingerprint_id: self.fingerprint_id,
charge_id: self.charge_id,
client_source: self.client_source,
client_version: self.client_version,
customer_acceptance: self.customer_acceptance,
organization_id: self.organization_id,
profile_id: self.profile_id,
shipping_cost: self.shipping_cost,
order_tax_amount: self.order_tax_amount,
}
}
fn from_storage_model(storage_model: Self::StorageModel) -> Self {
Self {
net_amount: storage_model.get_or_calculate_net_amount(),
payment_id: storage_model.payment_id,
merchant_id: storage_model.merchant_id,
attempt_id: storage_model.attempt_id,
status: storage_model.status,
amount: storage_model.amount,
currency: storage_model.currency,
save_to_locker: storage_model.save_to_locker,
connector: storage_model.connector,
error_message: storage_model.error_message,
offer_amount: storage_model.offer_amount,
surcharge_amount: storage_model.surcharge_amount,
tax_amount: storage_model.tax_amount,
payment_method_id: storage_model.payment_method_id,
payment_method: storage_model.payment_method,
connector_transaction_id: storage_model.connector_transaction_id,
capture_method: storage_model.capture_method,
capture_on: storage_model.capture_on,
confirm: storage_model.confirm,
authentication_type: storage_model.authentication_type,
created_at: storage_model.created_at,
modified_at: storage_model.modified_at,
last_synced: storage_model.last_synced,
cancellation_reason: storage_model.cancellation_reason,
amount_to_capture: storage_model.amount_to_capture,
mandate_id: storage_model.mandate_id,
browser_info: storage_model.browser_info,
error_code: storage_model.error_code,
payment_token: storage_model.payment_token,
connector_metadata: storage_model.connector_metadata,
payment_experience: storage_model.payment_experience,
payment_method_type: storage_model.payment_method_type,
payment_method_data: storage_model.payment_method_data,
business_sub_label: storage_model.business_sub_label,
straight_through_algorithm: storage_model.straight_through_algorithm,
preprocessing_step_id: storage_model.preprocessing_step_id,
mandate_details: storage_model
.mandate_details
.map(MandateDataType::from_storage_model),
error_reason: storage_model.error_reason,
multiple_capture_count: storage_model.multiple_capture_count,
connector_response_reference_id: storage_model.connector_response_reference_id,
amount_capturable: storage_model.amount_capturable,
updated_by: storage_model.updated_by,
authentication_data: storage_model.authentication_data,
encoded_data: storage_model.encoded_data,
merchant_connector_id: storage_model.merchant_connector_id,
unified_code: storage_model.unified_code,
unified_message: storage_model.unified_message,
external_three_ds_authentication_attempted: storage_model
.external_three_ds_authentication_attempted,
authentication_connector: storage_model.authentication_connector,
authentication_id: storage_model.authentication_id,
mandate_data: storage_model
.mandate_data
.map(MandateDetails::from_storage_model),
payment_method_billing_address_id: storage_model.payment_method_billing_address_id,
fingerprint_id: storage_model.fingerprint_id,
charge_id: storage_model.charge_id,
client_source: storage_model.client_source,
client_version: storage_model.client_version,
customer_acceptance: storage_model.customer_acceptance,
organization_id: storage_model.organization_id,
profile_id: storage_model.profile_id,
shipping_cost: storage_model.shipping_cost,
order_tax_amount: storage_model.order_tax_amount,
}
}
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
impl DataModelExt for PaymentAttempt {
type StorageModel = DieselPaymentAttempt;
@ -1679,6 +1525,7 @@ impl DataModelExt for PaymentAttempt {
}
}
#[cfg(feature = "v1")]
impl DataModelExt for PaymentAttemptNew {
type StorageModel = DieselPaymentAttemptNew;
@ -1830,6 +1677,7 @@ impl DataModelExt for PaymentAttemptNew {
}
}
#[cfg(feature = "v1")]
impl DataModelExt for PaymentAttemptUpdate {
type StorageModel = DieselPaymentAttemptUpdate;

View File

@ -12,16 +12,12 @@ use common_utils::{
use diesel::{associations::HasTable, ExpressionMethods, JoinOnDsl, QueryDsl};
#[cfg(feature = "olap")]
use diesel_models::query::generics::db_metrics;
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_v2"),
feature = "olap"
))]
#[cfg(all(feature = "v1", feature = "olap"))]
use diesel_models::schema::{
payment_attempt::{self as payment_attempt_schema, dsl as pa_dsl},
payment_intent::dsl as pi_dsl,
};
#[cfg(all(feature = "v2", feature = "payment_v2", feature = "olap"))]
#[cfg(all(feature = "v2", feature = "olap"))]
use diesel_models::schema_v2::{
payment_attempt::{self as payment_attempt_schema, dsl as pa_dsl},
payment_intent::dsl as pi_dsl,
@ -29,24 +25,23 @@ use diesel_models::schema_v2::{
use diesel_models::{
enums::MerchantStorageScheme,
kv,
payment_attempt::PaymentAttempt as DieselPaymentAttempt,
payment_intent::{
PaymentIntent as DieselPaymentIntent, PaymentIntentUpdate as DieselPaymentIntentUpdate,
},
};
use error_stack::ResultExt;
#[cfg(feature = "olap")]
use hyperswitch_domain_models::payments::payment_intent::PaymentIntentFetchConstraints;
use hyperswitch_domain_models::payments::{
payment_attempt::PaymentAttempt, payment_intent::PaymentIntentFetchConstraints,
};
use hyperswitch_domain_models::{
behaviour::Conversion,
errors::StorageError,
merchant_key_store::MerchantKeyStore,
payments::{
payment_attempt::PaymentAttempt,
payment_intent::{PaymentIntentInterface, PaymentIntentUpdate},
PaymentIntent,
},
RemoteStorageObject,
};
use redis_interface::HsetnxReply;
#[cfg(feature = "olap")]
@ -60,7 +55,7 @@ use crate::{
errors::RedisErrorExt,
redis::kv_store::{decide_storage_scheme, kv_wrapper, KvOperation, Op, PartitionKey},
utils::{self, pg_connection_read, pg_connection_write},
DataModelExt, DatabaseStore, KVRouterStore,
DatabaseStore, KVRouterStore,
};
#[async_trait::async_trait]
@ -285,7 +280,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for KVRouterStore<T> {
}
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_payment_intent_by_payment_id_merchant_id(
&self,
@ -345,7 +340,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for KVRouterStore<T> {
.change_context(StorageError::DecryptionError)
}
#[cfg(all(feature = "v2", feature = "payment_v2"))]
#[cfg(feature = "v2")]
#[instrument(skip_all)]
async fn find_payment_intent_by_id(
&self,
@ -377,38 +372,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for KVRouterStore<T> {
.change_context(StorageError::DecryptionError)
}
async fn get_active_payment_attempt(
&self,
payment: &mut PaymentIntent,
_storage_scheme: MerchantStorageScheme,
) -> error_stack::Result<PaymentAttempt, StorageError> {
match payment.active_attempt.clone() {
RemoteStorageObject::ForeignID(attempt_id) => {
let conn = pg_connection_read(self).await?;
let pa = DieselPaymentAttempt::find_by_merchant_id_attempt_id(
&conn,
&payment.merchant_id,
attempt_id.as_str(),
)
.await
.map_err(|er| {
let new_err = diesel_error_to_data_error(er.current_context());
er.change_context(new_err)
})
.map(PaymentAttempt::from_storage_model)?;
payment.active_attempt = RemoteStorageObject::Object(pa.clone());
Ok(pa)
}
RemoteStorageObject::Object(pa) => Ok(pa.clone()),
}
}
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_v2"),
feature = "olap"
))]
#[cfg(all(feature = "v1", feature = "olap"))]
async fn filter_payment_intent_by_constraints(
&self,
state: &KeyManagerState,
@ -428,11 +392,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for KVRouterStore<T> {
.await
}
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_v2"),
feature = "olap"
))]
#[cfg(all(feature = "v1", feature = "olap"))]
async fn filter_payment_intents_by_time_range_constraints(
&self,
state: &KeyManagerState,
@ -452,11 +412,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for KVRouterStore<T> {
.await
}
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_v2"),
feature = "olap"
))]
#[cfg(all(feature = "v1", feature = "olap"))]
async fn get_intent_status_with_count(
&self,
merchant_id: &common_utils::id_type::MerchantId,
@ -468,11 +424,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for KVRouterStore<T> {
.await
}
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_v2"),
feature = "olap"
))]
#[cfg(all(feature = "v1", feature = "olap"))]
async fn get_filtered_payment_intents_attempt(
&self,
state: &KeyManagerState,
@ -492,11 +444,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for KVRouterStore<T> {
.await
}
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_v2"),
feature = "olap"
))]
#[cfg(all(feature = "v1", feature = "olap"))]
async fn get_filtered_active_attempt_ids_for_total_count(
&self,
merchant_id: &common_utils::id_type::MerchantId,
@ -578,7 +526,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for crate::RouterStore<T> {
.change_context(StorageError::DecryptionError)
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))]
#[cfg(feature = "v1")]
#[instrument(skip_all)]
async fn find_payment_intent_by_payment_id_merchant_id(
&self,
@ -609,7 +557,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for crate::RouterStore<T> {
.await
}
#[cfg(all(feature = "v2", feature = "payment_v2"))]
#[cfg(feature = "v2")]
#[instrument(skip_all)]
async fn find_payment_intent_by_id(
&self,
@ -638,39 +586,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for crate::RouterStore<T> {
.change_context(StorageError::DecryptionError)
}
#[instrument(skip_all)]
async fn get_active_payment_attempt(
&self,
payment: &mut PaymentIntent,
_storage_scheme: MerchantStorageScheme,
) -> error_stack::Result<PaymentAttempt, StorageError> {
match &payment.active_attempt {
RemoteStorageObject::ForeignID(attempt_id) => {
let conn = pg_connection_read(self).await?;
let pa = DieselPaymentAttempt::find_by_merchant_id_attempt_id(
&conn,
&payment.merchant_id,
attempt_id.as_str(),
)
.await
.map_err(|er| {
let new_err = diesel_error_to_data_error(er.current_context());
er.change_context(new_err)
})
.map(PaymentAttempt::from_storage_model)?;
payment.active_attempt = RemoteStorageObject::Object(pa.clone());
Ok(pa)
}
RemoteStorageObject::Object(pa) => Ok(pa.clone()),
}
}
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_v2"),
feature = "olap"
))]
#[cfg(all(feature = "v1", feature = "olap"))]
#[instrument(skip_all)]
async fn filter_payment_intent_by_constraints(
&self,
@ -796,11 +712,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for crate::RouterStore<T> {
.await
}
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_v2"),
feature = "olap"
))]
#[cfg(all(feature = "v1", feature = "olap"))]
#[instrument(skip_all)]
async fn filter_payment_intents_by_time_range_constraints(
&self,
@ -822,11 +734,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for crate::RouterStore<T> {
.await
}
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_v2"),
feature = "olap"
))]
#[cfg(all(feature = "v1", feature = "olap"))]
#[instrument(skip_all)]
async fn get_intent_status_with_count(
&self,
@ -870,11 +778,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for crate::RouterStore<T> {
})
}
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_v2"),
feature = "olap"
))]
#[cfg(all(feature = "v1", feature = "olap"))]
#[instrument(skip_all)]
async fn get_filtered_payment_intents_attempt(
&self,
@ -886,6 +790,8 @@ impl<T: DatabaseStore> PaymentIntentInterface for crate::RouterStore<T> {
) -> error_stack::Result<Vec<(PaymentIntent, PaymentAttempt)>, StorageError> {
use futures::{future::try_join_all, FutureExt};
use crate::DataModelExt;
let conn = connection::pg_connection_read(self).await.switch()?;
let conn = async_bb8_diesel::Connection::as_async_conn(&conn);
let mut query = DieselPaymentIntent::table()
@ -1040,7 +946,10 @@ impl<T: DatabaseStore> PaymentIntentInterface for crate::RouterStore<T> {
logger::debug!(filter = %diesel::debug_query::<diesel::pg::Pg,_>(&query).to_string());
query
.get_results_async::<(DieselPaymentIntent, DieselPaymentAttempt)>(conn)
.get_results_async::<(
DieselPaymentIntent,
diesel_models::payment_attempt::PaymentAttempt,
)>(conn)
.await
.map(|results| {
try_join_all(results.into_iter().map(|(pi, pa)| {
@ -1067,11 +976,7 @@ impl<T: DatabaseStore> PaymentIntentInterface for crate::RouterStore<T> {
.await
}
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_v2"),
feature = "olap"
))]
#[cfg(all(feature = "v1", feature = "olap"))]
#[instrument(skip_all)]
async fn get_filtered_active_attempt_ids_for_total_count(
&self,