From aaabeb9731b2a5693786a0b7b43b5440d16da8df Mon Sep 17 00:00:00 2001 From: hrithikesh026 Date: Thu, 14 Nov 2024 12:59:32 +0530 Subject: [PATCH 01/10] chore: introduce database fields to support extended authorization --- crates/api_models/src/admin.rs | 3 + crates/diesel_models/Cargo.toml | 2 +- crates/diesel_models/src/business_profile.rs | 32 ++++++++++ crates/diesel_models/src/payment_attempt.rs | 59 +++++++++++++++++++ crates/diesel_models/src/payment_intent.rs | 4 ++ crates/diesel_models/src/schema.rs | 5 ++ crates/diesel_models/src/user/sample_data.rs | 6 ++ .../src/business_profile.rs | 15 ++++- .../hyperswitch_domain_models/src/payments.rs | 5 +- .../src/payments/payment_attempt.rs | 21 ++++++- .../src/payments/payment_intent.rs | 3 + crates/router/src/core/admin.rs | 1 + crates/router/src/core/payments/helpers.rs | 6 ++ .../payments/operations/payment_create.rs | 4 ++ crates/router/src/core/payments/retry.rs | 3 + crates/router/src/types/api/admin.rs | 1 + .../src/types/storage/payment_attempt.rs | 9 +++ crates/router/src/utils/user/sample_data.rs | 4 ++ .../src/mock_db/payment_attempt.rs | 3 + .../src/payments/payment_attempt.rs | 19 ++++++ .../down.sql | 16 +++++ .../up.sql | 21 +++++++ 22 files changed, 235 insertions(+), 7 deletions(-) create mode 100644 migrations/2024-11-13-090548_add-extended-authorization-related-fields/down.sql create mode 100644 migrations/2024-11-13-090548_add-extended-authorization-related-fields/up.sql diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs index 96335f34710..74dd61ab52b 100644 --- a/crates/api_models/src/admin.rs +++ b/crates/api_models/src/admin.rs @@ -1989,6 +1989,9 @@ pub struct ProfileCreate { /// Maximum number of auto retries allowed for a payment pub max_auto_retries_enabled: Option, + + /// Bool indicating if extended authentication must be requested for all payments + pub always_request_extended_authorization: Option, } #[nutype::nutype( diff --git a/crates/diesel_models/Cargo.toml b/crates/diesel_models/Cargo.toml index 120a606d58b..c7e2622cb18 100644 --- a/crates/diesel_models/Cargo.toml +++ b/crates/diesel_models/Cargo.toml @@ -17,7 +17,7 @@ payment_methods_v2 = [] [dependencies] async-bb8-diesel = { git = "https://github.com/jarnura/async-bb8-diesel", rev = "53b4ab901aab7635c8215fd1c2d542c8db443094" } -diesel = { version = "2.2.3", features = ["postgres", "serde_json", "time", "64-column-tables"] } +diesel = { version = "2.2.3", features = ["postgres", "serde_json", "time", "128-column-tables",] } error-stack = "0.4.1" rustc-hash = "1.1.0" serde = { version = "1.0.197", features = ["derive"] } diff --git a/crates/diesel_models/src/business_profile.rs b/crates/diesel_models/src/business_profile.rs index ecb53620640..49607d19264 100644 --- a/crates/diesel_models/src/business_profile.rs +++ b/crates/diesel_models/src/business_profile.rs @@ -57,6 +57,34 @@ pub struct Profile { pub is_network_tokenization_enabled: bool, pub is_auto_retries_enabled: Option, pub max_auto_retries_enabled: Option, + pub always_request_extended_authorization: Option, +} + +#[derive(Clone, Debug, Eq, PartialEq, diesel::expression::AsExpression)] +#[diesel(sql_type = diesel::sql_types::Bool)] +pub struct AlwaysRequestExtendedAuthorization(bool); +impl diesel::serialize::ToSql + for AlwaysRequestExtendedAuthorization +where + DB: diesel::backend::Backend, + bool: diesel::serialize::ToSql, +{ + fn to_sql<'b>( + &'b self, + out: &mut diesel::serialize::Output<'b, '_, DB>, + ) -> diesel::serialize::Result { + self.0.to_sql(out) + } +} +impl diesel::deserialize::FromSql + for AlwaysRequestExtendedAuthorization +where + DB: diesel::backend::Backend, + bool: diesel::deserialize::FromSql, +{ + fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result { + bool::from_sql(value).map(Self) + } } #[cfg(feature = "v1")] @@ -140,6 +168,7 @@ pub struct ProfileUpdateInternal { pub is_network_tokenization_enabled: Option, pub is_auto_retries_enabled: Option, pub max_auto_retries_enabled: Option, + pub always_request_extended_authorization: Option, } #[cfg(feature = "v1")] @@ -179,6 +208,7 @@ impl ProfileUpdateInternal { is_network_tokenization_enabled, is_auto_retries_enabled, max_auto_retries_enabled, + always_request_extended_authorization, } = self; Profile { profile_id: source.profile_id, @@ -238,6 +268,8 @@ impl ProfileUpdateInternal { .unwrap_or(source.is_network_tokenization_enabled), is_auto_retries_enabled: is_auto_retries_enabled.or(source.is_auto_retries_enabled), max_auto_retries_enabled: max_auto_retries_enabled.or(source.max_auto_retries_enabled), + always_request_extended_authorization: always_request_extended_authorization + .or(source.always_request_extended_authorization), } } } diff --git a/crates/diesel_models/src/payment_attempt.rs b/crates/diesel_models/src/payment_attempt.rs index 32ffcb545fb..812408ceb21 100644 --- a/crates/diesel_models/src/payment_attempt.rs +++ b/crates/diesel_models/src/payment_attempt.rs @@ -172,6 +172,61 @@ pub struct PaymentAttempt { pub order_tax_amount: Option, pub connector_transaction_data: Option, pub connector_mandate_detail: Option, + pub request_extended_authorization: Option, + pub extended_authorization_applied: Option, + #[serde(default, with = "common_utils::custom_serde::iso8601::option")] + pub capture_before: Option, +} + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, diesel::expression::AsExpression)] +#[diesel(sql_type = diesel::sql_types::Bool)] +pub struct ExtendedAuthorizationAppliedBool(bool); +impl diesel::serialize::ToSql for ExtendedAuthorizationAppliedBool +where + DB: diesel::backend::Backend, + bool: diesel::serialize::ToSql, +{ + fn to_sql<'b>( + &'b self, + out: &mut diesel::serialize::Output<'b, '_, DB>, + ) -> diesel::serialize::Result { + self.0.to_sql(out) + } +} +impl diesel::deserialize::FromSql + for ExtendedAuthorizationAppliedBool +where + DB: diesel::backend::Backend, + bool: diesel::deserialize::FromSql, +{ + fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result { + bool::from_sql(value).map(Self) + } +} +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, diesel::expression::AsExpression)] +#[diesel(sql_type = diesel::sql_types::Bool)] +pub struct RequestExtendedAuthorizationBool(bool); +impl diesel::serialize::ToSql for RequestExtendedAuthorizationBool +where + DB: diesel::backend::Backend, + bool: diesel::serialize::ToSql, +{ + fn to_sql<'b>( + &'b self, + out: &mut diesel::serialize::Output<'b, '_, DB>, + ) -> diesel::serialize::Result { + self.0.to_sql(out) + } +} +impl diesel::deserialize::FromSql + for RequestExtendedAuthorizationBool +where + DB: diesel::backend::Backend, + bool: diesel::deserialize::FromSql, +{ + fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result { + bool::from_sql(value).map(Self) + } } #[cfg(feature = "v1")] @@ -351,6 +406,10 @@ pub struct PaymentAttemptNew { pub shipping_cost: Option, pub order_tax_amount: Option, pub connector_mandate_detail: Option, + pub request_extended_authorization: Option, + pub extended_authorization_applied: Option, + #[serde(default, with = "common_utils::custom_serde::iso8601::option")] + pub capture_before: Option, } #[cfg(feature = "v1")] diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index 18248048110..4732ba04b8c 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -136,6 +136,8 @@ pub struct PaymentIntent { pub organization_id: common_utils::id_type::OrganizationId, pub tax_details: Option, pub skip_external_tax_calculation: Option, + pub request_extended_authorization: + Option, } #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq)] @@ -350,6 +352,8 @@ pub struct PaymentIntentNew { pub organization_id: common_utils::id_type::OrganizationId, pub tax_details: Option, pub skip_external_tax_calculation: Option, + pub request_extended_authorization: + Option, } #[cfg(feature = "v2")] diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs index 782d7f50eac..751f6c32fea 100644 --- a/crates/diesel_models/src/schema.rs +++ b/crates/diesel_models/src/schema.rs @@ -213,6 +213,7 @@ diesel::table! { is_network_tokenization_enabled -> Bool, is_auto_retries_enabled -> Nullable, max_auto_retries_enabled -> Nullable, + always_request_extended_authorization -> Nullable, } } @@ -851,6 +852,9 @@ diesel::table! { #[max_length = 512] connector_transaction_data -> Nullable, connector_mandate_detail -> Nullable, + request_extended_authorization -> Nullable, + extended_authorization_applied -> Nullable, + capture_before -> Nullable, } } @@ -931,6 +935,7 @@ diesel::table! { organization_id -> Varchar, tax_details -> Nullable, skip_external_tax_calculation -> Nullable, + request_extended_authorization -> Nullable, } } diff --git a/crates/diesel_models/src/user/sample_data.rs b/crates/diesel_models/src/user/sample_data.rs index cfc9e1c4c8e..87ad3b87abf 100644 --- a/crates/diesel_models/src/user/sample_data.rs +++ b/crates/diesel_models/src/user/sample_data.rs @@ -203,6 +203,9 @@ pub struct PaymentAttemptBatchNew { pub order_tax_amount: Option, pub connector_transaction_data: Option, pub connector_mandate_detail: Option, + pub request_extended_authorization: Option, + pub extended_authorization_applied: Option, + pub capture_before: Option, } #[cfg(feature = "v1")] @@ -282,6 +285,9 @@ impl PaymentAttemptBatchNew { shipping_cost: self.shipping_cost, order_tax_amount: self.order_tax_amount, connector_mandate_detail: self.connector_mandate_detail, + request_extended_authorization: self.request_extended_authorization, + extended_authorization_applied: self.extended_authorization_applied, + capture_before: self.capture_before, } } } diff --git a/crates/hyperswitch_domain_models/src/business_profile.rs b/crates/hyperswitch_domain_models/src/business_profile.rs index fb846e28862..dda80d235cb 100644 --- a/crates/hyperswitch_domain_models/src/business_profile.rs +++ b/crates/hyperswitch_domain_models/src/business_profile.rs @@ -7,8 +7,8 @@ use common_utils::{ types::keymanager, }; use diesel_models::business_profile::{ - AuthenticationConnectorDetails, BusinessPaymentLinkConfig, BusinessPayoutLinkConfig, - ProfileUpdateInternal, WebhookDetails, + AlwaysRequestExtendedAuthorization, AuthenticationConnectorDetails, BusinessPaymentLinkConfig, + BusinessPayoutLinkConfig, ProfileUpdateInternal, WebhookDetails, }; use error_stack::ResultExt; use masking::{PeekInterface, Secret}; @@ -58,6 +58,7 @@ pub struct Profile { pub is_network_tokenization_enabled: bool, pub is_auto_retries_enabled: bool, pub max_auto_retries_enabled: Option, + pub always_request_extended_authorization: Option, } #[cfg(feature = "v1")] @@ -98,6 +99,7 @@ pub struct ProfileSetter { pub is_network_tokenization_enabled: bool, pub is_auto_retries_enabled: bool, pub max_auto_retries_enabled: Option, + pub always_request_extended_authorization: Option, } #[cfg(feature = "v1")] @@ -145,6 +147,7 @@ impl From for Profile { is_network_tokenization_enabled: value.is_network_tokenization_enabled, is_auto_retries_enabled: value.is_auto_retries_enabled, max_auto_retries_enabled: value.max_auto_retries_enabled, + always_request_extended_authorization: value.always_request_extended_authorization, } } } @@ -293,6 +296,7 @@ impl From for ProfileUpdateInternal { is_network_tokenization_enabled, is_auto_retries_enabled, max_auto_retries_enabled, + always_request_extended_authorization: None, } } ProfileUpdate::RoutingAlgorithmUpdate { @@ -332,6 +336,7 @@ impl From for ProfileUpdateInternal { is_network_tokenization_enabled: None, is_auto_retries_enabled: None, max_auto_retries_enabled: None, + always_request_extended_authorization: None, }, ProfileUpdate::DynamicRoutingAlgorithmUpdate { dynamic_routing_algorithm, @@ -369,6 +374,7 @@ impl From for ProfileUpdateInternal { is_network_tokenization_enabled: None, is_auto_retries_enabled: None, max_auto_retries_enabled: None, + always_request_extended_authorization: None, }, ProfileUpdate::ExtendedCardInfoUpdate { is_extended_card_info_enabled, @@ -406,6 +412,7 @@ impl From for ProfileUpdateInternal { is_network_tokenization_enabled: None, is_auto_retries_enabled: None, max_auto_retries_enabled: None, + always_request_extended_authorization: None, }, ProfileUpdate::ConnectorAgnosticMitUpdate { is_connector_agnostic_mit_enabled, @@ -443,6 +450,7 @@ impl From for ProfileUpdateInternal { is_network_tokenization_enabled: None, is_auto_retries_enabled: None, max_auto_retries_enabled: None, + always_request_extended_authorization: None, }, ProfileUpdate::NetworkTokenizationUpdate { is_network_tokenization_enabled, @@ -480,6 +488,7 @@ impl From for ProfileUpdateInternal { is_network_tokenization_enabled: Some(is_network_tokenization_enabled), is_auto_retries_enabled: None, max_auto_retries_enabled: None, + always_request_extended_authorization: None, }, } } @@ -536,6 +545,7 @@ impl super::behaviour::Conversion for Profile { is_network_tokenization_enabled: self.is_network_tokenization_enabled, is_auto_retries_enabled: Some(self.is_auto_retries_enabled), max_auto_retries_enabled: self.max_auto_retries_enabled, + always_request_extended_authorization: self.always_request_extended_authorization, }) } @@ -604,6 +614,7 @@ impl super::behaviour::Conversion for Profile { is_network_tokenization_enabled: item.is_network_tokenization_enabled, is_auto_retries_enabled: item.is_auto_retries_enabled.unwrap_or(false), max_auto_retries_enabled: item.max_auto_retries_enabled, + always_request_extended_authorization: item.always_request_extended_authorization, }) } .await diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs index 8b4c351daa3..4d1761cd57b 100644 --- a/crates/hyperswitch_domain_models/src/payments.rs +++ b/crates/hyperswitch_domain_models/src/payments.rs @@ -11,7 +11,9 @@ use common_utils::{ id_type, pii, types::{keymanager::ToEncryptable, MinorUnit}, }; -use diesel_models::payment_intent::TaxDetails; +use diesel_models::{ + payment_attempt::RequestExtendedAuthorizationBool, payment_intent::TaxDetails, +}; #[cfg(feature = "v2")] use error_stack::ResultExt; use masking::Secret; @@ -99,6 +101,7 @@ pub struct PaymentIntent { pub organization_id: id_type::OrganizationId, pub tax_details: Option, pub skip_external_tax_calculation: Option, + pub request_extended_authorization: Option, } impl PaymentIntent { diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index d6fdf9f14c0..c36ef81b3ca 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -10,9 +10,9 @@ use common_utils::{ }, }; use diesel_models::{ - ConnectorMandateReferenceId, PaymentAttempt as DieselPaymentAttempt, - PaymentAttemptNew as DieselPaymentAttemptNew, - PaymentAttemptUpdate as DieselPaymentAttemptUpdate, + ConnectorMandateReferenceId, ExtendedAuthorizationAppliedBool, + PaymentAttempt as DieselPaymentAttempt, PaymentAttemptNew as DieselPaymentAttemptNew, + PaymentAttemptUpdate as DieselPaymentAttemptUpdate, RequestExtendedAuthorizationBool, }; use error_stack::ResultExt; #[cfg(feature = "v2")] @@ -479,6 +479,9 @@ pub struct PaymentAttempt { pub profile_id: id_type::ProfileId, pub organization_id: id_type::OrganizationId, pub connector_mandate_detail: Option, + pub request_extended_authentication: Option, + pub extended_authentication_applied: Option, + pub capture_before: Option, } #[cfg(feature = "v1")] @@ -724,6 +727,9 @@ pub struct PaymentAttemptNew { pub profile_id: id_type::ProfileId, pub organization_id: id_type::OrganizationId, pub connector_mandate_detail: Option, + pub request_extended_authorization: Option, + pub extended_authorization_applied: Option, + pub capture_before: Option, } #[cfg(feature = "v1")] @@ -1414,6 +1420,9 @@ impl behaviour::Conversion for PaymentAttempt { order_tax_amount: self.net_amount.get_order_tax_amount(), shipping_cost: self.net_amount.get_shipping_cost(), connector_mandate_detail: self.connector_mandate_detail, + request_extended_authorization: self.request_extended_authentication, + extended_authorization_applied: self.extended_authentication_applied, + capture_before: self.capture_before, }) } @@ -1495,6 +1504,9 @@ impl behaviour::Conversion for PaymentAttempt { profile_id: storage_model.profile_id, organization_id: storage_model.organization_id, connector_mandate_detail: storage_model.connector_mandate_detail, + request_extended_authentication: storage_model.request_extended_authorization, + extended_authentication_applied: storage_model.extended_authorization_applied, + capture_before: storage_model.capture_before, }) } .await @@ -1577,6 +1589,9 @@ impl behaviour::Conversion for PaymentAttempt { order_tax_amount: self.net_amount.get_order_tax_amount(), shipping_cost: self.net_amount.get_shipping_cost(), connector_mandate_detail: self.connector_mandate_detail, + request_extended_authorization: self.request_extended_authentication, + extended_authorization_applied: self.extended_authentication_applied, + capture_before: self.capture_before, }) } } diff --git a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs index 4f2053ec6f9..f0b1a159187 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs @@ -1551,6 +1551,7 @@ impl behaviour::Conversion for PaymentIntent { shipping_cost: self.shipping_cost, tax_details: self.tax_details, skip_external_tax_calculation: self.skip_external_tax_calculation, + request_extended_authorization: self.request_extended_authorization, }) } @@ -1638,6 +1639,7 @@ impl behaviour::Conversion for PaymentIntent { is_payment_processor_token_flow: storage_model.is_payment_processor_token_flow, organization_id: storage_model.organization_id, skip_external_tax_calculation: storage_model.skip_external_tax_calculation, + request_extended_authorization: storage_model.request_extended_authorization, }) } .await @@ -1700,6 +1702,7 @@ impl behaviour::Conversion for PaymentIntent { shipping_cost: self.shipping_cost, tax_details: self.tax_details, skip_external_tax_calculation: self.skip_external_tax_calculation, + request_extended_authorization: self.request_extended_authorization, }) } } diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index 68f2b9d6343..41bc9d8f0d8 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -3556,6 +3556,7 @@ impl ProfileCreateBridge for api::ProfileCreate { is_network_tokenization_enabled: self.is_network_tokenization_enabled, is_auto_retries_enabled: self.is_auto_retries_enabled.unwrap_or_default(), max_auto_retries_enabled: self.max_auto_retries_enabled.map(i16::from), + always_request_extended_authorization: todo!(), })) } diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index acaccccbb17..a5d493bdeac 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -3464,6 +3464,7 @@ mod tests { shipping_cost: None, tax_details: None, skip_external_tax_calculation: None, + request_extended_authorization: None, }; let req_cs = Some("1".to_string()); assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent).is_ok()); @@ -3533,6 +3534,7 @@ mod tests { shipping_cost: None, tax_details: None, skip_external_tax_calculation: None, + request_extended_authorization: None, }; let req_cs = Some("1".to_string()); assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent,).is_err()) @@ -3600,6 +3602,7 @@ mod tests { shipping_cost: None, tax_details: None, skip_external_tax_calculation: None, + request_extended_authorization: None, }; let req_cs = Some("1".to_string()); assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent).is_err()) @@ -4134,6 +4137,9 @@ impl AttemptType { organization_id: old_payment_attempt.organization_id, profile_id: old_payment_attempt.profile_id, connector_mandate_detail: None, + request_extended_authorization: None, + extended_authorization_applied: None, + capture_before: None, } } diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index c65e58ea2d4..d877d06e045 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -1267,6 +1267,9 @@ impl PaymentCreate { organization_id: organization_id.clone(), profile_id, connector_mandate_detail: None, + request_extended_authorization: None, + extended_authorization_applied: None, + capture_before: None, }, additional_pm_data, @@ -1474,6 +1477,7 @@ impl PaymentCreate { shipping_cost: request.shipping_cost, tax_details: None, skip_external_tax_calculation, + request_extended_authorization: None, }) } diff --git a/crates/router/src/core/payments/retry.rs b/crates/router/src/core/payments/retry.rs index fed28b68011..60ba609828a 100644 --- a/crates/router/src/core/payments/retry.rs +++ b/crates/router/src/core/payments/retry.rs @@ -654,6 +654,9 @@ pub fn make_new_payment_attempt( charge_id: Default::default(), customer_acceptance: Default::default(), connector_mandate_detail: Default::default(), + request_extended_authorization: Default::default(), + extended_authorization_applied: Default::default(), + capture_before: Default::default(), } } diff --git a/crates/router/src/types/api/admin.rs b/crates/router/src/types/api/admin.rs index c81fc7ceb48..b3de6b460e7 100644 --- a/crates/router/src/types/api/admin.rs +++ b/crates/router/src/types/api/admin.rs @@ -363,5 +363,6 @@ pub async fn create_profile_from_merchant_account( is_network_tokenization_enabled: request.is_network_tokenization_enabled, is_auto_retries_enabled: request.is_auto_retries_enabled.unwrap_or_default(), max_auto_retries_enabled: request.max_auto_retries_enabled.map(i16::from), + always_request_extended_authorization: todo!(), })) } diff --git a/crates/router/src/types/storage/payment_attempt.rs b/crates/router/src/types/storage/payment_attempt.rs index 0291374d54f..453b8e08f55 100644 --- a/crates/router/src/types/storage/payment_attempt.rs +++ b/crates/router/src/types/storage/payment_attempt.rs @@ -217,6 +217,9 @@ mod tests { profile_id: common_utils::generate_profile_id_of_default_length(), organization_id: Default::default(), connector_mandate_detail: Default::default(), + request_extended_authorization: Default::default(), + extended_authorization_applied: Default::default(), + capture_before: Default::default(), }; let store = state @@ -301,6 +304,9 @@ mod tests { profile_id: common_utils::generate_profile_id_of_default_length(), organization_id: Default::default(), connector_mandate_detail: Default::default(), + request_extended_authorization: Default::default(), + extended_authorization_applied: Default::default(), + capture_before: Default::default(), }; let store = state .stores @@ -398,6 +404,9 @@ mod tests { profile_id: common_utils::generate_profile_id_of_default_length(), organization_id: Default::default(), connector_mandate_detail: Default::default(), + request_extended_authorization: Default::default(), + extended_authorization_applied: Default::default(), + capture_before: Default::default(), }; let store = state .stores diff --git a/crates/router/src/utils/user/sample_data.rs b/crates/router/src/utils/user/sample_data.rs index 4f859d8e56a..723399730a3 100644 --- a/crates/router/src/utils/user/sample_data.rs +++ b/crates/router/src/utils/user/sample_data.rs @@ -274,6 +274,7 @@ pub async fn generate_sample_data( shipping_cost: None, tax_details: None, skip_external_tax_calculation: None, + request_extended_authorization: None, }; let (connector_transaction_id, connector_transaction_data) = ConnectorTransactionId::form_id_and_data(attempt_id.clone()); @@ -359,6 +360,9 @@ pub async fn generate_sample_data( order_tax_amount: None, connector_transaction_data, connector_mandate_detail: None, + request_extended_authorization: None, + extended_authorization_applied: None, + capture_before: None, }; let refund = if refunds_count < number_of_refunds && !is_failed_payment { diff --git a/crates/storage_impl/src/mock_db/payment_attempt.rs b/crates/storage_impl/src/mock_db/payment_attempt.rs index ae4a9e659a6..efa34d41755 100644 --- a/crates/storage_impl/src/mock_db/payment_attempt.rs +++ b/crates/storage_impl/src/mock_db/payment_attempt.rs @@ -182,6 +182,9 @@ impl PaymentAttemptInterface for MockDb { organization_id: payment_attempt.organization_id, profile_id: payment_attempt.profile_id, connector_mandate_detail: payment_attempt.connector_mandate_detail, + request_extended_authentication: payment_attempt.request_extended_authorization, + extended_authentication_applied: payment_attempt.extended_authorization_applied, + capture_before: payment_attempt.capture_before, }; payment_attempts.push(payment_attempt.clone()); Ok(payment_attempt) diff --git a/crates/storage_impl/src/payments/payment_attempt.rs b/crates/storage_impl/src/payments/payment_attempt.rs index 7bc9bcc8a92..6c967fa2fe3 100644 --- a/crates/storage_impl/src/payments/payment_attempt.rs +++ b/crates/storage_impl/src/payments/payment_attempt.rs @@ -534,6 +534,13 @@ impl PaymentAttemptInterface for KVRouterStore { organization_id: payment_attempt.organization_id.clone(), profile_id: payment_attempt.profile_id.clone(), connector_mandate_detail: payment_attempt.connector_mandate_detail.clone(), + request_extended_authentication: payment_attempt + .request_extended_authorization + .clone(), + extended_authentication_applied: payment_attempt + .extended_authorization_applied + .clone(), + capture_before: payment_attempt.capture_before.clone(), }; let field = format!("pa_{}", created_attempt.attempt_id); @@ -1459,6 +1466,9 @@ impl DataModelExt for PaymentAttempt { shipping_cost: self.net_amount.get_shipping_cost(), order_tax_amount: self.net_amount.get_order_tax_amount(), connector_mandate_detail: self.connector_mandate_detail, + request_extended_authorization: self.request_extended_authentication, + extended_authorization_applied: self.extended_authentication_applied, + capture_before: self.capture_before, } } @@ -1535,6 +1545,9 @@ impl DataModelExt for PaymentAttempt { organization_id: storage_model.organization_id, profile_id: storage_model.profile_id, connector_mandate_detail: storage_model.connector_mandate_detail, + request_extended_authentication: storage_model.request_extended_authorization, + extended_authentication_applied: storage_model.extended_authorization_applied, + capture_before: storage_model.capture_before, } } } @@ -1618,6 +1631,9 @@ impl DataModelExt for PaymentAttemptNew { shipping_cost: self.net_amount.get_shipping_cost(), order_tax_amount: self.net_amount.get_order_tax_amount(), connector_mandate_detail: self.connector_mandate_detail, + request_extended_authorization: self.request_extended_authorization, + extended_authorization_applied: self.extended_authorization_applied, + capture_before: self.capture_before, } } @@ -1690,6 +1706,9 @@ impl DataModelExt for PaymentAttemptNew { organization_id: storage_model.organization_id, profile_id: storage_model.profile_id, connector_mandate_detail: storage_model.connector_mandate_detail, + request_extended_authorization: storage_model.request_extended_authorization, + extended_authorization_applied: storage_model.extended_authorization_applied, + capture_before: storage_model.capture_before, } } } diff --git a/migrations/2024-11-13-090548_add-extended-authorization-related-fields/down.sql b/migrations/2024-11-13-090548_add-extended-authorization-related-fields/down.sql new file mode 100644 index 00000000000..a5e982f8ac3 --- /dev/null +++ b/migrations/2024-11-13-090548_add-extended-authorization-related-fields/down.sql @@ -0,0 +1,16 @@ +-- Remove the 'request_extended_authorization' column from the 'payment_intent' table +ALTER TABLE payment_intent +DROP COLUMN request_extended_authorization; + +-- Remove the 'request_extended_authorization' and 'extended_authorization_applied' columns from the 'payment_attempt' table +ALTER TABLE payment_attempt +DROP COLUMN request_extended_authorization, +DROP COLUMN extended_authorization_applied; + +-- Remove the 'capture_before' column from the 'payment_attempt' table +ALTER TABLE payment_attempt +DROP COLUMN capture_before; + +-- Remove the 'always_request_extended_authorization' column from the 'business_profile' table +ALTER TABLE business_profile +DROP COLUMN always_request_extended_authorization; \ No newline at end of file diff --git a/migrations/2024-11-13-090548_add-extended-authorization-related-fields/up.sql b/migrations/2024-11-13-090548_add-extended-authorization-related-fields/up.sql new file mode 100644 index 00000000000..ab5eac19411 --- /dev/null +++ b/migrations/2024-11-13-090548_add-extended-authorization-related-fields/up.sql @@ -0,0 +1,21 @@ +-- stores the flag send by the merchant during payments-create call +ALTER TABLE payment_intent +ADD COLUMN request_extended_authorization boolean; + + +ALTER TABLE payment_attempt +-- stores the flag sent to the connector +ADD COLUMN request_extended_authorization boolean; + +ALTER TABLE payment_attempt +-- Set to true if extended authentication request was successfully processed by the connector +ADD COLUMN extended_authorization_applied boolean; + + +ALTER TABLE payment_attempt +-- stores the flag sent to the connector +ADD COLUMN capture_before timestamp; + +ALTER TABLE business_profile +-- merchant can configure the default value for request_extended_authorization here +ADD COLUMN always_request_extended_authorization boolean; From e97e342445d291ff3afced201b4ac139872cd229 Mon Sep 17 00:00:00 2001 From: hrithikesh026 Date: Tue, 19 Nov 2024 13:04:02 +0530 Subject: [PATCH 02/10] move bool wrappers to common_utils crate --- crates/api_models/src/admin.rs | 7 +- crates/common_utils/src/types.rs | 7 ++ .../src/types/primitive_wrappers.rs | 91 +++++++++++++++++++ crates/diesel_models/src/business_profile.rs | 29 +----- crates/diesel_models/src/payment_attempt.rs | 56 +----------- crates/diesel_models/src/payment_intent.rs | 12 ++- crates/diesel_models/src/user/sample_data.rs | 9 +- .../src/business_profile.rs | 6 +- .../hyperswitch_domain_models/src/payments.rs | 6 +- .../src/payments/payment_attempt.rs | 9 +- crates/router/src/core/admin.rs | 2 +- crates/router/src/types/api/admin.rs | 2 +- 12 files changed, 133 insertions(+), 103 deletions(-) create mode 100644 crates/common_utils/src/types/primitive_wrappers.rs diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs index 74dd61ab52b..ef4cd625375 100644 --- a/crates/api_models/src/admin.rs +++ b/crates/api_models/src/admin.rs @@ -8,7 +8,10 @@ use common_utils::{ id_type, link_utils, pii, }; #[cfg(feature = "v1")] -use common_utils::{crypto::OptionalEncryptableName, ext_traits::ValueExt}; +use common_utils::{ + crypto::OptionalEncryptableName, ext_traits::ValueExt, + types::AlwaysRequestExtendedAuthorization, +}; #[cfg(feature = "v2")] use masking::ExposeInterface; use masking::Secret; @@ -1991,7 +1994,7 @@ pub struct ProfileCreate { pub max_auto_retries_enabled: Option, /// Bool indicating if extended authentication must be requested for all payments - pub always_request_extended_authorization: Option, + pub always_request_extended_authorization: Option, } #[nutype::nutype( diff --git a/crates/common_utils/src/types.rs b/crates/common_utils/src/types.rs index ef7a4b847c4..de0613131a5 100644 --- a/crates/common_utils/src/types.rs +++ b/crates/common_utils/src/types.rs @@ -4,6 +4,9 @@ pub mod keymanager; /// Enum for Authentication Level pub mod authentication; +/// types that are wrappers aroung primitive types +pub mod primitive_wrappers; + use std::{ borrow::Cow, fmt::Display, @@ -24,6 +27,10 @@ use diesel::{ AsExpression, FromSqlRow, Queryable, }; use error_stack::{report, ResultExt}; +pub use primitive_wrappers::bool_wrappers::{ + AlwaysRequestExtendedAuthorization, ExtendedAuthorizationAppliedBool, + RequestExtendedAuthorizationBool, +}; use rust_decimal::{ prelude::{FromPrimitive, ToPrimitive}, Decimal, diff --git a/crates/common_utils/src/types/primitive_wrappers.rs b/crates/common_utils/src/types/primitive_wrappers.rs new file mode 100644 index 00000000000..f9e9b878491 --- /dev/null +++ b/crates/common_utils/src/types/primitive_wrappers.rs @@ -0,0 +1,91 @@ +pub(crate) mod bool_wrappers { + use serde::{Deserialize, Serialize}; + + /// Bool that represents if Extended Authorization is Applied or not + #[derive( + Clone, Debug, Eq, PartialEq, Serialize, Deserialize, diesel::expression::AsExpression, + )] + #[diesel(sql_type = diesel::sql_types::Bool)] + pub struct ExtendedAuthorizationAppliedBool(bool); + impl diesel::serialize::ToSql for ExtendedAuthorizationAppliedBool + where + DB: diesel::backend::Backend, + bool: diesel::serialize::ToSql, + { + fn to_sql<'b>( + &'b self, + out: &mut diesel::serialize::Output<'b, '_, DB>, + ) -> diesel::serialize::Result { + self.0.to_sql(out) + } + } + impl diesel::deserialize::FromSql + for ExtendedAuthorizationAppliedBool + where + DB: diesel::backend::Backend, + bool: diesel::deserialize::FromSql, + { + fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result { + bool::from_sql(value).map(Self) + } + } + + /// Bool that represents if Extended Authorization is Requested or not + #[derive( + Clone, Debug, Eq, PartialEq, Serialize, Deserialize, diesel::expression::AsExpression, + )] + #[diesel(sql_type = diesel::sql_types::Bool)] + pub struct RequestExtendedAuthorizationBool(bool); + impl diesel::serialize::ToSql for RequestExtendedAuthorizationBool + where + DB: diesel::backend::Backend, + bool: diesel::serialize::ToSql, + { + fn to_sql<'b>( + &'b self, + out: &mut diesel::serialize::Output<'b, '_, DB>, + ) -> diesel::serialize::Result { + self.0.to_sql(out) + } + } + impl diesel::deserialize::FromSql + for RequestExtendedAuthorizationBool + where + DB: diesel::backend::Backend, + bool: diesel::deserialize::FromSql, + { + fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result { + bool::from_sql(value).map(Self) + } + } + + /// Bool that represents if Extended Authorization is always Requested or not + #[derive( + Clone, Debug, Eq, PartialEq, diesel::expression::AsExpression, Serialize, Deserialize, + )] + #[diesel(sql_type = diesel::sql_types::Bool)] + pub struct AlwaysRequestExtendedAuthorization(bool); + impl diesel::serialize::ToSql + for AlwaysRequestExtendedAuthorization + where + DB: diesel::backend::Backend, + bool: diesel::serialize::ToSql, + { + fn to_sql<'b>( + &'b self, + out: &mut diesel::serialize::Output<'b, '_, DB>, + ) -> diesel::serialize::Result { + self.0.to_sql(out) + } + } + impl diesel::deserialize::FromSql + for AlwaysRequestExtendedAuthorization + where + DB: diesel::backend::Backend, + bool: diesel::deserialize::FromSql, + { + fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result { + bool::from_sql(value).map(Self) + } + } +} diff --git a/crates/diesel_models/src/business_profile.rs b/crates/diesel_models/src/business_profile.rs index 49607d19264..c249974fb69 100644 --- a/crates/diesel_models/src/business_profile.rs +++ b/crates/diesel_models/src/business_profile.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use common_enums::{AuthenticationConnectors, UIWidgetFormLayout}; -use common_utils::{encryption::Encryption, pii}; +use common_utils::{encryption::Encryption, pii, types::AlwaysRequestExtendedAuthorization}; use diesel::{AsChangeset, Identifiable, Insertable, Queryable, Selectable}; use masking::Secret; @@ -60,33 +60,6 @@ pub struct Profile { pub always_request_extended_authorization: Option, } -#[derive(Clone, Debug, Eq, PartialEq, diesel::expression::AsExpression)] -#[diesel(sql_type = diesel::sql_types::Bool)] -pub struct AlwaysRequestExtendedAuthorization(bool); -impl diesel::serialize::ToSql - for AlwaysRequestExtendedAuthorization -where - DB: diesel::backend::Backend, - bool: diesel::serialize::ToSql, -{ - fn to_sql<'b>( - &'b self, - out: &mut diesel::serialize::Output<'b, '_, DB>, - ) -> diesel::serialize::Result { - self.0.to_sql(out) - } -} -impl diesel::deserialize::FromSql - for AlwaysRequestExtendedAuthorization -where - DB: diesel::backend::Backend, - bool: diesel::deserialize::FromSql, -{ - fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result { - bool::from_sql(value).map(Self) - } -} - #[cfg(feature = "v1")] #[derive(Clone, Debug, Insertable, router_derive::DebugAsDisplay)] #[diesel(table_name = business_profile, primary_key(profile_id))] diff --git a/crates/diesel_models/src/payment_attempt.rs b/crates/diesel_models/src/payment_attempt.rs index 812408ceb21..813e28d83f7 100644 --- a/crates/diesel_models/src/payment_attempt.rs +++ b/crates/diesel_models/src/payment_attempt.rs @@ -1,6 +1,9 @@ use common_utils::{ id_type, pii, - types::{ConnectorTransactionId, ConnectorTransactionIdTrait, MinorUnit}, + types::{ + ConnectorTransactionId, ConnectorTransactionIdTrait, ExtendedAuthorizationAppliedBool, + MinorUnit, RequestExtendedAuthorizationBool, + }, }; use diesel::{AsChangeset, Identifiable, Insertable, Queryable, Selectable}; use serde::{Deserialize, Serialize}; @@ -178,57 +181,6 @@ pub struct PaymentAttempt { pub capture_before: Option, } -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, diesel::expression::AsExpression)] -#[diesel(sql_type = diesel::sql_types::Bool)] -pub struct ExtendedAuthorizationAppliedBool(bool); -impl diesel::serialize::ToSql for ExtendedAuthorizationAppliedBool -where - DB: diesel::backend::Backend, - bool: diesel::serialize::ToSql, -{ - fn to_sql<'b>( - &'b self, - out: &mut diesel::serialize::Output<'b, '_, DB>, - ) -> diesel::serialize::Result { - self.0.to_sql(out) - } -} -impl diesel::deserialize::FromSql - for ExtendedAuthorizationAppliedBool -where - DB: diesel::backend::Backend, - bool: diesel::deserialize::FromSql, -{ - fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result { - bool::from_sql(value).map(Self) - } -} -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, diesel::expression::AsExpression)] -#[diesel(sql_type = diesel::sql_types::Bool)] -pub struct RequestExtendedAuthorizationBool(bool); -impl diesel::serialize::ToSql for RequestExtendedAuthorizationBool -where - DB: diesel::backend::Backend, - bool: diesel::serialize::ToSql, -{ - fn to_sql<'b>( - &'b self, - out: &mut diesel::serialize::Output<'b, '_, DB>, - ) -> diesel::serialize::Result { - self.0.to_sql(out) - } -} -impl diesel::deserialize::FromSql - for RequestExtendedAuthorizationBool -where - DB: diesel::backend::Backend, - bool: diesel::deserialize::FromSql, -{ - fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result { - bool::from_sql(value).map(Self) - } -} - #[cfg(feature = "v1")] impl ConnectorTransactionIdTrait for PaymentAttempt { fn get_optional_connector_transaction_id(&self) -> Option<&String> { diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index 4732ba04b8c..99f4e2f7476 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -1,5 +1,9 @@ use common_enums::{PaymentMethodType, RequestIncrementalAuthorization}; -use common_utils::{encryption::Encryption, pii, types::MinorUnit}; +use common_utils::{ + encryption::Encryption, + pii, + types::{MinorUnit, RequestExtendedAuthorizationBool}, +}; use diesel::{AsChangeset, Identifiable, Insertable, Queryable, Selectable}; use serde::{Deserialize, Serialize}; use time::PrimitiveDateTime; @@ -136,8 +140,7 @@ pub struct PaymentIntent { pub organization_id: common_utils::id_type::OrganizationId, pub tax_details: Option, pub skip_external_tax_calculation: Option, - pub request_extended_authorization: - Option, + pub request_extended_authorization: Option, } #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq)] @@ -352,8 +355,7 @@ pub struct PaymentIntentNew { pub organization_id: common_utils::id_type::OrganizationId, pub tax_details: Option, pub skip_external_tax_calculation: Option, - pub request_extended_authorization: - Option, + pub request_extended_authorization: Option, } #[cfg(feature = "v2")] diff --git a/crates/diesel_models/src/user/sample_data.rs b/crates/diesel_models/src/user/sample_data.rs index 87ad3b87abf..53e3b3869b2 100644 --- a/crates/diesel_models/src/user/sample_data.rs +++ b/crates/diesel_models/src/user/sample_data.rs @@ -2,7 +2,10 @@ use common_enums::{ AttemptStatus, AuthenticationType, CaptureMethod, Currency, PaymentExperience, PaymentMethod, PaymentMethodType, }; -use common_utils::types::{ConnectorTransactionId, MinorUnit}; +use common_utils::types::{ + ConnectorTransactionId, ExtendedAuthorizationAppliedBool, MinorUnit, + RequestExtendedAuthorizationBool, +}; use serde::{Deserialize, Serialize}; use time::PrimitiveDateTime; @@ -203,8 +206,8 @@ pub struct PaymentAttemptBatchNew { pub order_tax_amount: Option, pub connector_transaction_data: Option, pub connector_mandate_detail: Option, - pub request_extended_authorization: Option, - pub extended_authorization_applied: Option, + pub request_extended_authorization: Option, + pub extended_authorization_applied: Option, pub capture_before: Option, } diff --git a/crates/hyperswitch_domain_models/src/business_profile.rs b/crates/hyperswitch_domain_models/src/business_profile.rs index dda80d235cb..d2fae0b56df 100644 --- a/crates/hyperswitch_domain_models/src/business_profile.rs +++ b/crates/hyperswitch_domain_models/src/business_profile.rs @@ -4,11 +4,11 @@ use common_utils::{ encryption::Encryption, errors::{CustomResult, ValidationError}, pii, type_name, - types::keymanager, + types::{keymanager, AlwaysRequestExtendedAuthorization}, }; use diesel_models::business_profile::{ - AlwaysRequestExtendedAuthorization, AuthenticationConnectorDetails, BusinessPaymentLinkConfig, - BusinessPayoutLinkConfig, ProfileUpdateInternal, WebhookDetails, + AuthenticationConnectorDetails, BusinessPaymentLinkConfig, BusinessPayoutLinkConfig, + ProfileUpdateInternal, WebhookDetails, }; use error_stack::ResultExt; use masking::{PeekInterface, Secret}; diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs index 4d1761cd57b..d311147d856 100644 --- a/crates/hyperswitch_domain_models/src/payments.rs +++ b/crates/hyperswitch_domain_models/src/payments.rs @@ -9,11 +9,9 @@ use common_utils::{ encryption::Encryption, errors::CustomResult, id_type, pii, - types::{keymanager::ToEncryptable, MinorUnit}, -}; -use diesel_models::{ - payment_attempt::RequestExtendedAuthorizationBool, payment_intent::TaxDetails, + types::{keymanager::ToEncryptable, MinorUnit, RequestExtendedAuthorizationBool}, }; +use diesel_models::payment_intent::TaxDetails; #[cfg(feature = "v2")] use error_stack::ResultExt; use masking::Secret; diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index c36ef81b3ca..6badb3971e2 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -6,13 +6,14 @@ use common_utils::{ id_type, pii, types::{ keymanager::{self, KeyManagerState}, - ConnectorTransactionId, ConnectorTransactionIdTrait, MinorUnit, + ConnectorTransactionId, ConnectorTransactionIdTrait, ExtendedAuthorizationAppliedBool, + MinorUnit, RequestExtendedAuthorizationBool, }, }; use diesel_models::{ - ConnectorMandateReferenceId, ExtendedAuthorizationAppliedBool, - PaymentAttempt as DieselPaymentAttempt, PaymentAttemptNew as DieselPaymentAttemptNew, - PaymentAttemptUpdate as DieselPaymentAttemptUpdate, RequestExtendedAuthorizationBool, + ConnectorMandateReferenceId, PaymentAttempt as DieselPaymentAttempt, + PaymentAttemptNew as DieselPaymentAttemptNew, + PaymentAttemptUpdate as DieselPaymentAttemptUpdate, }; use error_stack::ResultExt; #[cfg(feature = "v2")] diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index 41bc9d8f0d8..a71171e4b72 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -3556,7 +3556,7 @@ impl ProfileCreateBridge for api::ProfileCreate { is_network_tokenization_enabled: self.is_network_tokenization_enabled, is_auto_retries_enabled: self.is_auto_retries_enabled.unwrap_or_default(), max_auto_retries_enabled: self.max_auto_retries_enabled.map(i16::from), - always_request_extended_authorization: todo!(), + always_request_extended_authorization: self.always_request_extended_authorization, })) } diff --git a/crates/router/src/types/api/admin.rs b/crates/router/src/types/api/admin.rs index b3de6b460e7..1c15fd12aeb 100644 --- a/crates/router/src/types/api/admin.rs +++ b/crates/router/src/types/api/admin.rs @@ -363,6 +363,6 @@ pub async fn create_profile_from_merchant_account( is_network_tokenization_enabled: request.is_network_tokenization_enabled, is_auto_retries_enabled: request.is_auto_retries_enabled.unwrap_or_default(), max_auto_retries_enabled: request.max_auto_retries_enabled.map(i16::from), - always_request_extended_authorization: todo!(), + always_request_extended_authorization: request.always_request_extended_authorization, })) } From 385f5f2536b9a2261f78a800da68a0c4dc327d9b Mon Sep 17 00:00:00 2001 From: hrithikesh026 Date: Tue, 19 Nov 2024 15:46:32 +0530 Subject: [PATCH 03/10] add extended authorization related fields to payments api models --- crates/api_models/src/lib.rs | 9 +++++ crates/api_models/src/payments.rs | 34 +++++++++++++++++-- crates/api_models/src/payments/trait_impls.rs | 24 +++++++++++++ .../src/payments/payment_attempt.rs | 8 ++--- .../router/src/core/payments/transformers.rs | 4 +++ crates/router/tests/payments.rs | 4 +++ crates/router/tests/payments2.rs | 4 +++ .../src/mock_db/payment_attempt.rs | 2 +- .../src/payments/payment_attempt.rs | 6 ++-- 9 files changed, 85 insertions(+), 10 deletions(-) create mode 100644 crates/api_models/src/payments/trait_impls.rs diff --git a/crates/api_models/src/lib.rs b/crates/api_models/src/lib.rs index a28332e7fea..3468f44b1c0 100644 --- a/crates/api_models/src/lib.rs +++ b/crates/api_models/src/lib.rs @@ -39,3 +39,12 @@ pub mod verifications; pub mod verify_connector; pub mod webhook_events; pub mod webhooks; + +pub trait ValidateFieldAndGet { + fn validate_field_and_get( + &self, + request: &Request, + ) -> common_utils::errors::CustomResult + where + Self: Sized; +} diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 567d601c45c..f9ce7ab3642 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -4,6 +4,7 @@ use std::{ num::NonZeroI64, }; pub mod additional_info; +pub mod trait_impls; use cards::CardNumber; use common_enums::ProductType; #[cfg(feature = "v2")] @@ -16,7 +17,10 @@ use common_utils::{ hashing::HashedString, id_type, pii::{self, Email}, - types::{MinorUnit, StringMajorUnit}, + types::{ + ExtendedAuthorizationAppliedBool, MinorUnit, RequestExtendedAuthorizationBool, + StringMajorUnit, + }, }; use error_stack::ResultExt; use masking::{PeekInterface, Secret, WithType}; @@ -32,7 +36,7 @@ use crate::{ disputes, enums as api_enums, ephemeral_key::EphemeralKeyCreateResponse, mandates::RecurringDetails, - refunds, + refunds, ValidateFieldAndGet, }; #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -846,6 +850,12 @@ pub struct PaymentsRequest { /// Fee information to be charged on the payment being collected pub charges: Option, + /// Optional boolean value to extent authorization period of this payment + /// + /// capture method must be manual or manual_multiple + #[schema(value_type = Option, default = false)] + pub request_extended_authorization: Option, + /// Merchant's identifier for the payment/invoice. This will be sent to the connector /// if the connector provides support to accept multiple reference ids. /// In case the connector supports only one reference id, Hyperswitch's Payment ID will be sent as reference. @@ -885,6 +895,18 @@ impl PaymentsRequest { .or(self.customer.as_ref().map(|customer| &customer.id)) } + pub fn validate_and_get_request_extended_authorization( + &self, + ) -> common_utils::errors::CustomResult, ValidationError> + { + self.request_extended_authorization + .as_ref() + .map(|request_extended_authorization| { + request_extended_authorization.validate_field_and_get(self) + }) + .transpose() + } + /// Checks if the customer details are passed in both places /// If they are passed in both places, check for both the values to be equal /// Or else, return the field which has inconsistent data @@ -4437,6 +4459,14 @@ pub struct PaymentsResponse { #[schema(value_type = Option, example = r#"{ "fulfillment_method" : "deliver", "coverage_request" : "fraud" }"#)] pub frm_metadata: Option, + /// flag that indicates if extended authorization is applied on this payment or not + #[schema(value_type = Option)] + pub extended_authorization_applied: Option, + + /// date and time after which this payment cannot be captured + #[serde(default, with = "common_utils::custom_serde::iso8601::option")] + pub capture_before: Option, + /// Merchant's identifier for the payment/invoice. This will be sent to the connector /// if the connector provides support to accept multiple reference ids. /// In case the connector supports only one reference id, Hyperswitch's Payment ID will be sent as reference. diff --git a/crates/api_models/src/payments/trait_impls.rs b/crates/api_models/src/payments/trait_impls.rs new file mode 100644 index 00000000000..4f3b212594a --- /dev/null +++ b/crates/api_models/src/payments/trait_impls.rs @@ -0,0 +1,24 @@ +use common_enums::enums; +use common_utils::errors; + +use crate::payments; + +impl crate::ValidateFieldAndGet + for common_utils::types::RequestExtendedAuthorizationBool +{ + fn validate_field_and_get( + &self, + request: &payments::PaymentsRequest, + ) -> errors::CustomResult + where + Self: Sized, + { + match request.capture_method{ + Some(enums::CaptureMethod::Automatic) + | Some(enums::CaptureMethod::Scheduled) + | None => Err(error_stack::report!(errors::ValidationError::InvalidValue { message: "request_extended_authorization must be sent only if capture method is manual or manual_multiple".to_string() })), + Some(enums::CaptureMethod::Manual) + | Some(enums::CaptureMethod::ManualMultiple) => Ok(self.clone()) + } + } +} diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index 6badb3971e2..05183eba0ce 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -481,7 +481,7 @@ pub struct PaymentAttempt { pub organization_id: id_type::OrganizationId, pub connector_mandate_detail: Option, pub request_extended_authentication: Option, - pub extended_authentication_applied: Option, + pub extended_authorization_applied: Option, pub capture_before: Option, } @@ -1422,7 +1422,7 @@ impl behaviour::Conversion for PaymentAttempt { shipping_cost: self.net_amount.get_shipping_cost(), connector_mandate_detail: self.connector_mandate_detail, request_extended_authorization: self.request_extended_authentication, - extended_authorization_applied: self.extended_authentication_applied, + extended_authorization_applied: self.extended_authorization_applied, capture_before: self.capture_before, }) } @@ -1506,7 +1506,7 @@ impl behaviour::Conversion for PaymentAttempt { organization_id: storage_model.organization_id, connector_mandate_detail: storage_model.connector_mandate_detail, request_extended_authentication: storage_model.request_extended_authorization, - extended_authentication_applied: storage_model.extended_authorization_applied, + extended_authorization_applied: storage_model.extended_authorization_applied, capture_before: storage_model.capture_before, }) } @@ -1591,7 +1591,7 @@ impl behaviour::Conversion for PaymentAttempt { shipping_cost: self.net_amount.get_shipping_cost(), connector_mandate_detail: self.connector_mandate_detail, request_extended_authorization: self.request_extended_authentication, - extended_authorization_applied: self.extended_authentication_applied, + extended_authorization_applied: self.extended_authorization_applied, capture_before: self.capture_before, }) } diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 52c0f69be16..9416ccd2d3f 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -1878,6 +1878,8 @@ where order_tax_amount, connector_mandate_id, shipping_cost: payment_intent.shipping_cost, + capture_before: payment_attempt.capture_before, + extended_authorization_applied: payment_attempt.extended_authorization_applied, }; services::ApplicationResponse::JsonWithHeaders((payments_response, headers)) @@ -2132,6 +2134,8 @@ impl ForeignFrom<(storage::PaymentIntent, storage::PaymentAttempt)> for api::Pay updated: None, charges: None, frm_metadata: None, + capture_before: pa.capture_before, + extended_authorization_applied: pa.extended_authorization_applied, order_tax_amount: None, connector_mandate_id:None, shipping_cost: None, diff --git a/crates/router/tests/payments.rs b/crates/router/tests/payments.rs index df4340a353e..ddc2046f5c9 100644 --- a/crates/router/tests/payments.rs +++ b/crates/router/tests/payments.rs @@ -444,6 +444,8 @@ async fn payments_create_core() { charges: None, frm_metadata: None, merchant_order_reference_id: None, + capture_before: None, + extended_authorization_applied: None, order_tax_amount: None, connector_mandate_id: None, shipping_cost: None, @@ -703,6 +705,8 @@ async fn payments_create_core_adyen_no_redirect() { charges: None, frm_metadata: None, merchant_order_reference_id: None, + capture_before: None, + extended_authorization_applied: None, order_tax_amount: None, connector_mandate_id: None, shipping_cost: None, diff --git a/crates/router/tests/payments2.rs b/crates/router/tests/payments2.rs index b5962d454fa..d1bcfc2927c 100644 --- a/crates/router/tests/payments2.rs +++ b/crates/router/tests/payments2.rs @@ -205,6 +205,8 @@ async fn payments_create_core() { charges: None, frm_metadata: None, merchant_order_reference_id: None, + capture_before: None, + extended_authorization_applied: None, order_tax_amount: None, connector_mandate_id: None, shipping_cost: None, @@ -473,6 +475,8 @@ async fn payments_create_core_adyen_no_redirect() { charges: None, frm_metadata: None, merchant_order_reference_id: None, + capture_before: None, + extended_authorization_applied: None, order_tax_amount: None, connector_mandate_id: None, shipping_cost: None, diff --git a/crates/storage_impl/src/mock_db/payment_attempt.rs b/crates/storage_impl/src/mock_db/payment_attempt.rs index efa34d41755..e9b4b03bd18 100644 --- a/crates/storage_impl/src/mock_db/payment_attempt.rs +++ b/crates/storage_impl/src/mock_db/payment_attempt.rs @@ -183,7 +183,7 @@ impl PaymentAttemptInterface for MockDb { profile_id: payment_attempt.profile_id, connector_mandate_detail: payment_attempt.connector_mandate_detail, request_extended_authentication: payment_attempt.request_extended_authorization, - extended_authentication_applied: payment_attempt.extended_authorization_applied, + extended_authorization_applied: payment_attempt.extended_authorization_applied, capture_before: payment_attempt.capture_before, }; payment_attempts.push(payment_attempt.clone()); diff --git a/crates/storage_impl/src/payments/payment_attempt.rs b/crates/storage_impl/src/payments/payment_attempt.rs index 6c967fa2fe3..73fb6c10b91 100644 --- a/crates/storage_impl/src/payments/payment_attempt.rs +++ b/crates/storage_impl/src/payments/payment_attempt.rs @@ -537,7 +537,7 @@ impl PaymentAttemptInterface for KVRouterStore { request_extended_authentication: payment_attempt .request_extended_authorization .clone(), - extended_authentication_applied: payment_attempt + extended_authorization_applied: payment_attempt .extended_authorization_applied .clone(), capture_before: payment_attempt.capture_before.clone(), @@ -1467,7 +1467,7 @@ impl DataModelExt for PaymentAttempt { order_tax_amount: self.net_amount.get_order_tax_amount(), connector_mandate_detail: self.connector_mandate_detail, request_extended_authorization: self.request_extended_authentication, - extended_authorization_applied: self.extended_authentication_applied, + extended_authorization_applied: self.extended_authorization_applied, capture_before: self.capture_before, } } @@ -1546,7 +1546,7 @@ impl DataModelExt for PaymentAttempt { profile_id: storage_model.profile_id, connector_mandate_detail: storage_model.connector_mandate_detail, request_extended_authentication: storage_model.request_extended_authorization, - extended_authentication_applied: storage_model.extended_authorization_applied, + extended_authorization_applied: storage_model.extended_authorization_applied, capture_before: storage_model.capture_before, } } From 67f342296778615bc25a3754321d8d3780f046b1 Mon Sep 17 00:00:00 2001 From: hrithikesh026 Date: Tue, 19 Nov 2024 15:55:49 +0530 Subject: [PATCH 04/10] add always_request_extended_authorization business profile response --- crates/api_models/src/admin.rs | 3 +++ crates/router/src/types/api/admin.rs | 1 + 2 files changed, 4 insertions(+) diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs index ef4cd625375..24fa03f8696 100644 --- a/crates/api_models/src/admin.rs +++ b/crates/api_models/src/admin.rs @@ -2231,6 +2231,9 @@ pub struct ProfileResponse { /// Maximum number of auto retries allowed for a payment pub max_auto_retries_enabled: Option, + + /// Bool indicating if extended authentication must be requested for all payments + pub always_request_extended_authorization: Option, } #[cfg(feature = "v2")] diff --git a/crates/router/src/types/api/admin.rs b/crates/router/src/types/api/admin.rs index 1c15fd12aeb..9b464c497cf 100644 --- a/crates/router/src/types/api/admin.rs +++ b/crates/router/src/types/api/admin.rs @@ -170,6 +170,7 @@ impl ForeignTryFrom for ProfileResponse { is_network_tokenization_enabled: item.is_network_tokenization_enabled, is_auto_retries_enabled: item.is_auto_retries_enabled, max_auto_retries_enabled: item.max_auto_retries_enabled, + always_request_extended_authorization: item.always_request_extended_authorization, }) } } From e3b73a4f856b52ced2a46a23d93c338330dea51c Mon Sep 17 00:00:00 2001 From: hrithikesh026 Date: Tue, 19 Nov 2024 16:20:38 +0530 Subject: [PATCH 05/10] generate openapi spec --- api-reference/openapi_spec.json | 56 +++++++++++++++++++++++++++++++ crates/api_models/src/admin.rs | 2 ++ crates/api_models/src/payments.rs | 2 +- 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index 733ba96237c..96724c3ec0f 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -16816,6 +16816,12 @@ ], "nullable": true }, + "request_extended_authorization": { + "type": "boolean", + "description": "Optional boolean value to extent authorization period of this payment\n\ncapture method must be manual or manual_multiple", + "default": false, + "nullable": true + }, "merchant_order_reference_id": { "type": "string", "description": "Merchant's identifier for the payment/invoice. This will be sent to the connector\nif the connector provides support to accept multiple reference ids.\nIn case the connector supports only one reference id, Hyperswitch's Payment ID will be sent as reference.", @@ -17186,6 +17192,12 @@ ], "nullable": true }, + "request_extended_authorization": { + "type": "boolean", + "description": "Optional boolean value to extent authorization period of this payment\n\ncapture method must be manual or manual_multiple", + "default": false, + "nullable": true + }, "merchant_order_reference_id": { "type": "string", "description": "Merchant's identifier for the payment/invoice. This will be sent to the connector\nif the connector provides support to accept multiple reference ids.\nIn case the connector supports only one reference id, Hyperswitch's Payment ID will be sent as reference.", @@ -17717,6 +17729,17 @@ "description": "You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. FRM Metadata is useful for storing additional, structured information on an object related to FRM.", "nullable": true }, + "extended_authorization_applied": { + "type": "boolean", + "description": "flag that indicates if extended authorization is applied on this payment or not", + "nullable": true + }, + "capture_before": { + "type": "string", + "format": "date-time", + "description": "date and time after which this payment cannot be captured", + "nullable": true + }, "merchant_order_reference_id": { "type": "string", "description": "Merchant's identifier for the payment/invoice. This will be sent to the connector\nif the connector provides support to accept multiple reference ids.\nIn case the connector supports only one reference id, Hyperswitch's Payment ID will be sent as reference.", @@ -18380,6 +18403,12 @@ ], "nullable": true }, + "request_extended_authorization": { + "type": "boolean", + "description": "Optional boolean value to extent authorization period of this payment\n\ncapture method must be manual or manual_multiple", + "default": false, + "nullable": true + }, "merchant_order_reference_id": { "type": "string", "description": "Merchant's identifier for the payment/invoice. This will be sent to the connector\nif the connector provides support to accept multiple reference ids.\nIn case the connector supports only one reference id, Hyperswitch's Payment ID will be sent as reference.", @@ -18937,6 +18966,17 @@ "description": "You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. FRM Metadata is useful for storing additional, structured information on an object related to FRM.", "nullable": true }, + "extended_authorization_applied": { + "type": "boolean", + "description": "flag that indicates if extended authorization is applied on this payment or not", + "nullable": true + }, + "capture_before": { + "type": "string", + "format": "date-time", + "description": "date and time after which this payment cannot be captured", + "nullable": true + }, "merchant_order_reference_id": { "type": "string", "description": "Merchant's identifier for the payment/invoice. This will be sent to the connector\nif the connector provides support to accept multiple reference ids.\nIn case the connector supports only one reference id, Hyperswitch's Payment ID will be sent as reference.", @@ -19413,6 +19453,12 @@ ], "nullable": true }, + "request_extended_authorization": { + "type": "boolean", + "description": "Optional boolean value to extent authorization period of this payment\n\ncapture method must be manual or manual_multiple", + "default": false, + "nullable": true + }, "merchant_order_reference_id": { "type": "string", "description": "Merchant's identifier for the payment/invoice. This will be sent to the connector\nif the connector provides support to accept multiple reference ids.\nIn case the connector supports only one reference id, Hyperswitch's Payment ID will be sent as reference.", @@ -21381,6 +21427,11 @@ "description": "Maximum number of auto retries allowed for a payment", "nullable": true, "minimum": 0 + }, + "always_request_extended_authorization": { + "type": "boolean", + "description": "Bool indicating if extended authentication must be requested for all payments", + "nullable": true } }, "additionalProperties": false @@ -21610,6 +21661,11 @@ "format": "int32", "description": "Maximum number of auto retries allowed for a payment", "nullable": true + }, + "always_request_extended_authorization": { + "type": "boolean", + "description": "Bool indicating if extended authentication must be requested for all payments", + "nullable": true } } }, diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs index 24fa03f8696..1f8a14e2323 100644 --- a/crates/api_models/src/admin.rs +++ b/crates/api_models/src/admin.rs @@ -1994,6 +1994,7 @@ pub struct ProfileCreate { pub max_auto_retries_enabled: Option, /// Bool indicating if extended authentication must be requested for all payments + #[schema(value_type = Option)] pub always_request_extended_authorization: Option, } @@ -2233,6 +2234,7 @@ pub struct ProfileResponse { pub max_auto_retries_enabled: Option, /// Bool indicating if extended authentication must be requested for all payments + #[schema(value_type = Option)] pub always_request_extended_authorization: Option, } diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index f9ce7ab3642..afa419883d9 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -853,7 +853,7 @@ pub struct PaymentsRequest { /// Optional boolean value to extent authorization period of this payment /// /// capture method must be manual or manual_multiple - #[schema(value_type = Option, default = false)] + #[schema(value_type = Option, default = false)] pub request_extended_authorization: Option, /// Merchant's identifier for the payment/invoice. This will be sent to the connector From e693333e5343cb24390fcac80f5008dfb7553603 Mon Sep 17 00:00:00 2001 From: hrithikesh026 Date: Wed, 20 Nov 2024 14:58:24 +0530 Subject: [PATCH 06/10] address clippy lints for v2 --- crates/diesel_models/src/payment_attempt.rs | 1 - crates/storage_impl/src/payments/payment_attempt.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/diesel_models/src/payment_attempt.rs b/crates/diesel_models/src/payment_attempt.rs index 813e28d83f7..2f3d76e5cc9 100644 --- a/crates/diesel_models/src/payment_attempt.rs +++ b/crates/diesel_models/src/payment_attempt.rs @@ -177,7 +177,6 @@ pub struct PaymentAttempt { pub connector_mandate_detail: Option, pub request_extended_authorization: Option, pub extended_authorization_applied: Option, - #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub capture_before: Option, } diff --git a/crates/storage_impl/src/payments/payment_attempt.rs b/crates/storage_impl/src/payments/payment_attempt.rs index 73fb6c10b91..2a4127d1e57 100644 --- a/crates/storage_impl/src/payments/payment_attempt.rs +++ b/crates/storage_impl/src/payments/payment_attempt.rs @@ -540,7 +540,7 @@ impl PaymentAttemptInterface for KVRouterStore { extended_authorization_applied: payment_attempt .extended_authorization_applied .clone(), - capture_before: payment_attempt.capture_before.clone(), + capture_before: payment_attempt.capture_before, }; let field = format!("pa_{}", created_attempt.attempt_id); From 1df76e220f419ddb9003fcca9306cd40b092d958 Mon Sep 17 00:00:00 2001 From: hrithikesh026 Date: Wed, 27 Nov 2024 13:15:34 +0530 Subject: [PATCH 07/10] resolve merge conflicts --- crates/router/src/utils/user/sample_data.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/crates/router/src/utils/user/sample_data.rs b/crates/router/src/utils/user/sample_data.rs index 3896a6d5d0f..f5d43c72be7 100644 --- a/crates/router/src/utils/user/sample_data.rs +++ b/crates/router/src/utils/user/sample_data.rs @@ -274,11 +274,8 @@ pub async fn generate_sample_data( shipping_cost: None, tax_details: None, skip_external_tax_calculation: None, -<<<<<<< HEAD request_extended_authorization: None, -======= psd2_sca_exemption_type: None, ->>>>>>> origin/main }; let (connector_transaction_id, connector_transaction_data) = ConnectorTransactionId::form_id_and_data(attempt_id.clone()); From e7ca2e0b1fddd0963e21bb4d84f70871cd96674f Mon Sep 17 00:00:00 2001 From: hrithikesh026 Date: Wed, 27 Nov 2024 16:03:03 +0530 Subject: [PATCH 08/10] run v2 migration --- crates/diesel_models/src/schema_v2.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/diesel_models/src/schema_v2.rs b/crates/diesel_models/src/schema_v2.rs index f6bab9071cd..6746e86d64c 100644 --- a/crates/diesel_models/src/schema_v2.rs +++ b/crates/diesel_models/src/schema_v2.rs @@ -221,6 +221,7 @@ diesel::table! { is_network_tokenization_enabled -> Bool, is_auto_retries_enabled -> Nullable, max_auto_retries_enabled -> Nullable, + always_request_extended_authorization -> Nullable, } } @@ -822,6 +823,9 @@ diesel::table! { shipping_cost -> Nullable, order_tax_amount -> Nullable, connector_mandate_detail -> Nullable, + request_extended_authorization -> Nullable, + extended_authorization_applied -> Nullable, + capture_before -> Nullable, } } @@ -895,6 +899,7 @@ diesel::table! { payment_link_config -> Nullable, #[max_length = 64] id -> Varchar, + request_extended_authorization -> Nullable, psd2_sca_exemption_type -> Nullable, } } From 916b84ebfdfcfe67808a621fc09a668d3f0ff1d1 Mon Sep 17 00:00:00 2001 From: hrithikesh026 Date: Thu, 28 Nov 2024 16:58:00 +0530 Subject: [PATCH 09/10] add 128-column-tables feature for diesel crate in common_enums --- crates/common_enums/Cargo.toml | 2 +- crates/diesel_models/Cargo.toml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/common_enums/Cargo.toml b/crates/common_enums/Cargo.toml index 92fc2f02066..5db5393644a 100644 --- a/crates/common_enums/Cargo.toml +++ b/crates/common_enums/Cargo.toml @@ -13,7 +13,7 @@ openapi = [] payouts = [] [dependencies] -diesel = { version = "2.2.3", features = ["postgres"] } +diesel = { version = "2.2.3", features = ["postgres", "128-column-tables"] } serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" strum = { version = "0.26", features = ["derive"] } diff --git a/crates/diesel_models/Cargo.toml b/crates/diesel_models/Cargo.toml index c7e2622cb18..9e195bc3c00 100644 --- a/crates/diesel_models/Cargo.toml +++ b/crates/diesel_models/Cargo.toml @@ -17,7 +17,8 @@ payment_methods_v2 = [] [dependencies] async-bb8-diesel = { git = "https://github.com/jarnura/async-bb8-diesel", rev = "53b4ab901aab7635c8215fd1c2d542c8db443094" } -diesel = { version = "2.2.3", features = ["postgres", "serde_json", "time", "128-column-tables",] } +diesel = { version = "2.2.3", features = ["postgres", "serde_json", "time", "128-column-tables"] } + error-stack = "0.4.1" rustc-hash = "1.1.0" serde = { version = "1.0.197", features = ["derive"] } From 9e38ed86c4702b7028a1f4a96bba6f40b1f6b512 Mon Sep 17 00:00:00 2001 From: hrithikesh026 Date: Thu, 28 Nov 2024 17:15:14 +0530 Subject: [PATCH 10/10] chore: address spelling mistakes --- crates/common_utils/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/common_utils/src/types.rs b/crates/common_utils/src/types.rs index 4399fbb8e18..944b326d8d6 100644 --- a/crates/common_utils/src/types.rs +++ b/crates/common_utils/src/types.rs @@ -6,7 +6,7 @@ pub mod authentication; /// Enum for Theme Lineage pub mod theme; -/// types that are wrappers aroung primitive types +/// types that are wrappers around primitive types pub mod primitive_wrappers; use std::{