Bug: [BUG] Fix contract updation for Contract routing



### Feature Description

We need to update the contract once it is not found in the dynamic routing service.


### Possible Implementation

The updation happening in the post-update tracker does not work when the payment goes through a different connector.
Need to set the contract when fetch fails.

### Have you spent some time checking if this feature request has been raised before?

- [x] I checked and didn't find a similar issue

### Have you read the Contributing Guidelines?

- [x] I have read the [Contributing Guidelines](https://github.com/juspay/hyperswitch/blob/main/docs/CONTRIBUTING.md)

### Are you willing to submit a PR?

Yes, I am willing to submit a PR!
diff --git a/crates/external_services/src/grpc_client/dynamic_routing.rs b/crates/external_services/src/grpc_client/dynamic_routing.rs
index e34f721b30e..67069b9fe8b 100644
--- a/crates/external_services/src/grpc_client/dynamic_routing.rs
+++ b/crates/external_services/src/grpc_client/dynamic_routing.rs
@@ -32,9 +32,12 @@ pub enum DynamicRoutingError {
     #[error("Error from Dynamic Routing Server while perfrming success_rate analysis : {0}")]
     SuccessRateBasedRoutingFailure(String),
 
-    /// Error from Dynamic Routing Server while performing contract based routing
+    /// Generic Error from Dynamic Routing Server while performing contract based routing
     #[error("Error from Dynamic Routing Server while performing contract based routing: {0}")]
     ContractBasedRoutingFailure(String),
+    /// Generic Error from Dynamic Routing Server while performing contract based routing
+    #[error("Contract not found in the dynamic routing service")]
+    ContractNotFound,
     /// Error from Dynamic Routing Server while perfrming elimination
     #[error("Error from Dynamic Routing Server while perfrming elimination : {0}")]
     EliminationRateRoutingFailure(String),
diff --git a/crates/external_services/src/grpc_client/dynamic_routing/contract_routing_client.rs b/crates/external_services/src/grpc_client/dynamic_routing/contract_routing_client.rs
index b210d996bc0..ff16594ca6e 100644
--- a/crates/external_services/src/grpc_client/dynamic_routing/contract_routing_client.rs
+++ b/crates/external_services/src/grpc_client/dynamic_routing/contract_routing_client.rs
@@ -26,6 +26,8 @@ use crate::grpc_client::{self, GrpcHeaders};
 pub mod contract_routing {
     tonic::include_proto!("contract_routing");
 }
+pub use tonic::Code;
+
 use super::{Client, DynamicRoutingError, DynamicRoutingResult};
 /// The trait ContractBasedDynamicRouting would have the functions required to support the calculation and updation window
 #[async_trait::async_trait]
@@ -46,6 +48,7 @@ pub trait ContractBasedDynamicRouting: dyn_clone::DynClone + Send + Sync {
         label_info: Vec<LabelInformation>,
         params: String,
         response: Vec<RoutableConnectorChoiceWithStatus>,
+        incr_count: u64,
         headers: GrpcHeaders,
     ) -> DynamicRoutingResult<UpdateContractResponse>;
     /// To invalidates the contract scores against the id
@@ -90,9 +93,10 @@ impl ContractBasedDynamicRouting for ContractScoreCalculatorClient<Client> {
             .clone()
             .fetch_contract_score(request)
             .await
-            .change_context(DynamicRoutingError::ContractBasedRoutingFailure(
-                "Failed to fetch the contract score".to_string(),
-            ))?
+            .map_err(|err| match err.code() {
+                Code::NotFound => DynamicRoutingError::ContractNotFound,
+                _ => DynamicRoutingError::ContractBasedRoutingFailure(err.to_string()),
+            })?
             .into_inner();
 
         logger::info!(dynamic_routing_response=?response);
@@ -106,13 +110,18 @@ impl ContractBasedDynamicRouting for ContractScoreCalculatorClient<Client> {
         label_info: Vec<LabelInformation>,
         params: String,
         _response: Vec<RoutableConnectorChoiceWithStatus>,
+        incr_count: u64,
         headers: GrpcHeaders,
     ) -> DynamicRoutingResult<UpdateContractResponse> {
-        let labels_information = label_info
+        let mut labels_information = label_info
             .into_iter()
             .map(ProtoLabelInfo::foreign_from)
             .collect::<Vec<_>>();
 
+        labels_information
+            .iter_mut()
+            .for_each(|info| info.current_count += incr_count);
+
         let request = grpc_client::create_grpc_request(
             UpdateContractRequest {
                 id,
@@ -183,10 +192,14 @@ impl ForeignTryFrom<ContractBasedRoutingConfigBody> for CalContractScoreConfig {
 impl ForeignFrom<LabelInformation> for ProtoLabelInfo {
     fn foreign_from(config: LabelInformation) -> Self {
         Self {
-            label: config.label,
+            label: format!(
+                "{}:{}",
+                config.label.clone(),
+                config.mca_id.get_string_repr()
+            ),
             target_count: config.target_count,
             target_time: config.target_time,
-            current_count: 1,
+            current_count: u64::default(),
         }
     }
 }
diff --git a/crates/router/src/core/errors.rs b/crates/router/src/core/errors.rs
index d06ffea581f..215f262ea8b 100644
--- a/crates/router/src/core/errors.rs
+++ b/crates/router/src/core/errors.rs
@@ -400,8 +400,10 @@ pub enum RoutingError {
     ContractBasedRoutingConfigError,
     #[error("Params not found in contract based routing config")]
     ContractBasedRoutingParamsNotFoundError,
-    #[error("Unable to calculate contract score from dynamic routing service")]
-    ContractScoreCalculationError,
+    #[error("Unable to calculate contract score from dynamic routing service: '{err}'")]
+    ContractScoreCalculationError { err: String },
+    #[error("Unable to update contract score on dynamic routing service")]
+    ContractScoreUpdationError,
     #[error("contract routing client from dynamic routing gRPC service not initialized")]
     ContractRoutingClientInitializationError,
     #[error("Invalid contract based connector label received from dynamic routing service: '{0}'")]
diff --git a/crates/router/src/core/payments/routing.rs b/crates/router/src/core/payments/routing.rs
index cf5cd35fb98..e78861d4327 100644
--- a/crates/router/src/core/payments/routing.rs
+++ b/crates/router/src/core/payments/routing.rs
@@ -26,8 +26,9 @@ use euclid::{
 };
 #[cfg(all(feature = "v1", feature = "dynamic_routing"))]
 use external_services::grpc_client::dynamic_routing::{
-    contract_routing_client::{CalContractScoreResponse, ContractBasedDynamicRouting},
+    contract_routing_client::ContractBasedDynamicRouting,
     success_rate_client::{CalSuccessRateResponse, SuccessBasedDynamicRouting},
+    DynamicRoutingError,
 };
 use hyperswitch_domain_models::address::Address;
 use kgraph_utils::{
@@ -1599,19 +1600,57 @@ pub async fn perform_contract_based_routing(
         .change_context(errors::RoutingError::ContractBasedRoutingConfigError)
         .attach_printable("unable to fetch contract based dynamic routing configs")?;
 
-        let contract_based_connectors: CalContractScoreResponse = client
+        let contract_based_connectors_result = client
             .calculate_contract_score(
                 profile_id.get_string_repr().into(),
-                contract_based_routing_configs,
+                contract_based_routing_configs.clone(),
                 "".to_string(),
                 routable_connectors,
                 state.get_grpc_headers(),
             )
             .await
-            .change_context(errors::RoutingError::ContractScoreCalculationError)
             .attach_printable(
                 "unable to calculate/fetch contract score from dynamic routing service",
-            )?;
+            );
+
+        let contract_based_connectors = match contract_based_connectors_result {
+            Ok(resp) => resp,
+            Err(err) => match err.current_context() {
+                DynamicRoutingError::ContractNotFound => {
+                    let label_info = contract_based_routing_configs
+                        .label_info
+                        .ok_or(errors::RoutingError::ContractBasedRoutingConfigError)
+                        .attach_printable(
+                            "Label information not found in contract routing configs",
+                        )?;
+
+                    client
+                            .update_contracts(
+                                profile_id.get_string_repr().into(),
+                                label_info,
+                                "".to_string(),
+                                vec![],
+                                u64::default(),
+                                state.get_grpc_headers(),
+                            )
+                            .await
+                            .change_context(errors::RoutingError::ContractScoreUpdationError)
+                            .attach_printable(
+                                "unable to update contract based routing window in dynamic routing service",
+                            )?;
+                    return Err((errors::RoutingError::ContractScoreCalculationError {
+                        err: err.to_string(),
+                    })
+                    .into());
+                }
+                _ => {
+                    return Err((errors::RoutingError::ContractScoreCalculationError {
+                        err: err.to_string(),
+                    })
+                    .into())
+                }
+            },
+        };
 
         let mut connectors = Vec::with_capacity(contract_based_connectors.labels_with_score.len());
 
diff --git a/crates/router/src/core/routing/helpers.rs b/crates/router/src/core/routing/helpers.rs
index b8a7ee5dc1c..17edc50a30d 100644
--- a/crates/router/src/core/routing/helpers.rs
+++ b/crates/router/src/core/routing/helpers.rs
@@ -1036,11 +1036,7 @@ pub async fn push_metrics_with_update_window_for_contract_based_routing(
             );
 
             let request_label_info = routing_types::LabelInformation {
-                label: format!(
-                    "{}:{}",
-                    final_label_info.label.clone(),
-                    final_label_info.mca_id.get_string_repr()
-                ),
+                label: final_label_info.label.clone(),
                 target_count: final_label_info.target_count,
                 target_time: final_label_info.target_time,
                 mca_id: final_label_info.mca_id.to_owned(),
@@ -1056,6 +1052,7 @@ pub async fn push_metrics_with_update_window_for_contract_based_routing(
                         vec![request_label_info],
                         "".to_string(),
                         vec![],
+                        1,
                         state.get_grpc_headers(),
                     )
                     .await

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

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

## Description
<!-- Describe your changes in detail -->
Fixed the contract updation when contract is not set in dynamo. If contract is not set, we'll set in the same flow.
This fixes an issue.

### 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)?
-->
Same as https://github.com/juspay/hyperswitch/pull/6761
New error log - 
![image](https://github.com/user-attachments/assets/26b7f7c0-ac06-4d8c-9996-d08f4c5b74fb)



## 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`
- [ ] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible
