mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-03 21:37:41 +08:00
feat(router): Default configs and toggle api for dynamic routing feature (#5830)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@ -3478,6 +3478,7 @@ impl BusinessProfileCreateBridge for api::BusinessProfileCreate {
|
||||
.always_collect_billing_details_from_wallet_connector,
|
||||
always_collect_shipping_details_from_wallet_connector: self
|
||||
.always_collect_shipping_details_from_wallet_connector,
|
||||
dynamic_routing_algorithm: None,
|
||||
},
|
||||
))
|
||||
}
|
||||
@ -3825,6 +3826,7 @@ impl BusinessProfileUpdateBridge for api::BusinessProfileUpdate {
|
||||
.always_collect_shipping_details_from_wallet_connector,
|
||||
tax_connector_id: self.tax_connector_id,
|
||||
is_tax_connector_enabled: self.is_tax_connector_enabled,
|
||||
dynamic_routing_algorithm: self.dynamic_routing_algorithm,
|
||||
},
|
||||
)))
|
||||
}
|
||||
|
||||
@ -923,12 +923,12 @@ impl<F: Clone + Send> Domain<F, api::PaymentsRequest, PaymentData<F>> for Paymen
|
||||
Some(helpers::PaymentExternalAuthenticationFlow::PostAuthenticationFlow {
|
||||
authentication_id,
|
||||
}) => {
|
||||
let authentication = authentication::perform_post_authentication(
|
||||
let authentication = Box::pin(authentication::perform_post_authentication(
|
||||
state,
|
||||
key_store,
|
||||
business_profile.clone(),
|
||||
authentication_id.clone(),
|
||||
)
|
||||
))
|
||||
.await?;
|
||||
//If authentication is not successful, skip the payment connector flows and mark the payment as failure
|
||||
if authentication.authentication_status
|
||||
|
||||
@ -2,12 +2,13 @@ pub mod helpers;
|
||||
pub mod transformers;
|
||||
|
||||
use api_models::{
|
||||
enums, mandates as mandates_api,
|
||||
enums, mandates as mandates_api, routing,
|
||||
routing::{self as routing_types, RoutingRetrieveQuery},
|
||||
};
|
||||
use diesel_models::routing_algorithm::RoutingAlgorithm;
|
||||
use error_stack::ResultExt;
|
||||
use hyperswitch_domain_models::{mandates, payment_address};
|
||||
use router_env::metrics::add_attributes;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
@ -411,42 +412,89 @@ pub async fn link_routing_config(
|
||||
|
||||
core_utils::validate_profile_id_from_auth_layer(authentication_profile_id, &business_profile)?;
|
||||
|
||||
let mut routing_ref: routing_types::RoutingAlgorithmRef = business_profile
|
||||
.routing_algorithm
|
||||
.clone()
|
||||
.map(|val| val.parse_value("RoutingAlgorithmRef"))
|
||||
.transpose()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("unable to deserialize routing algorithm ref from merchant account")?
|
||||
.unwrap_or_default();
|
||||
match routing_algorithm.kind {
|
||||
diesel_models::enums::RoutingAlgorithmKind::Dynamic => {
|
||||
let mut dynamic_routing_ref: routing_types::DynamicRoutingAlgorithmRef =
|
||||
business_profile
|
||||
.dynamic_routing_algorithm
|
||||
.clone()
|
||||
.map(|val| val.parse_value("DynamicRoutingAlgorithmRef"))
|
||||
.transpose()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable(
|
||||
"unable to deserialize Dynamic routing algorithm ref from business profile",
|
||||
)?
|
||||
.unwrap_or_default();
|
||||
|
||||
utils::when(routing_algorithm.algorithm_for != *transaction_type, || {
|
||||
Err(errors::ApiErrorResponse::PreconditionFailed {
|
||||
message: format!(
|
||||
"Cannot use {}'s routing algorithm for {} operation",
|
||||
routing_algorithm.algorithm_for, transaction_type
|
||||
),
|
||||
})
|
||||
})?;
|
||||
utils::when(
|
||||
matches!(
|
||||
dynamic_routing_ref.success_based_algorithm,
|
||||
Some(routing_types::DynamicAlgorithmWithTimestamp {
|
||||
algorithm_id: Some(ref id),
|
||||
timestamp: _
|
||||
}) if id == &algorithm_id
|
||||
),
|
||||
|| {
|
||||
Err(errors::ApiErrorResponse::PreconditionFailed {
|
||||
message: "Algorithm is already active".to_string(),
|
||||
})
|
||||
},
|
||||
)?;
|
||||
|
||||
utils::when(
|
||||
routing_ref.algorithm_id == Some(algorithm_id.clone()),
|
||||
|| {
|
||||
Err(errors::ApiErrorResponse::PreconditionFailed {
|
||||
message: "Algorithm is already active".to_string(),
|
||||
})
|
||||
},
|
||||
)?;
|
||||
routing_ref.update_algorithm_id(algorithm_id);
|
||||
helpers::update_business_profile_active_algorithm_ref(
|
||||
db,
|
||||
key_manager_state,
|
||||
&key_store,
|
||||
business_profile,
|
||||
routing_ref,
|
||||
transaction_type,
|
||||
)
|
||||
.await?;
|
||||
dynamic_routing_ref.update_algorithm_id(algorithm_id);
|
||||
helpers::update_business_profile_active_dynamic_algorithm_ref(
|
||||
db,
|
||||
key_manager_state,
|
||||
&key_store,
|
||||
business_profile,
|
||||
dynamic_routing_ref,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
diesel_models::enums::RoutingAlgorithmKind::Single
|
||||
| diesel_models::enums::RoutingAlgorithmKind::Priority
|
||||
| diesel_models::enums::RoutingAlgorithmKind::Advanced
|
||||
| diesel_models::enums::RoutingAlgorithmKind::VolumeSplit => {
|
||||
let mut routing_ref: routing_types::RoutingAlgorithmRef = business_profile
|
||||
.routing_algorithm
|
||||
.clone()
|
||||
.map(|val| val.parse_value("RoutingAlgorithmRef"))
|
||||
.transpose()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable(
|
||||
"unable to deserialize routing algorithm ref from business profile",
|
||||
)?
|
||||
.unwrap_or_default();
|
||||
|
||||
utils::when(routing_algorithm.algorithm_for != *transaction_type, || {
|
||||
Err(errors::ApiErrorResponse::PreconditionFailed {
|
||||
message: format!(
|
||||
"Cannot use {}'s routing algorithm for {} operation",
|
||||
routing_algorithm.algorithm_for, transaction_type
|
||||
),
|
||||
})
|
||||
})?;
|
||||
|
||||
utils::when(
|
||||
routing_ref.algorithm_id == Some(algorithm_id.clone()),
|
||||
|| {
|
||||
Err(errors::ApiErrorResponse::PreconditionFailed {
|
||||
message: "Algorithm is already active".to_string(),
|
||||
})
|
||||
},
|
||||
)?;
|
||||
routing_ref.update_algorithm_id(algorithm_id);
|
||||
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(
|
||||
@ -1111,3 +1159,192 @@ pub async fn update_default_routing_config_for_profile(
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1")]
|
||||
pub async fn toggle_success_based_routing(
|
||||
state: SessionState,
|
||||
merchant_account: domain::MerchantAccount,
|
||||
key_store: domain::MerchantKeyStore,
|
||||
status: bool,
|
||||
profile_id: common_utils::id_type::ProfileId,
|
||||
) -> RouterResponse<routing_types::RoutingDictionaryRecord> {
|
||||
metrics::ROUTING_CREATE_REQUEST_RECEIVED.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&add_attributes([("profile_id", profile_id.get_string_repr().to_owned())]),
|
||||
);
|
||||
let db = state.store.as_ref();
|
||||
let key_manager_state = &(&state).into();
|
||||
|
||||
let business_profile: domain::BusinessProfile = 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")
|
||||
.change_context(errors::ApiErrorResponse::BusinessProfileNotFound {
|
||||
id: profile_id.get_string_repr().to_owned(),
|
||||
})?;
|
||||
|
||||
let mut success_based_dynamic_routing_algo_ref: routing_types::DynamicRoutingAlgorithmRef =
|
||||
business_profile
|
||||
.dynamic_routing_algorithm
|
||||
.clone()
|
||||
.map(|val| val.parse_value("DynamicRoutingAlgorithmRef"))
|
||||
.transpose()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable(
|
||||
"unable to deserialize dynamic routing algorithm ref from business profile",
|
||||
)?
|
||||
.unwrap_or_default();
|
||||
|
||||
if status {
|
||||
let default_success_based_routing_config = routing::SuccessBasedRoutingConfig::default();
|
||||
let algorithm_id = common_utils::generate_routing_id_of_default_length();
|
||||
let timestamp = common_utils::date_time::now();
|
||||
let algo = RoutingAlgorithm {
|
||||
algorithm_id: algorithm_id.clone(),
|
||||
profile_id: business_profile.get_id().to_owned(),
|
||||
merchant_id: merchant_account.get_id().to_owned(),
|
||||
name: "Dynamic routing algorithm".to_string(),
|
||||
description: None,
|
||||
kind: diesel_models::enums::RoutingAlgorithmKind::Dynamic,
|
||||
algorithm_data: serde_json::json!(default_success_based_routing_config),
|
||||
created_at: timestamp,
|
||||
modified_at: timestamp,
|
||||
algorithm_for: common_enums::TransactionType::Payment,
|
||||
};
|
||||
|
||||
let record = db
|
||||
.insert_routing_algorithm(algo)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Unable to insert record in routing algorithm table")?;
|
||||
|
||||
success_based_dynamic_routing_algo_ref.update_algorithm_id(algorithm_id);
|
||||
helpers::update_business_profile_active_dynamic_algorithm_ref(
|
||||
db,
|
||||
key_manager_state,
|
||||
&key_store,
|
||||
business_profile,
|
||||
success_based_dynamic_routing_algo_ref,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let new_record = record.foreign_into();
|
||||
|
||||
metrics::ROUTING_CREATE_SUCCESS_RESPONSE.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&add_attributes([("profile_id", profile_id.get_string_repr().to_owned())]),
|
||||
);
|
||||
Ok(service_api::ApplicationResponse::Json(new_record))
|
||||
} else {
|
||||
let timestamp = common_utils::date_time::now_unix_timestamp();
|
||||
match success_based_dynamic_routing_algo_ref.success_based_algorithm {
|
||||
Some(algorithm_ref) => {
|
||||
if let Some(algorithm_id) = algorithm_ref.algorithm_id {
|
||||
let dynamic_routing_algorithm = routing_types::DynamicRoutingAlgorithmRef {
|
||||
success_based_algorithm: Some(
|
||||
routing_types::DynamicAlgorithmWithTimestamp {
|
||||
algorithm_id: None,
|
||||
timestamp,
|
||||
},
|
||||
),
|
||||
};
|
||||
|
||||
let record = db
|
||||
.find_routing_algorithm_by_profile_id_algorithm_id(
|
||||
business_profile.get_id(),
|
||||
&algorithm_id,
|
||||
)
|
||||
.await
|
||||
.to_not_found_response(errors::ApiErrorResponse::ResourceIdNotFound)?;
|
||||
let response = record.foreign_into();
|
||||
helpers::update_business_profile_active_dynamic_algorithm_ref(
|
||||
db,
|
||||
key_manager_state,
|
||||
&key_store,
|
||||
business_profile,
|
||||
dynamic_routing_algorithm,
|
||||
)
|
||||
.await?;
|
||||
|
||||
metrics::ROUTING_UNLINK_CONFIG_SUCCESS_RESPONSE.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&add_attributes([("profile_id", profile_id.get_string_repr().to_owned())]),
|
||||
);
|
||||
|
||||
Ok(service_api::ApplicationResponse::Json(response))
|
||||
} else {
|
||||
Err(errors::ApiErrorResponse::PreconditionFailed {
|
||||
message: "Algorithm is already inactive".to_string(),
|
||||
})?
|
||||
}
|
||||
}
|
||||
None => Err(errors::ApiErrorResponse::PreconditionFailed {
|
||||
message: "Algorithm is already inactive".to_string(),
|
||||
})?,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1")]
|
||||
pub async fn success_based_routing_update_configs(
|
||||
state: SessionState,
|
||||
request: routing_types::SuccessBasedRoutingConfig,
|
||||
algorithm_id: common_utils::id_type::RoutingId,
|
||||
profile_id: common_utils::id_type::ProfileId,
|
||||
) -> RouterResponse<routing_types::RoutingDictionaryRecord> {
|
||||
metrics::ROUTING_UPDATE_CONFIG_FOR_PROFILE.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&add_attributes([("profile_id", profile_id.get_string_repr().to_owned())]),
|
||||
);
|
||||
let db = state.store.as_ref();
|
||||
let dynamic_routing_algo_to_update = db
|
||||
.find_routing_algorithm_by_profile_id_algorithm_id(&profile_id, &algorithm_id)
|
||||
.await
|
||||
.to_not_found_response(errors::ApiErrorResponse::ResourceIdNotFound)?;
|
||||
|
||||
let mut config_to_update: routing::SuccessBasedRoutingConfig = dynamic_routing_algo_to_update
|
||||
.algorithm_data
|
||||
.parse_value::<routing::SuccessBasedRoutingConfig>("SuccessBasedRoutingConfig")
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("unable to deserialize algorithm data from routing table into SuccessBasedRoutingConfig")?;
|
||||
|
||||
config_to_update.update(request);
|
||||
|
||||
let algorithm_id = common_utils::generate_routing_id_of_default_length();
|
||||
let timestamp = common_utils::date_time::now();
|
||||
let algo = RoutingAlgorithm {
|
||||
algorithm_id,
|
||||
profile_id: dynamic_routing_algo_to_update.profile_id,
|
||||
merchant_id: dynamic_routing_algo_to_update.merchant_id,
|
||||
name: dynamic_routing_algo_to_update.name,
|
||||
description: dynamic_routing_algo_to_update.description,
|
||||
kind: dynamic_routing_algo_to_update.kind,
|
||||
algorithm_data: serde_json::json!(config_to_update),
|
||||
created_at: timestamp,
|
||||
modified_at: timestamp,
|
||||
algorithm_for: dynamic_routing_algo_to_update.algorithm_for,
|
||||
};
|
||||
let record = db
|
||||
.insert_routing_algorithm(algo)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Unable to insert record in routing algorithm table")?;
|
||||
|
||||
let new_record = record.foreign_into();
|
||||
|
||||
metrics::ROUTING_UPDATE_CONFIG_FOR_PROFILE_SUCCESS_RESPONSE.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&add_attributes([("profile_id", profile_id.get_string_repr().to_owned())]),
|
||||
);
|
||||
Ok(service_api::ApplicationResponse::Json(new_record))
|
||||
}
|
||||
|
||||
@ -236,6 +236,33 @@ pub async fn update_business_profile_active_algorithm_ref(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1")]
|
||||
pub async fn update_business_profile_active_dynamic_algorithm_ref(
|
||||
db: &dyn StorageInterface,
|
||||
key_manager_state: &KeyManagerState,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
current_business_profile: domain::BusinessProfile,
|
||||
dynamic_routing_algorithm: routing_types::DynamicRoutingAlgorithmRef,
|
||||
) -> RouterResult<()> {
|
||||
let ref_val = dynamic_routing_algorithm
|
||||
.encode_to_value()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to convert dynamic routing ref to value")?;
|
||||
let business_profile_update = domain::BusinessProfileUpdate::DynamicRoutingAlgorithmUpdate {
|
||||
dynamic_routing_algorithm: Some(ref_val),
|
||||
};
|
||||
db.update_business_profile_by_profile_id(
|
||||
key_manager_state,
|
||||
merchant_key_store,
|
||||
current_business_profile,
|
||||
business_profile_update,
|
||||
)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to update dynamic routing algorithm ref in business profile")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RoutingAlgorithmHelpers<'h> {
|
||||
|
||||
@ -72,6 +72,7 @@ impl ForeignFrom<storage_enums::RoutingAlgorithmKind> for RoutingAlgorithmKind {
|
||||
storage_enums::RoutingAlgorithmKind::Priority => Self::Priority,
|
||||
storage_enums::RoutingAlgorithmKind::VolumeSplit => Self::VolumeSplit,
|
||||
storage_enums::RoutingAlgorithmKind::Advanced => Self::Advanced,
|
||||
storage_enums::RoutingAlgorithmKind::Dynamic => Self::Dynamic,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -83,6 +84,7 @@ impl ForeignFrom<RoutingAlgorithmKind> for storage_enums::RoutingAlgorithmKind {
|
||||
RoutingAlgorithmKind::Priority => Self::Priority,
|
||||
RoutingAlgorithmKind::VolumeSplit => Self::VolumeSplit,
|
||||
RoutingAlgorithmKind::Advanced => Self::Advanced,
|
||||
RoutingAlgorithmKind::Dynamic => Self::Dynamic,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1626,6 +1626,23 @@ impl BusinessProfile {
|
||||
)
|
||||
.service(
|
||||
web::scope("/{profile_id}")
|
||||
.service(
|
||||
web::scope("/dynamic_routing").service(
|
||||
web::scope("/success_based")
|
||||
.service(
|
||||
web::resource("/toggle").route(
|
||||
web::post().to(routing::toggle_success_based_routing),
|
||||
),
|
||||
)
|
||||
.service(web::resource("/config/{algorithm_id}").route(
|
||||
web::patch().to(|state, req, path, payload| {
|
||||
routing::success_based_routing_update_configs(
|
||||
state, req, path, payload,
|
||||
)
|
||||
}),
|
||||
)),
|
||||
),
|
||||
)
|
||||
.service(
|
||||
web::resource("")
|
||||
.route(web::get().to(admin::business_profile_retrieve))
|
||||
|
||||
@ -65,6 +65,8 @@ impl From<Flow> for ApiIdentifier {
|
||||
| Flow::RoutingDeleteConfig
|
||||
| Flow::DecisionManagerDeleteConfig
|
||||
| Flow::DecisionManagerRetrieveConfig
|
||||
| Flow::ToggleDynamicRouting
|
||||
| Flow::UpdateDynamicRoutingConfigs
|
||||
| Flow::DecisionManagerUpsertConfig => Self::Routing,
|
||||
|
||||
Flow::RetrieveForexFlow => Self::Forex,
|
||||
|
||||
@ -978,3 +978,88 @@ pub async fn routing_update_default_config_for_profile(
|
||||
))
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "olap", feature = "v1"))]
|
||||
#[instrument(skip_all)]
|
||||
pub async fn toggle_success_based_routing(
|
||||
state: web::Data<AppState>,
|
||||
req: HttpRequest,
|
||||
query: web::Query<api_models::routing::ToggleSuccessBasedRoutingQuery>,
|
||||
path: web::Path<routing_types::ToggleSuccessBasedRoutingPath>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::ToggleDynamicRouting;
|
||||
let wrapper = routing_types::ToggleSuccessBasedRoutingWrapper {
|
||||
status: query.into_inner().status,
|
||||
profile_id: path.into_inner().profile_id,
|
||||
};
|
||||
Box::pin(oss_api::server_wrap(
|
||||
flow,
|
||||
state,
|
||||
&req,
|
||||
wrapper.clone(),
|
||||
|state,
|
||||
auth: auth::AuthenticationData,
|
||||
wrapper: routing_types::ToggleSuccessBasedRoutingWrapper,
|
||||
_| {
|
||||
routing::toggle_success_based_routing(
|
||||
state,
|
||||
auth.merchant_account,
|
||||
auth.key_store,
|
||||
wrapper.status,
|
||||
wrapper.profile_id,
|
||||
)
|
||||
},
|
||||
#[cfg(not(feature = "release"))]
|
||||
auth::auth_type(
|
||||
&auth::HeaderAuth(auth::ApiKeyAuth),
|
||||
&auth::JWTAuthProfileFromRoute {
|
||||
profile_id: wrapper.profile_id,
|
||||
required_permission: Permission::RoutingWrite,
|
||||
minimum_entity_level: EntityType::Merchant,
|
||||
},
|
||||
req.headers(),
|
||||
),
|
||||
#[cfg(feature = "release")]
|
||||
&auth::JWTAuthProfileFromRoute {
|
||||
profile_id: wrapper.profile_id,
|
||||
required_permission: Permission::RoutingWrite,
|
||||
minimum_entity_level: EntityType::Merchant,
|
||||
},
|
||||
api_locking::LockAction::NotApplicable,
|
||||
))
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "olap", feature = "v1"))]
|
||||
#[instrument(skip_all)]
|
||||
pub async fn success_based_routing_update_configs(
|
||||
state: web::Data<AppState>,
|
||||
req: HttpRequest,
|
||||
path: web::Path<routing_types::SuccessBasedRoutingUpdateConfigQuery>,
|
||||
json_payload: web::Json<routing_types::SuccessBasedRoutingConfig>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::UpdateDynamicRoutingConfigs;
|
||||
let routing_payload_wrapper = routing_types::SuccessBasedRoutingPayloadWrapper {
|
||||
updated_config: json_payload.into_inner(),
|
||||
algorithm_id: path.clone().algorithm_id,
|
||||
profile_id: path.clone().profile_id,
|
||||
};
|
||||
Box::pin(oss_api::server_wrap(
|
||||
flow,
|
||||
state,
|
||||
&req,
|
||||
routing_payload_wrapper,
|
||||
|state, _, wrapper: routing_types::SuccessBasedRoutingPayloadWrapper, _| async {
|
||||
Box::pin(routing::success_based_routing_update_configs(
|
||||
state,
|
||||
wrapper.updated_config,
|
||||
wrapper.algorithm_id,
|
||||
wrapper.profile_id,
|
||||
))
|
||||
.await
|
||||
},
|
||||
&auth::AdminApiAuth,
|
||||
api_locking::LockAction::NotApplicable,
|
||||
))
|
||||
.await
|
||||
}
|
||||
|
||||
@ -347,6 +347,7 @@ pub async fn create_business_profile_from_merchant_account(
|
||||
.map(Into::into),
|
||||
tax_connector_id: request.tax_connector_id,
|
||||
is_tax_connector_enabled: request.is_tax_connector_enabled,
|
||||
dynamic_routing_algorithm: None,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user