feat(dynamic_routing): add get api for dynamic routing volume split (#8114)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Chethan Rao
2025-05-27 22:45:44 +05:30
committed by GitHub
parent e637b214e3
commit b7c5f1f276
8 changed files with 122 additions and 3 deletions

View File

@ -26254,6 +26254,19 @@
}
}
},
"RoutingVolumeSplitResponse": {
"type": "object",
"required": [
"split"
],
"properties": {
"split": {
"type": "integer",
"format": "int32",
"minimum": 0
}
}
},
"RuleConnectorSelection": {
"type": "object",
"description": "Represents a rule\n\n```text\nrule_name: [stripe, adyen, checkout]\n{\npayment.method = card {\npayment.method.cardtype = (credit, debit) {\npayment.method.network = (amex, rupay, diners)\n}\n\npayment.method.cardtype = credit\n}\n}\n```",

View File

@ -7,8 +7,9 @@ use crate::routing::{
RoutingAlgorithmId, RoutingConfigRequest, RoutingDictionaryRecord, RoutingKind,
RoutingLinkWrapper, RoutingPayloadWrapper, RoutingRetrieveLinkQuery,
RoutingRetrieveLinkQueryWrapper, RoutingRetrieveQuery, RoutingVolumeSplit,
RoutingVolumeSplitWrapper, SuccessBasedRoutingConfig, SuccessBasedRoutingPayloadWrapper,
ToggleDynamicRoutingQuery, ToggleDynamicRoutingWrapper,
RoutingVolumeSplitResponse, RoutingVolumeSplitWrapper, SuccessBasedRoutingConfig,
SuccessBasedRoutingPayloadWrapper, ToggleDynamicRoutingPath, ToggleDynamicRoutingQuery,
ToggleDynamicRoutingWrapper,
};
impl ApiEventMetric for RoutingKind {
@ -135,6 +136,18 @@ impl ApiEventMetric for RoutingVolumeSplitWrapper {
}
}
impl ApiEventMetric for ToggleDynamicRoutingPath {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Routing)
}
}
impl ApiEventMetric for RoutingVolumeSplitResponse {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Routing)
}
}
impl ApiEventMetric for RoutingVolumeSplit {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Routing)

View File

@ -857,6 +857,11 @@ pub struct ToggleDynamicRoutingPath {
pub profile_id: common_utils::id_type::ProfileId,
}
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct RoutingVolumeSplitResponse {
pub split: u8,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct EliminationRoutingConfig {

View File

@ -671,6 +671,7 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::routing::SuccessRateSpecificityLevel,
api_models::routing::ToggleDynamicRoutingQuery,
api_models::routing::ToggleDynamicRoutingPath,
api_models::routing::RoutingVolumeSplitResponse,
api_models::routing::ast::RoutableChoiceKind,
api_models::enums::RoutableConnectors,
api_models::routing::ast::ProgramConnectorSelection,

View File

@ -1554,6 +1554,48 @@ pub async fn configure_dynamic_routing_volume_split(
Ok(service_api::ApplicationResponse::Json(routing_info))
}
#[cfg(feature = "v1")]
pub async fn retrieve_dynamic_routing_volume_split(
state: SessionState,
merchant_context: domain::MerchantContext,
profile_id: common_utils::id_type::ProfileId,
) -> RouterResponse<routing_types::RoutingVolumeSplitResponse> {
let db = state.store.as_ref();
let key_manager_state = &(&state).into();
let business_profile: domain::Profile = core_utils::validate_and_get_business_profile(
db,
key_manager_state,
merchant_context.get_merchant_key_store(),
Some(&profile_id),
merchant_context.get_merchant_account().get_id(),
)
.await?
.get_required_value("Profile")
.change_context(errors::ApiErrorResponse::ProfileNotFound {
id: profile_id.get_string_repr().to_owned(),
})?;
let 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();
let resp = routing_types::RoutingVolumeSplitResponse {
split: dynamic_routing_algo_ref
.dynamic_routing_volume_split
.unwrap_or_default(),
};
Ok(service_api::ApplicationResponse::Json(resp))
}
#[cfg(all(feature = "v1", feature = "dynamic_routing"))]
pub async fn success_based_routing_update_configs(
state: SessionState,

View File

@ -2082,6 +2082,10 @@ impl Profile {
web::resource("/set_volume_split")
.route(web::post().to(routing::set_dynamic_routing_volume_split)),
)
.service(
web::resource("/get_volume_split")
.route(web::get().to(routing::get_dynamic_routing_volume_split)),
)
.service(
web::scope("/elimination")
.service(

View File

@ -1502,3 +1502,44 @@ pub async fn set_dynamic_routing_volume_split(
))
.await
}
#[cfg(all(feature = "olap", feature = "v1"))]
#[instrument(skip_all)]
pub async fn get_dynamic_routing_volume_split(
state: web::Data<AppState>,
req: HttpRequest,
path: web::Path<routing_types::ToggleDynamicRoutingPath>,
) -> impl Responder {
let flow = Flow::VolumeSplitOnRoutingType;
let payload = path.into_inner();
Box::pin(oss_api::server_wrap(
flow,
state,
&req,
payload.clone(),
|state, auth: auth::AuthenticationData, payload, _| {
let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
domain::Context(auth.merchant_account, auth.key_store),
));
routing::retrieve_dynamic_routing_volume_split(
state,
merchant_context,
payload.profile_id,
)
},
auth::auth_type(
&auth::HeaderAuth(auth::ApiKeyAuth {
is_connected_allowed: false,
is_platform_allowed: false,
}),
&auth::JWTAuthProfileFromRoute {
profile_id: payload.profile_id,
required_permission: Permission::ProfileRoutingRead,
},
req.headers(),
),
api_locking::LockAction::NotApplicable,
))
.await
}

View File

@ -255,7 +255,7 @@ export const connectorDetails = {
},
},
},
manualPaymentPartialRefund : {
manualPaymentPartialRefund: {
Request: {
amount: 5000,
},