mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 01:27:31 +08:00
feat(router): Add revenue recovery retry algorithm type and data columns to business_profile table (#7772)
Co-authored-by: Aniket Burman <aniket.burman@Aniket-Burman-JDXHW2PH34.local> Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Co-authored-by: Amisha Prabhat <55580080+Aprabhat19@users.noreply.github.com>
This commit is contained in:
@ -212,6 +212,29 @@ pub enum CardDiscovery {
|
||||
ClickToPay,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Hash,
|
||||
Eq,
|
||||
PartialEq,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
strum::EnumIter,
|
||||
ToSchema,
|
||||
)]
|
||||
#[router_derive::diesel_enum(storage_type = "db_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum RevenueRecoveryAlgorithmType {
|
||||
Monitoring,
|
||||
Smart,
|
||||
Cascading,
|
||||
}
|
||||
|
||||
/// Pass this parameter to force 3DS or non 3DS auth for this payment. Some connectors will still force 3DS auth even in case of passing 'no_three_ds' here and vice versa. Default value is 'no_three_ds' if not set
|
||||
#[derive(
|
||||
Clone,
|
||||
|
||||
@ -364,6 +364,8 @@ pub struct Profile {
|
||||
pub three_ds_decision_manager_config: Option<common_types::payments::DecisionManagerRecord>,
|
||||
pub should_collect_cvv_during_payment:
|
||||
Option<primitive_wrappers::ShouldCollectCvvDuringPayment>,
|
||||
pub revenue_recovery_retry_algorithm_type: Option<common_enums::RevenueRecoveryAlgorithmType>,
|
||||
pub revenue_recovery_retry_algorithm_data: Option<RevenueRecoveryAlgorithmData>,
|
||||
}
|
||||
|
||||
impl Profile {
|
||||
@ -432,6 +434,8 @@ pub struct ProfileNew {
|
||||
pub should_collect_cvv_during_payment:
|
||||
Option<primitive_wrappers::ShouldCollectCvvDuringPayment>,
|
||||
pub id: common_utils::id_type::ProfileId,
|
||||
pub revenue_recovery_retry_algorithm_type: Option<common_enums::RevenueRecoveryAlgorithmType>,
|
||||
pub revenue_recovery_retry_algorithm_data: Option<RevenueRecoveryAlgorithmData>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
@ -484,6 +488,8 @@ pub struct ProfileUpdateInternal {
|
||||
pub three_ds_decision_manager_config: Option<common_types::payments::DecisionManagerRecord>,
|
||||
pub should_collect_cvv_during_payment:
|
||||
Option<primitive_wrappers::ShouldCollectCvvDuringPayment>,
|
||||
pub revenue_recovery_retry_algorithm_type: Option<common_enums::RevenueRecoveryAlgorithmType>,
|
||||
pub revenue_recovery_retry_algorithm_data: Option<RevenueRecoveryAlgorithmData>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
@ -533,6 +539,8 @@ impl ProfileUpdateInternal {
|
||||
is_clear_pan_retries_enabled,
|
||||
is_debit_routing_enabled,
|
||||
merchant_business_country,
|
||||
revenue_recovery_retry_algorithm_type,
|
||||
revenue_recovery_retry_algorithm_data,
|
||||
} = self;
|
||||
Profile {
|
||||
id: source.id,
|
||||
@ -613,6 +621,10 @@ impl ProfileUpdateInternal {
|
||||
is_debit_routing_enabled,
|
||||
merchant_business_country: merchant_business_country
|
||||
.or(source.merchant_business_country),
|
||||
revenue_recovery_retry_algorithm_type: revenue_recovery_retry_algorithm_type
|
||||
.or(source.revenue_recovery_retry_algorithm_type),
|
||||
revenue_recovery_retry_algorithm_data: revenue_recovery_retry_algorithm_data
|
||||
.or(source.revenue_recovery_retry_algorithm_data),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -738,3 +750,11 @@ pub struct BusinessGenericLinkConfig {
|
||||
}
|
||||
|
||||
common_utils::impl_to_sql_from_sql_json!(BusinessPayoutLinkConfig);
|
||||
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, diesel::AsExpression)]
|
||||
#[diesel(sql_type = diesel::sql_types::Jsonb)]
|
||||
pub struct RevenueRecoveryAlgorithmData {
|
||||
pub monitoring_configured_timestamp: time::PrimitiveDateTime,
|
||||
}
|
||||
|
||||
common_utils::impl_to_sql_from_sql_json!(RevenueRecoveryAlgorithmData);
|
||||
|
||||
@ -20,8 +20,8 @@ pub mod diesel_exports {
|
||||
DbRefundStatus as RefundStatus, DbRefundType as RefundType, DbRelayStatus as RelayStatus,
|
||||
DbRelayType as RelayType,
|
||||
DbRequestIncrementalAuthorization as RequestIncrementalAuthorization,
|
||||
DbRoleScope as RoleScope, DbRoutingAlgorithmKind as RoutingAlgorithmKind,
|
||||
DbScaExemptionType as ScaExemptionType,
|
||||
DbRevenueRecoveryAlgorithmType as RevenueRecoveryAlgorithmType, DbRoleScope as RoleScope,
|
||||
DbRoutingAlgorithmKind as RoutingAlgorithmKind, DbScaExemptionType as ScaExemptionType,
|
||||
DbSuccessBasedRoutingConclusiveState as SuccessBasedRoutingConclusiveState,
|
||||
DbTotpStatus as TotpStatus, DbTransactionType as TransactionType,
|
||||
DbUserRoleVersion as UserRoleVersion, DbUserStatus as UserStatus,
|
||||
|
||||
@ -232,6 +232,8 @@ diesel::table! {
|
||||
default_fallback_routing -> Nullable<Jsonb>,
|
||||
three_ds_decision_manager_config -> Nullable<Jsonb>,
|
||||
should_collect_cvv_during_payment -> Nullable<Bool>,
|
||||
revenue_recovery_retry_algorithm_type -> Nullable<RevenueRecoveryAlgorithmType>,
|
||||
revenue_recovery_retry_algorithm_data -> Nullable<Jsonb>,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,8 @@ use common_utils::{
|
||||
pii, type_name,
|
||||
types::keymanager,
|
||||
};
|
||||
#[cfg(feature = "v2")]
|
||||
use diesel_models::business_profile::RevenueRecoveryAlgorithmData;
|
||||
use diesel_models::business_profile::{
|
||||
AuthenticationConnectorDetails, BusinessPaymentLinkConfig, BusinessPayoutLinkConfig,
|
||||
CardTestingGuardConfig, ProfileUpdateInternal, WebhookDetails,
|
||||
@ -901,6 +903,8 @@ pub struct Profile {
|
||||
pub is_clear_pan_retries_enabled: bool,
|
||||
pub is_debit_routing_enabled: bool,
|
||||
pub merchant_business_country: Option<api_enums::CountryAlpha2>,
|
||||
pub revenue_recovery_retry_algorithm_type: Option<common_enums::RevenueRecoveryAlgorithmType>,
|
||||
pub revenue_recovery_retry_algorithm_data: Option<RevenueRecoveryAlgorithmData>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
@ -951,6 +955,8 @@ pub struct ProfileSetter {
|
||||
pub is_clear_pan_retries_enabled: bool,
|
||||
pub is_debit_routing_enabled: bool,
|
||||
pub merchant_business_country: Option<api_enums::CountryAlpha2>,
|
||||
pub revenue_recovery_retry_algorithm_type: Option<common_enums::RevenueRecoveryAlgorithmType>,
|
||||
pub revenue_recovery_retry_algorithm_data: Option<RevenueRecoveryAlgorithmData>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
@ -1006,6 +1012,8 @@ impl From<ProfileSetter> for Profile {
|
||||
is_clear_pan_retries_enabled: value.is_clear_pan_retries_enabled,
|
||||
is_debit_routing_enabled: value.is_debit_routing_enabled,
|
||||
merchant_business_country: value.merchant_business_country,
|
||||
revenue_recovery_retry_algorithm_type: value.revenue_recovery_retry_algorithm_type,
|
||||
revenue_recovery_retry_algorithm_data: value.revenue_recovery_retry_algorithm_data,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1095,6 +1103,10 @@ pub enum ProfileUpdate {
|
||||
CardTestingSecretKeyUpdate {
|
||||
card_testing_secret_key: OptionalEncryptableName,
|
||||
},
|
||||
RevenueRecoveryAlgorithmUpdate {
|
||||
revenue_recovery_retry_algorithm_type: common_enums::RevenueRecoveryAlgorithmType,
|
||||
revenue_recovery_retry_algorithm_data: Option<RevenueRecoveryAlgorithmData>,
|
||||
},
|
||||
}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
@ -1181,6 +1193,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
||||
is_clear_pan_retries_enabled: None,
|
||||
is_debit_routing_enabled,
|
||||
merchant_business_country,
|
||||
revenue_recovery_retry_algorithm_type: None,
|
||||
revenue_recovery_retry_algorithm_data: None,
|
||||
}
|
||||
}
|
||||
ProfileUpdate::RoutingAlgorithmUpdate {
|
||||
@ -1230,6 +1244,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
||||
is_clear_pan_retries_enabled: None,
|
||||
is_debit_routing_enabled: false,
|
||||
merchant_business_country: None,
|
||||
revenue_recovery_retry_algorithm_type: None,
|
||||
revenue_recovery_retry_algorithm_data: None,
|
||||
},
|
||||
ProfileUpdate::ExtendedCardInfoUpdate {
|
||||
is_extended_card_info_enabled,
|
||||
@ -1277,6 +1293,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
||||
is_clear_pan_retries_enabled: None,
|
||||
is_debit_routing_enabled: false,
|
||||
merchant_business_country: None,
|
||||
revenue_recovery_retry_algorithm_type: None,
|
||||
revenue_recovery_retry_algorithm_data: None,
|
||||
},
|
||||
ProfileUpdate::ConnectorAgnosticMitUpdate {
|
||||
is_connector_agnostic_mit_enabled,
|
||||
@ -1324,6 +1342,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
||||
is_clear_pan_retries_enabled: None,
|
||||
is_debit_routing_enabled: false,
|
||||
merchant_business_country: None,
|
||||
revenue_recovery_retry_algorithm_type: None,
|
||||
revenue_recovery_retry_algorithm_data: None,
|
||||
},
|
||||
ProfileUpdate::DefaultRoutingFallbackUpdate {
|
||||
default_fallback_routing,
|
||||
@ -1371,6 +1391,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
||||
is_clear_pan_retries_enabled: None,
|
||||
is_debit_routing_enabled: false,
|
||||
merchant_business_country: None,
|
||||
revenue_recovery_retry_algorithm_type: None,
|
||||
revenue_recovery_retry_algorithm_data: None,
|
||||
},
|
||||
ProfileUpdate::NetworkTokenizationUpdate {
|
||||
is_network_tokenization_enabled,
|
||||
@ -1418,6 +1440,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
||||
is_clear_pan_retries_enabled: None,
|
||||
is_debit_routing_enabled: false,
|
||||
merchant_business_country: None,
|
||||
revenue_recovery_retry_algorithm_type: None,
|
||||
revenue_recovery_retry_algorithm_data: None,
|
||||
},
|
||||
ProfileUpdate::CollectCvvDuringPaymentUpdate {
|
||||
should_collect_cvv_during_payment,
|
||||
@ -1465,6 +1489,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
||||
is_clear_pan_retries_enabled: None,
|
||||
is_debit_routing_enabled: false,
|
||||
merchant_business_country: None,
|
||||
revenue_recovery_retry_algorithm_type: None,
|
||||
revenue_recovery_retry_algorithm_data: None,
|
||||
},
|
||||
ProfileUpdate::DecisionManagerRecordUpdate {
|
||||
three_ds_decision_manager_config,
|
||||
@ -1512,6 +1538,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
||||
is_clear_pan_retries_enabled: None,
|
||||
is_debit_routing_enabled: false,
|
||||
merchant_business_country: None,
|
||||
revenue_recovery_retry_algorithm_type: None,
|
||||
revenue_recovery_retry_algorithm_data: None,
|
||||
},
|
||||
ProfileUpdate::CardTestingSecretKeyUpdate {
|
||||
card_testing_secret_key,
|
||||
@ -1559,6 +1587,58 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
||||
is_clear_pan_retries_enabled: None,
|
||||
is_debit_routing_enabled: false,
|
||||
merchant_business_country: None,
|
||||
revenue_recovery_retry_algorithm_type: None,
|
||||
revenue_recovery_retry_algorithm_data: None,
|
||||
},
|
||||
ProfileUpdate::RevenueRecoveryAlgorithmUpdate {
|
||||
revenue_recovery_retry_algorithm_type,
|
||||
revenue_recovery_retry_algorithm_data,
|
||||
} => Self {
|
||||
profile_name: None,
|
||||
modified_at: now,
|
||||
return_url: None,
|
||||
enable_payment_response_hash: None,
|
||||
payment_response_hash_key: None,
|
||||
redirect_to_merchant_with_http_post: None,
|
||||
webhook_details: None,
|
||||
metadata: None,
|
||||
is_recon_enabled: None,
|
||||
applepay_verified_domains: None,
|
||||
payment_link_config: None,
|
||||
session_expiry: None,
|
||||
authentication_connector_details: None,
|
||||
payout_link_config: None,
|
||||
is_extended_card_info_enabled: None,
|
||||
extended_card_info_config: None,
|
||||
is_connector_agnostic_mit_enabled: None,
|
||||
use_billing_as_payment_method_billing: None,
|
||||
collect_shipping_details_from_wallet_connector: None,
|
||||
collect_billing_details_from_wallet_connector: None,
|
||||
outgoing_webhook_custom_http_headers: None,
|
||||
always_collect_billing_details_from_wallet_connector: None,
|
||||
always_collect_shipping_details_from_wallet_connector: None,
|
||||
routing_algorithm_id: None,
|
||||
payout_routing_algorithm_id: None,
|
||||
order_fulfillment_time: None,
|
||||
order_fulfillment_time_origin: None,
|
||||
frm_routing_algorithm_id: None,
|
||||
default_fallback_routing: None,
|
||||
should_collect_cvv_during_payment: None,
|
||||
tax_connector_id: None,
|
||||
is_tax_connector_enabled: None,
|
||||
is_network_tokenization_enabled: None,
|
||||
is_auto_retries_enabled: None,
|
||||
max_auto_retries_enabled: None,
|
||||
is_click_to_pay_enabled: None,
|
||||
authentication_product_ids: None,
|
||||
three_ds_decision_manager_config: None,
|
||||
card_testing_guard_config: None,
|
||||
card_testing_secret_key: None,
|
||||
is_clear_pan_retries_enabled: None,
|
||||
is_debit_routing_enabled: false,
|
||||
merchant_business_country: None,
|
||||
revenue_recovery_retry_algorithm_type: Some(revenue_recovery_retry_algorithm_type),
|
||||
revenue_recovery_retry_algorithm_data,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -1628,6 +1708,8 @@ impl super::behaviour::Conversion for Profile {
|
||||
force_3ds_challenge: None,
|
||||
is_debit_routing_enabled: self.is_debit_routing_enabled,
|
||||
merchant_business_country: self.merchant_business_country,
|
||||
revenue_recovery_retry_algorithm_type: self.revenue_recovery_retry_algorithm_type,
|
||||
revenue_recovery_retry_algorithm_data: self.revenue_recovery_retry_algorithm_data,
|
||||
})
|
||||
}
|
||||
|
||||
@ -1717,6 +1799,8 @@ impl super::behaviour::Conversion for Profile {
|
||||
is_clear_pan_retries_enabled: item.is_clear_pan_retries_enabled,
|
||||
is_debit_routing_enabled: item.is_debit_routing_enabled,
|
||||
merchant_business_country: item.merchant_business_country,
|
||||
revenue_recovery_retry_algorithm_type: item.revenue_recovery_retry_algorithm_type,
|
||||
revenue_recovery_retry_algorithm_data: item.revenue_recovery_retry_algorithm_data,
|
||||
})
|
||||
}
|
||||
.await
|
||||
@ -1780,6 +1864,8 @@ impl super::behaviour::Conversion for Profile {
|
||||
is_clear_pan_retries_enabled: Some(self.is_clear_pan_retries_enabled),
|
||||
is_debit_routing_enabled: self.is_debit_routing_enabled,
|
||||
merchant_business_country: self.merchant_business_country,
|
||||
revenue_recovery_retry_algorithm_type: self.revenue_recovery_retry_algorithm_type,
|
||||
revenue_recovery_retry_algorithm_data: self.revenue_recovery_retry_algorithm_data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -2913,6 +2913,17 @@ pub async fn create_connector(
|
||||
.validate_and_get_business_profile(&merchant_account, store, key_manager_state, &key_store)
|
||||
.await?;
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
if req.connector_type == common_enums::ConnectorType::BillingProcessor {
|
||||
update_revenue_recovery_algorithm_under_profile(
|
||||
business_profile.clone(),
|
||||
store,
|
||||
key_manager_state,
|
||||
&key_store,
|
||||
common_enums::RevenueRecoveryAlgorithmType::Monitoring,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
core_utils::validate_profile_id_from_auth_layer(auth_profile_id, &business_profile)?;
|
||||
|
||||
let pm_auth_config_validation = PMAuthConfigValidation {
|
||||
@ -3941,6 +3952,8 @@ impl ProfileCreateBridge for api::ProfileCreate {
|
||||
is_clear_pan_retries_enabled: self.is_clear_pan_retries_enabled.unwrap_or_default(),
|
||||
is_debit_routing_enabled: self.is_debit_routing_enabled.unwrap_or_default(),
|
||||
merchant_business_country: self.merchant_business_country,
|
||||
revenue_recovery_retry_algorithm_type: None,
|
||||
revenue_recovery_retry_algorithm_data: None,
|
||||
}))
|
||||
}
|
||||
}
|
||||
@ -4546,6 +4559,33 @@ impl ProfileWrapper {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "v2")]
|
||||
pub async fn update_revenue_recovery_algorithm_under_profile(
|
||||
profile: domain::Profile,
|
||||
db: &dyn StorageInterface,
|
||||
key_manager_state: &KeyManagerState,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
revenue_recovery_retry_algorithm_type: common_enums::RevenueRecoveryAlgorithmType,
|
||||
) -> RouterResult<()> {
|
||||
let recovery_algorithm_data = diesel_models::business_profile::RevenueRecoveryAlgorithmData {
|
||||
monitoring_configured_timestamp: date_time::now(),
|
||||
};
|
||||
let profile_update = domain::ProfileUpdate::RevenueRecoveryAlgorithmUpdate {
|
||||
revenue_recovery_retry_algorithm_type,
|
||||
revenue_recovery_retry_algorithm_data: Some(recovery_algorithm_data),
|
||||
};
|
||||
|
||||
db.update_profile_by_profile_id(
|
||||
key_manager_state,
|
||||
merchant_key_store,
|
||||
profile,
|
||||
profile_update,
|
||||
)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to update revenue recovery retry algorithm in business profile")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn extended_card_info_toggle(
|
||||
state: SessionState,
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
-- This file should undo anything in `up.sql`
|
||||
ALTER TABLE business_profile
|
||||
DROP COLUMN IF EXISTS revenue_recovery_retry_algorithm_type,
|
||||
DROP COLUMN IF EXISTS revenue_recovery_retry_algorithm_data;
|
||||
|
||||
DROP TYPE IF EXISTS "RevenueRecoveryAlgorithmType";
|
||||
@ -0,0 +1,6 @@
|
||||
-- Your SQL goes here
|
||||
CREATE TYPE "RevenueRecoveryAlgorithmType" AS ENUM ('monitoring', 'smart', 'cascading');
|
||||
|
||||
ALTER TABLE business_profile
|
||||
ADD COLUMN IF NOT EXISTS revenue_recovery_retry_algorithm_type "RevenueRecoveryAlgorithmType",
|
||||
ADD COLUMN IF NOT EXISTS revenue_recovery_retry_algorithm_data JSONB;
|
||||
Reference in New Issue
Block a user