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




diff --git a/crates/api_models/src/events/routing.rs b/crates/api_models/src/events/routing.rs
index 750bfde2710..f1ba35bd9f3 100644
--- a/crates/api_models/src/events/routing.rs
+++ b/crates/api_models/src/events/routing.rs
@@ -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)
diff --git a/crates/api_models/src/routing.rs b/crates/api_models/src/routing.rs
index a15b135ac1f..527e8353b8c 100644
--- a/crates/api_models/src/routing.rs
+++ b/crates/api_models/src/routing.rs
@@ -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 {
diff --git a/crates/openapi/src/openapi.rs b/crates/openapi/src/openapi.rs
index 8612dd080bd..4de9b85cd7c 100644
--- a/crates/openapi/src/openapi.rs
+++ b/crates/openapi/src/openapi.rs
@@ -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,
diff --git a/crates/router/src/core/routing.rs b/crates/router/src/core/routing.rs
index df6189ea424..1811f43d51e 100644
--- a/crates/router/src/core/routing.rs
+++ b/crates/router/src/core/routing.rs
@@ -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,
diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs
index 6071a9ee0b0..7e082296e7f 100644
--- a/crates/router/src/routes/app.rs
+++ b/crates/router/src/routes/app.rs
@@ -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(
diff --git a/crates/router/src/routes/routing.rs b/crates/router/src/routes/routing.rs
index ba041cbe5ac..ff8ad06e91c 100644
--- a/crates/router/src/routes/routing.rs
+++ b/crates/router/src/routes/routing.rs
@@ -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
+}

## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [x] New feature
- [ ] Enhancement
- [ ] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
<!-- Describe your changes in detail -->
This pull request introduces a new feature for retrieving dynamic routing volume split configurations and includes related updates across multiple files. The changes primarily focus on adding a new API endpoint, defining associated data structures, and integrating the functionality into the existing routing system.

### New Feature: Retrieve Dynamic Routing Volume Split

#### API Enhancements:
* Added a new endpoint `/get_volume_split` to retrieve dynamic routing volume split configurations. This endpoint is defined in `crates/router/src/routes/app.rs` and implemented in `crates/router/src/routes/routing.rs`. [[1]](diffhunk://#diff-a6e49b399ffdee83dd322b3cb8bee170c65fb9c6e2e52c14222ec310f6927c54R2055-R2058) [[2]](diffhunk://#diff-bdc480582fe22076ee5ec5bc2452ff57bf86b1b746607bdad4b4ed248c44c45fR1505-R1545)

#### Data Structures:
* Introduced a new struct `RoutingVolumeSplitResponse` in `crates/api_models/src/routing.rs` to encapsulate the volume split value (`split: u8`).
* Updated the `ApiEventMetric` trait implementation to include `RoutingVolumeSplitResponse` and `ToggleDynamicRoutingPath`.

#### Backend Logic:
* Added a new function `retrieve_dynamic_routing_volume_split` in `crates/router/src/core/routing.rs` to handle the business logic for fetching the volume split value from the database and returning it as a response.

#### Dependency Updates:
* Updated imports in `crates/api_models/src/events/routing.rs` and `crates/openapi/src/openapi.rs` to include the new `RoutingVolumeSplitResponse` type. [[1]](diffhunk://#diff-040f264f6e1e25cf7598bf4fafabb91f2d54d7d848ed356a9cf5ec356d5be087L9-R11) [[2]](diffhunk://#diff-449ddbba20051c3e750e25f17452d490a28f78cfe4bcda279865a0365c6b29d8R668)

### Additional Changes

- [ ] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!--
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->


## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless it is an obvious bug or documentation fix
that will have little conversation).
-->


## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->
1. Create merchant account and api_key
2. Using the default profile created during merchant account creation, hit below api to set volume split

```
curl --location --request POST 'http://localhost:8080/account/merchant_1747932999/business_profile/pro_kXrizzzc7yklUW8sfxXz/dynamic_routing/set_volume_split?split=50' \
--header 'api-key: xyz'
```

3. Hit get api which is added in this PR to get the volume split set in above api

```
curl --location 'http://localhost:8080/account/merchant_1747932999/business_profile/pro_kXrizzzc7yklUW8sfxXz/dynamic_routing/get_volume_split' \
--header 'api-key: xyz'
```


## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible
