refactor(core): Adapt the usage of routing_algorithm_id in routing and payments core for v2 (#5533)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Amisha Prabhat
2024-08-12 14:56:51 +05:30
committed by GitHub
parent 6a5b49397a
commit 61de3e025a
21 changed files with 897 additions and 435 deletions

View File

@ -1,21 +1,19 @@
pub mod helpers;
pub mod transformers;
#[cfg(all(feature = "v2", feature = "routing_v2"))]
use api_models::routing::RoutingConfigRequest;
use api_models::{
enums,
routing::{self as routing_types, RoutingRetrieveLinkQuery, RoutingRetrieveQuery},
routing::{self as routing_types, RoutingRetrieveQuery},
};
use diesel_models::routing_algorithm::RoutingAlgorithm;
use error_stack::ResultExt;
#[cfg(all(feature = "v2", feature = "routing_v2"))]
use masking::Secret;
use rustc_hash::FxHashSet;
use super::payments;
#[cfg(feature = "payouts")]
use super::payouts;
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "routing_v2")))]
use crate::utils::ValueExt;
use crate::{
consts,
core::{
@ -28,10 +26,13 @@ use crate::{
domain,
transformers::{ForeignInto, ForeignTryFrom},
},
utils::{self, OptionExt, ValueExt},
utils::{self, OptionExt},
};
#[cfg(all(feature = "v2", feature = "routing_v2"))]
use crate::{core::errors::RouterResult, db::StorageInterface};
use crate::{
core::{admin, errors::RouterResult},
db::StorageInterface,
};
pub enum TransactionData<'a, F>
where
F: Clone,
@ -47,7 +48,7 @@ struct RoutingAlgorithmUpdate(RoutingAlgorithm);
#[cfg(all(feature = "v2", feature = "routing_v2"))]
impl RoutingAlgorithmUpdate {
pub fn create_new_routing_algorithm(
request: &RoutingConfigRequest,
request: &routing_types::RoutingConfigRequest,
merchant_id: &common_utils::id_type::MerchantId,
profile_id: String,
transaction_type: &enums::TransactionType,
@ -82,32 +83,6 @@ impl RoutingAlgorithmUpdate {
.change_context(errors::ApiErrorResponse::ResourceIdNotFound)?;
Ok(Self(routing_algo))
}
pub fn update_routing_ref_with_algorithm_id(
&self,
transaction_type: &enums::TransactionType,
routing_ref: &mut routing_types::RoutingAlgorithmRef,
) -> RouterResult<()> {
utils::when(self.0.algorithm_for != *transaction_type, || {
Err(errors::ApiErrorResponse::PreconditionFailed {
message: format!(
"Cannot use {}'s routing algorithm for {} operation",
self.0.algorithm_for, transaction_type
),
})
})?;
utils::when(
routing_ref.algorithm_id == Some(self.0.algorithm_id.clone()),
|| {
Err(errors::ApiErrorResponse::PreconditionFailed {
message: "Algorithm is already active".to_string(),
})
},
)?;
routing_ref.update_algorithm_id(self.0.algorithm_id.clone());
Ok(())
}
}
pub async fn retrieve_merchant_routing_dictionary(
@ -140,11 +115,11 @@ pub async fn retrieve_merchant_routing_dictionary(
}
#[cfg(all(feature = "v2", feature = "routing_v2"))]
pub async fn create_routing_config(
pub async fn create_routing_algorithm_under_profile(
state: SessionState,
merchant_account: domain::MerchantAccount,
key_store: domain::MerchantKeyStore,
request: RoutingConfigRequest,
request: routing_types::RoutingConfigRequest,
transaction_type: &enums::TransactionType,
) -> RouterResponse<routing_types::RoutingDictionaryRecord> {
metrics::ROUTING_CREATE_REQUEST_RECEIVED.add(&metrics::CONTEXT, 1, &[]);
@ -170,7 +145,7 @@ pub async fn create_routing_config(
let name_mca_id_set = helpers::ConnectNameAndMCAIdForProfile(
all_mcas.filter_by_profile(&business_profile.profile_id, |mca| {
(&mca.connector_name, &mca.id)
(&mca.connector_name, mca.get_id())
}),
);
@ -207,7 +182,7 @@ pub async fn create_routing_config(
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "routing_v2")))]
pub async fn create_routing_config(
pub async fn create_routing_algorithm_under_profile(
state: SessionState,
merchant_account: domain::MerchantAccount,
key_store: domain::MerchantKeyStore,
@ -295,8 +270,12 @@ pub async fn create_routing_config(
Ok(service_api::ApplicationResponse::Json(new_record))
}
#[cfg(all(feature = "v2", feature = "routing_v2"))]
pub async fn link_routing_config(
#[cfg(all(
feature = "v2",
feature = "routing_v2",
feature = "business_profile_v2"
))]
pub async fn link_routing_config_under_profile(
state: SessionState,
merchant_account: domain::MerchantAccount,
key_store: domain::MerchantKeyStore,
@ -328,31 +307,47 @@ pub async fn link_routing_config(
.await?
.get_required_value("BusinessProfile")?;
let mut routing_ref = routing_types::RoutingAlgorithmRef::parse_routing_algorithm(
business_profile.routing_algorithm.clone().map(Secret::new),
)
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("unable to deserialize routing algorithm ref from merchant account")?
.unwrap_or_default();
utils::when(
routing_algorithm.0.algorithm_for != *transaction_type,
|| {
Err(errors::ApiErrorResponse::PreconditionFailed {
message: format!(
"Cannot use {}'s routing algorithm for {} operation",
routing_algorithm.0.algorithm_for, transaction_type
),
})
},
)?;
routing_algorithm.update_routing_ref_with_algorithm_id(transaction_type, &mut routing_ref)?;
utils::when(
business_profile.routing_algorithm_id == Some(algorithm_id.clone())
|| business_profile.payout_routing_algorithm_id == Some(algorithm_id.clone()),
|| {
Err(errors::ApiErrorResponse::PreconditionFailed {
message: "Algorithm is already active".to_string(),
})
},
)?;
admin::BusinessProfileWrapper::new(business_profile)
.update_business_profile_and_invalidate_routing_config_for_active_algorithm_id_update(
db,
key_manager_state,
&key_store,
algorithm_id,
transaction_type,
)
.await?;
helpers::update_business_profile_active_algorithm_ref(
db,
key_manager_state,
&key_store,
business_profile,
routing_ref,
transaction_type,
)
.await?;
metrics::ROUTING_LINK_CONFIG_SUCCESS_RESPONSE.add(&metrics::CONTEXT, 1, &[]);
Ok(service_api::ApplicationResponse::Json(
routing_algorithm.0.foreign_into(),
))
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "routing_v2")))]
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(any(feature = "routing_v2", feature = "business_profile_v2"))
))]
pub async fn link_routing_config(
state: SessionState,
merchant_account: domain::MerchantAccount,
@ -428,8 +423,8 @@ pub async fn link_routing_config(
))
}
#[cfg(all(feature = "v2", feature = "routing_v2"))]
pub async fn retrieve_routing_config(
#[cfg(all(feature = "v2", feature = "routing_v2",))]
pub async fn retrieve_active_routing_config(
state: SessionState,
merchant_account: domain::MerchantAccount,
key_store: domain::MerchantKeyStore,
@ -462,7 +457,7 @@ pub async fn retrieve_routing_config(
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "routing_v2")))]
pub async fn retrieve_routing_config(
pub async fn retrieve_active_routing_config(
state: SessionState,
merchant_account: domain::MerchantAccount,
key_store: domain::MerchantKeyStore,
@ -499,8 +494,12 @@ pub async fn retrieve_routing_config(
Ok(service_api::ApplicationResponse::Json(response))
}
#[cfg(all(feature = "v2", feature = "routing_v2"))]
pub async fn unlink_routing_config(
#[cfg(all(
feature = "v2",
feature = "routing_v2",
feature = "business_profile_v2"
))]
pub async fn unlink_routing_config_under_profile(
state: SessionState,
merchant_account: domain::MerchantAccount,
key_store: domain::MerchantKeyStore,
@ -521,27 +520,13 @@ pub async fn unlink_routing_config(
.await?
.get_required_value("BusinessProfile")?;
let routing_algo_ref = routing_types::RoutingAlgorithmRef::parse_routing_algorithm(
match transaction_type {
enums::TransactionType::Payment => business_profile.routing_algorithm.clone(),
#[cfg(feature = "payouts")]
enums::TransactionType::Payout => business_profile.payout_routing_algorithm.clone(),
}
.map(Secret::new),
)
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("unable to deserialize routing algorithm ref from merchant account")?
.unwrap_or_default();
let routing_algo_id = match transaction_type {
enums::TransactionType::Payment => business_profile.routing_algorithm_id.clone(),
#[cfg(feature = "payouts")]
enums::TransactionType::Payout => business_profile.payout_routing_algorithm_id.clone(),
};
if let Some(algorithm_id) = routing_algo_ref.algorithm_id {
let timestamp = common_utils::date_time::now_unix_timestamp();
let routing_algorithm: routing_types::RoutingAlgorithmRef =
routing_types::RoutingAlgorithmRef {
algorithm_id: None,
timestamp,
config_algo_id: routing_algo_ref.config_algo_id.clone(),
surcharge_config_algo_id: routing_algo_ref.surcharge_config_algo_id,
};
if let Some(algorithm_id) = routing_algo_id {
let record = RoutingAlgorithmUpdate::fetch_routing_algo(
merchant_account.get_id(),
&algorithm_id,
@ -549,16 +534,15 @@ pub async fn unlink_routing_config(
)
.await?;
let response = record.0.foreign_into();
helpers::update_business_profile_active_algorithm_ref(
db,
key_manager_state,
&key_store,
business_profile,
routing_algorithm,
transaction_type,
)
.await?;
admin::BusinessProfileWrapper::new(business_profile)
.update_business_profile_and_invalidate_routing_config_for_active_algorithm_id_update(
db,
key_manager_state,
&key_store,
algorithm_id,
transaction_type,
)
.await?;
metrics::ROUTING_UNLINK_CONFIG_SUCCESS_RESPONSE.add(&metrics::CONTEXT, 1, &[]);
Ok(service_api::ApplicationResponse::Json(response))
} else {
@ -568,7 +552,10 @@ pub async fn unlink_routing_config(
}
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "routing_v2")))]
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(any(feature = "routing_v2", feature = "business_profile_v2"))
))]
pub async fn unlink_routing_config(
state: SessionState,
merchant_account: domain::MerchantAccount,
@ -726,11 +713,63 @@ pub async fn retrieve_default_routing_config(
})
}
#[cfg(all(
feature = "v2",
feature = "routing_v2",
feature = "business_profile_v2"
))]
pub async fn retrieve_routing_config_under_profile(
state: SessionState,
merchant_account: domain::MerchantAccount,
key_store: domain::MerchantKeyStore,
query_params: RoutingRetrieveQuery,
profile_id: String,
transaction_type: &enums::TransactionType,
) -> RouterResponse<routing_types::LinkedRoutingConfigRetrieveResponse> {
metrics::ROUTING_RETRIEVE_LINK_CONFIG.add(&metrics::CONTEXT, 1, &[]);
let db = state.store.as_ref();
let key_manager_state = &(&state).into();
let business_profile = core_utils::validate_and_get_business_profile(
db,
key_manager_state,
&key_store,
Some(&profile_id),
merchant_account.get_id(),
)
.await?
.get_required_value("BusinessProfile")?;
let record = db
.list_routing_algorithm_metadata_by_profile_id(
&business_profile.profile_id,
i64::from(query_params.limit.unwrap_or_default()),
i64::from(query_params.offset.unwrap_or_default()),
)
.await
.to_not_found_response(errors::ApiErrorResponse::ResourceIdNotFound)?;
let active_algorithms = record
.into_iter()
.filter(|routing_rec| &routing_rec.algorithm_for == transaction_type)
.map(|routing_algo| routing_algo.foreign_into())
.collect::<Vec<_>>();
metrics::ROUTING_RETRIEVE_LINK_CONFIG_SUCCESS_RESPONSE.add(&metrics::CONTEXT, 1, &[]);
Ok(service_api::ApplicationResponse::Json(
routing_types::LinkedRoutingConfigRetrieveResponse::ProfileBased(active_algorithms),
))
}
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(any(feature = "routing_v2", feature = "business_profile_v2"))
))]
pub async fn retrieve_linked_routing_config(
state: SessionState,
merchant_account: domain::MerchantAccount,
key_store: domain::MerchantKeyStore,
query_params: RoutingRetrieveLinkQuery,
query_params: routing_types::RoutingRetrieveLinkQuery,
transaction_type: &enums::TransactionType,
) -> RouterResponse<routing_types::LinkedRoutingConfigRetrieveResponse> {
metrics::ROUTING_RETRIEVE_LINK_CONFIG.add(&metrics::CONTEXT, 1, &[]);