Skip to content

Commit

Permalink
feat(router): Create a merchant config for enable processor agnostic …
Browse files Browse the repository at this point in the history
…MIT (#4025)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
  • Loading branch information
ShankarSinghC and hyperswitch-bot[bot] authored Apr 3, 2024
1 parent 49cfe72 commit 2a691a5
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 55 deletions.
32 changes: 5 additions & 27 deletions crates/api_models/src/routing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub use euclid::{
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

use crate::enums::{self, RoutableConnectors, TransactionType};
use crate::enums::{RoutableConnectors, TransactionType};

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
Expand Down Expand Up @@ -299,35 +299,13 @@ impl From<RoutableConnectorChoice> for ast::ConnectorChoice {
}
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
pub struct DetailedConnectorChoice {
pub connector: RoutableConnectors,
pub business_label: Option<String>,
pub business_country: Option<enums::CountryAlpha2>,
pub business_sub_label: Option<String>,
}

impl DetailedConnectorChoice {
pub fn get_connector_label(&self) -> Option<String> {
self.business_country
.as_ref()
.zip(self.business_label.as_ref())
.map(|(business_country, business_label)| {
let mut base_label = format!(
"{}_{:?}_{}",
self.connector, business_country, business_label
);

if let Some(ref sub_label) = self.business_sub_label {
base_label.push('_');
base_label.push_str(sub_label);
}

base_label
})
}
pub enabled: bool,
}

impl common_utils::events::ApiEventMetric for DetailedConnectorChoice {}

#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize, strum::Display, ToSchema)]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
Expand Down
32 changes: 31 additions & 1 deletion crates/router/src/core/routing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use api_models::{
};
#[cfg(not(feature = "business_profile_routing"))]
use common_utils::ext_traits::{Encode, StringExt};
#[cfg(not(feature = "business_profile_routing"))]
use diesel_models::configs;
#[cfg(feature = "business_profile_routing")]
use diesel_models::routing_algorithm::RoutingAlgorithm;
Expand Down Expand Up @@ -807,6 +806,37 @@ pub async fn retrieve_linked_routing_config(
}
}

pub async fn upsert_connector_agnostic_mandate_config(
state: AppState,
business_profile_id: &str,
mandate_config: routing_types::DetailedConnectorChoice,
) -> RouterResponse<routing_types::DetailedConnectorChoice> {
let key = helpers::get_pg_agnostic_mandate_config_key(business_profile_id);

let mandate_config_str = mandate_config.enabled.to_string();

let find_config = state
.store
.find_config_by_key_unwrap_or(&key, Some(mandate_config_str.clone()))
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("error saving pg agnostic mandate config to db")?;

if find_config.config != mandate_config_str {
let config_update = configs::ConfigUpdate::Update {
config: Some(mandate_config_str),
};
state
.store
.update_config_by_key(&key, config_update)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("error saving pg agnostic mandate config to db")?;
}

Ok(service_api::ApplicationResponse::Json(mandate_config))
}

pub async fn retrieve_default_routing_config_for_profiles(
state: AppState,
merchant_account: domain::MerchantAccount,
Expand Down
31 changes: 4 additions & 27 deletions crates/router/src/core/routing/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,9 @@ pub async fn update_business_profile_active_algorithm_ref(

pub async fn get_merchant_connector_agnostic_mandate_config(
db: &dyn StorageInterface,
merchant_id: &str,
business_profile_id: &str,
) -> RouterResult<Vec<routing_types::DetailedConnectorChoice>> {
let key = get_pg_agnostic_mandate_config_key(merchant_id);
let key = get_pg_agnostic_mandate_config_key(business_profile_id);
let maybe_config = db.find_config_by_key(&key).await;

match maybe_config {
Expand Down Expand Up @@ -312,29 +312,6 @@ pub async fn get_merchant_connector_agnostic_mandate_config(
}
}

pub async fn update_merchant_connector_agnostic_mandate_config(
db: &dyn StorageInterface,
merchant_id: &str,
mandate_config: Vec<routing_types::DetailedConnectorChoice>,
) -> RouterResult<Vec<routing_types::DetailedConnectorChoice>> {
let key = get_pg_agnostic_mandate_config_key(merchant_id);
let mandate_config_str = mandate_config
.encode_to_string_of_json()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("unable to serialize pg agnostic mandate config during update")?;

let config_update = configs::ConfigUpdate::Update {
config: Some(mandate_config_str),
};

db.update_config_by_key(&key, config_update)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("error saving pg agnostic mandate config to db")?;

Ok(mandate_config)
}

pub async fn validate_connectors_in_routing_config(
db: &dyn StorageInterface,
key_store: &domain::MerchantKeyStore,
Expand Down Expand Up @@ -465,8 +442,8 @@ pub fn get_routing_dictionary_key(merchant_id: &str) -> String {

/// Provides the identifier for the specific merchant's agnostic_mandate_config
#[inline(always)]
pub fn get_pg_agnostic_mandate_config_key(merchant_id: &str) -> String {
format!("pg_agnostic_mandate_{merchant_id}")
pub fn get_pg_agnostic_mandate_config_key(business_profile_id: &str) -> String {
format!("pg_agnostic_mandate_{business_profile_id}")
}

/// Provides the identifier for the specific merchant's default_config
Expand Down
4 changes: 4 additions & 0 deletions crates/router/src/routes/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,10 @@ impl Routing {
)
})),
)
.service(
web::resource("/business_profile/{business_profile_id}/configs/pg_agnostic_mit")
.route(web::post().to(cloud_routing::upsert_connector_agnostic_mandate_config)),
)
.service(
web::resource("/default")
.route(web::get().to(|state, req| {
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/routes/lock_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ impl From<Flow> for ApiIdentifier {
| Flow::ReconTokenRequest
| Flow::ReconServiceRequest
| Flow::ReconVerifyToken => Self::Recon,
Flow::CreateConnectorAgnosticMandateConfig => Self::Routing,
}
}
}
38 changes: 38 additions & 0 deletions crates/router/src/routes/routing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,44 @@ pub async fn routing_retrieve_linked_config(
}
}

#[cfg(feature = "olap")]
#[instrument(skip_all)]
pub async fn upsert_connector_agnostic_mandate_config(
state: web::Data<AppState>,
req: HttpRequest,
json_payload: web::Json<routing_types::DetailedConnectorChoice>,
path: web::Path<String>,
) -> impl Responder {
use crate::services::authentication::AuthenticationData;

let flow = Flow::CreateConnectorAgnosticMandateConfig;
let business_profile_id = path.into_inner();

Box::pin(oss_api::server_wrap(
flow,
state,
&req,
json_payload.into_inner(),
|state, _auth: AuthenticationData, mandate_config| {
Box::pin(routing::upsert_connector_agnostic_mandate_config(
state,
&business_profile_id,
mandate_config,
))
},
#[cfg(not(feature = "release"))]
auth::auth_type(
&auth::ApiKeyAuth,
&auth::JWTAuth(Permission::RoutingWrite),
req.headers(),
),
#[cfg(feature = "release")]
&auth::JWTAuth(Permission::RoutingWrite),
api_locking::LockAction::NotApplicable,
))
.await
}

#[cfg(feature = "olap")]
#[instrument(skip_all)]
pub async fn routing_retrieve_default_config_for_profiles(
Expand Down
2 changes: 2 additions & 0 deletions crates/router_env/src/logger/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ pub enum Flow {
RoutingRetrieveConfig,
/// Routing retrieve active config
RoutingRetrieveActiveConfig,
/// Update connector agnostic mandate config
CreateConnectorAgnosticMandateConfig,
/// Routing retrieve default config
RoutingRetrieveDefaultConfig,
/// Routing retrieve dictionary
Expand Down

0 comments on commit 2a691a5

Please sign in to comment.