From 512ae85c81fc92158e1b54c48b55993849e14a2a Mon Sep 17 00:00:00 2001 From: Noa <130567821+noagbmn@users.noreply.github.com> Date: Fri, 6 Dec 2024 12:58:36 +0500 Subject: [PATCH] fix(connector): add config cleanup on payment connector deletion (#5998) --- crates/common_enums/src/enums.rs | 10 +++ crates/router/src/core/admin.rs | 141 ++++++++++++++++++++++++++++++- 2 files changed, 150 insertions(+), 1 deletion(-) diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index 1e05e7ec88..c3c876b22a 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -3342,6 +3342,16 @@ pub enum PresenceOfCustomerDuringPayment { Absent, } +impl From for TransactionType { + fn from(connector_type: ConnectorType) -> Self { + match connector_type { + #[cfg(feature = "payouts")] + ConnectorType::PayoutProcessor => Self::Payout, + _ => Self::Payment, + } + } +} + #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, Default, ToSchema)] #[serde(rename_all = "snake_case")] pub enum TaxCalculationOverride { diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index b026b1e32f..40ed4e7552 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -1931,6 +1931,65 @@ impl<'a> MerchantDefaultConfigUpdate<'a> { } Ok(()) } + + async fn retrieve_and_delete_from_default_fallback_routing_algorithm_if_routable_connector_exists( + &self, + ) -> RouterResult<()> { + let mut default_routing_config = routing::helpers::get_merchant_default_config( + self.store, + self.merchant_id.get_string_repr(), + self.transaction_type, + ) + .await?; + + let mut default_routing_config_for_profile = routing::helpers::get_merchant_default_config( + self.store, + self.profile_id.get_string_repr(), + self.transaction_type, + ) + .await?; + + if let Some(routable_connector_val) = self.routable_connector { + let choice = routing_types::RoutableConnectorChoice { + choice_kind: routing_types::RoutableChoiceKind::FullStruct, + connector: *routable_connector_val, + merchant_connector_id: Some(self.merchant_connector_id.clone()), + }; + if default_routing_config.contains(&choice) { + default_routing_config.retain(|mca| { + mca.merchant_connector_id + .as_ref() + .map_or(true, |merchant_connector_id| { + merchant_connector_id != self.merchant_connector_id + }) + }); + routing::helpers::update_merchant_default_config( + self.store, + self.merchant_id.get_string_repr(), + default_routing_config.clone(), + self.transaction_type, + ) + .await?; + } + if default_routing_config_for_profile.contains(&choice.clone()) { + default_routing_config_for_profile.retain(|mca| { + mca.merchant_connector_id + .as_ref() + .map_or(true, |merchant_connector_id| { + merchant_connector_id != self.merchant_connector_id + }) + }); + routing::helpers::update_merchant_default_config( + self.store, + self.profile_id.get_string_repr(), + default_routing_config_for_profile.clone(), + self.transaction_type, + ) + .await?; + } + } + Ok(()) + } } #[cfg(feature = "v2")] struct DefaultFallbackRoutingConfigUpdate<'a> { @@ -1970,6 +2029,40 @@ impl<'a> DefaultFallbackRoutingConfigUpdate<'a> { } Ok(()) } + + async fn retrieve_and_delete_from_default_fallback_routing_algorithm_if_routable_connector_exists( + &self, + ) -> RouterResult<()> { + let profile_wrapper = ProfileWrapper::new(self.business_profile.clone()); + let default_routing_config_for_profile = + &mut profile_wrapper.get_default_fallback_list_of_connector_under_profile()?; + if let Some(routable_connector_val) = self.routable_connector { + let choice = routing_types::RoutableConnectorChoice { + choice_kind: routing_types::RoutableChoiceKind::FullStruct, + connector: *routable_connector_val, + merchant_connector_id: Some(self.merchant_connector_id.clone()), + }; + if default_routing_config_for_profile.contains(&choice.clone()) { + default_routing_config_for_profile.retain(|mca| { + mca.merchant_connector_id + .as_ref() + .map_or(true, |merchant_connector_id| { + merchant_connector_id != self.merchant_connector_id + }) + }); + + profile_wrapper + .update_default_fallback_routing_of_connectors_under_profile( + self.store, + default_routing_config_for_profile, + self.key_manager_state, + &self.key_store, + ) + .await? + } + } + Ok(()) + } } #[cfg(any(feature = "v1", feature = "v2", feature = "olap"))] #[async_trait::async_trait] @@ -3138,7 +3231,7 @@ pub async fn delete_connector( .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; - let _mca = db + let mca = db .find_by_merchant_connector_account_merchant_id_merchant_connector_id( key_manager_state, &merchant_id, @@ -3160,6 +3253,26 @@ pub async fn delete_connector( id: merchant_connector_id.get_string_repr().to_string(), })?; + // delete the mca from the config as well + let merchant_default_config_delete = MerchantDefaultConfigUpdate { + routable_connector: &Some( + common_enums::RoutableConnectors::from_str(&mca.connector_name).map_err(|_| { + errors::ApiErrorResponse::InvalidDataValue { + field_name: "connector_name", + } + })?, + ), + merchant_connector_id: &mca.get_id(), + store: db, + merchant_id: &merchant_id, + profile_id: &mca.profile_id, + transaction_type: &mca.connector_type.into(), + }; + + merchant_default_config_delete + .retrieve_and_delete_from_default_fallback_routing_algorithm_if_routable_connector_exists() + .await?; + let response = api::MerchantConnectorDeleteResponse { merchant_id, merchant_connector_id, @@ -3206,6 +3319,32 @@ pub async fn delete_connector( id: id.clone().get_string_repr().to_string(), })?; + let business_profile = db + .find_business_profile_by_profile_id(key_manager_state, &key_store, &mca.profile_id) + .await + .to_not_found_response(errors::ApiErrorResponse::ProfileNotFound { + id: mca.profile_id.get_string_repr().to_owned(), + })?; + + let merchant_default_config_delete = DefaultFallbackRoutingConfigUpdate { + routable_connector: &Some( + common_enums::RoutableConnectors::from_str(&mca.connector_name).map_err(|_| { + errors::ApiErrorResponse::InvalidDataValue { + field_name: "connector_name", + } + })?, + ), + merchant_connector_id: &mca.get_id(), + store: db, + business_profile, + key_store, + key_manager_state, + }; + + merchant_default_config_delete + .retrieve_and_delete_from_default_fallback_routing_algorithm_if_routable_connector_exists() + .await?; + let response = api::MerchantConnectorDeleteResponse { merchant_id: merchant_id.clone(), id,