mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-29 00:49:42 +08:00 
			
		
		
		
	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:
		| @ -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```", | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -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 { | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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( | ||||
|  | ||||
| @ -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 | ||||
| } | ||||
|  | ||||
| @ -255,7 +255,7 @@ export const connectorDetails = { | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|     manualPaymentPartialRefund : { | ||||
|     manualPaymentPartialRefund: { | ||||
|       Request: { | ||||
|         amount: 5000, | ||||
|       }, | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Chethan Rao
					Chethan Rao