diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index 562b4fdf26..c30c9ec9f1 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -181,6 +181,31 @@ impl AttemptStatus { } } +/// Indicates the method by which a card is discovered during a payment +#[derive( + Clone, + Copy, + Debug, + Default, + Hash, + Eq, + PartialEq, + serde::Deserialize, + serde::Serialize, + strum::Display, + strum::EnumString, + ToSchema, +)] +#[router_derive::diesel_enum(storage_type = "db_enum")] +#[serde(rename_all = "snake_case")] +#[strum(serialize_all = "snake_case")] +pub enum CardDiscovery { + #[default] + Manual, + SavedCard, + ClickToPay, +} + /// 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, diff --git a/crates/diesel_models/src/enums.rs b/crates/diesel_models/src/enums.rs index ec6e91a2ec..1ee1a090ff 100644 --- a/crates/diesel_models/src/enums.rs +++ b/crates/diesel_models/src/enums.rs @@ -4,8 +4,8 @@ pub mod diesel_exports { DbApiVersion as ApiVersion, DbAttemptStatus as AttemptStatus, DbAuthenticationType as AuthenticationType, DbBlocklistDataKind as BlocklistDataKind, DbCaptureMethod as CaptureMethod, DbCaptureStatus as CaptureStatus, - DbConnectorStatus as ConnectorStatus, DbConnectorType as ConnectorType, - DbCountryAlpha2 as CountryAlpha2, DbCurrency as Currency, + DbCardDiscovery as CardDiscovery, DbConnectorStatus as ConnectorStatus, + DbConnectorType as ConnectorType, DbCountryAlpha2 as CountryAlpha2, DbCurrency as Currency, DbDashboardMetadata as DashboardMetadata, DbDeleteStatus as DeleteStatus, DbDisputeStage as DisputeStage, DbDisputeStatus as DisputeStatus, DbEventClass as EventClass, DbEventObjectType as EventObjectType, DbEventType as EventType, diff --git a/crates/diesel_models/src/payment_attempt.rs b/crates/diesel_models/src/payment_attempt.rs index a450a30fa7..dbd867c9e5 100644 --- a/crates/diesel_models/src/payment_attempt.rs +++ b/crates/diesel_models/src/payment_attempt.rs @@ -94,6 +94,7 @@ pub struct PaymentAttempt { pub shipping_cost: Option, pub order_tax_amount: Option, pub connector_mandate_detail: Option, + pub card_discovery: Option, } #[cfg(feature = "v1")] @@ -172,6 +173,7 @@ pub struct PaymentAttempt { pub order_tax_amount: Option, pub connector_transaction_data: Option, pub connector_mandate_detail: Option, + pub card_discovery: Option, } #[cfg(feature = "v1")] @@ -278,6 +280,7 @@ pub struct PaymentAttemptNew { pub payment_method_subtype: storage_enums::PaymentMethodType, pub id: id_type::GlobalAttemptId, pub connector_mandate_detail: Option, + pub card_discovery: Option, } #[cfg(feature = "v1")] @@ -351,6 +354,7 @@ pub struct PaymentAttemptNew { pub shipping_cost: Option, pub order_tax_amount: Option, pub connector_mandate_detail: Option, + pub card_discovery: Option, } #[cfg(feature = "v1")] @@ -423,6 +427,7 @@ pub enum PaymentAttemptUpdate { shipping_cost: Option, order_tax_amount: Option, connector_mandate_detail: Option, + card_discovery: Option, }, VoidUpdate { status: storage_enums::AttemptStatus, @@ -848,6 +853,7 @@ pub struct PaymentAttemptUpdateInternal { pub order_tax_amount: Option, pub connector_transaction_data: Option, pub connector_mandate_detail: Option, + pub card_discovery: Option, } #[cfg(feature = "v1")] @@ -1031,6 +1037,7 @@ impl PaymentAttemptUpdate { order_tax_amount, connector_transaction_data, connector_mandate_detail, + card_discovery, } = PaymentAttemptUpdateInternal::from(self).populate_derived_fields(&source); PaymentAttempt { amount: amount.unwrap_or(source.amount), @@ -1089,6 +1096,7 @@ impl PaymentAttemptUpdate { connector_transaction_data: connector_transaction_data .or(source.connector_transaction_data), connector_mandate_detail: connector_mandate_detail.or(source.connector_mandate_detail), + card_discovery: card_discovery.or(source.card_discovery), ..source } } @@ -2141,6 +2149,7 @@ impl From for PaymentAttemptUpdateInternal { order_tax_amount: None, connector_transaction_data: None, connector_mandate_detail: None, + card_discovery: None, }, PaymentAttemptUpdate::AuthenticationTypeUpdate { authentication_type, @@ -2197,6 +2206,7 @@ impl From for PaymentAttemptUpdateInternal { order_tax_amount: None, connector_transaction_data: None, connector_mandate_detail: None, + card_discovery: None, }, PaymentAttemptUpdate::ConfirmUpdate { amount, @@ -2232,6 +2242,7 @@ impl From for PaymentAttemptUpdateInternal { shipping_cost, order_tax_amount, connector_mandate_detail, + card_discovery, } => Self { amount: Some(amount), currency: Some(currency), @@ -2284,6 +2295,7 @@ impl From for PaymentAttemptUpdateInternal { order_tax_amount, connector_transaction_data: None, connector_mandate_detail, + card_discovery, }, PaymentAttemptUpdate::VoidUpdate { status, @@ -2341,6 +2353,7 @@ impl From for PaymentAttemptUpdateInternal { order_tax_amount: None, connector_transaction_data: None, connector_mandate_detail: None, + card_discovery: None, }, PaymentAttemptUpdate::RejectUpdate { status, @@ -2399,6 +2412,7 @@ impl From for PaymentAttemptUpdateInternal { order_tax_amount: None, connector_transaction_data: None, connector_mandate_detail: None, + card_discovery: None, }, PaymentAttemptUpdate::BlocklistUpdate { status, @@ -2457,6 +2471,7 @@ impl From for PaymentAttemptUpdateInternal { order_tax_amount: None, connector_transaction_data: None, connector_mandate_detail: None, + card_discovery: None, }, PaymentAttemptUpdate::ConnectorMandateDetailUpdate { connector_mandate_detail, @@ -2513,6 +2528,7 @@ impl From for PaymentAttemptUpdateInternal { order_tax_amount: None, connector_transaction_data: None, connector_mandate_detail, + card_discovery: None, }, PaymentAttemptUpdate::PaymentMethodDetailsUpdate { payment_method_id, @@ -2569,6 +2585,7 @@ impl From for PaymentAttemptUpdateInternal { order_tax_amount: None, connector_transaction_data: None, connector_mandate_detail: None, + card_discovery: None, }, PaymentAttemptUpdate::ResponseUpdate { status, @@ -2650,6 +2667,7 @@ impl From for PaymentAttemptUpdateInternal { shipping_cost: None, order_tax_amount: None, connector_mandate_detail, + card_discovery: None, } } PaymentAttemptUpdate::ErrorUpdate { @@ -2723,6 +2741,7 @@ impl From for PaymentAttemptUpdateInternal { shipping_cost: None, order_tax_amount: None, connector_mandate_detail: None, + card_discovery: None, } } PaymentAttemptUpdate::StatusUpdate { status, updated_by } => Self { @@ -2777,6 +2796,7 @@ impl From for PaymentAttemptUpdateInternal { order_tax_amount: None, connector_transaction_data: None, connector_mandate_detail: None, + card_discovery: None, }, PaymentAttemptUpdate::UpdateTrackers { payment_token, @@ -2839,6 +2859,7 @@ impl From for PaymentAttemptUpdateInternal { order_tax_amount: None, connector_transaction_data: None, connector_mandate_detail: None, + card_discovery: None, }, PaymentAttemptUpdate::UnresolvedResponseUpdate { status, @@ -2908,6 +2929,7 @@ impl From for PaymentAttemptUpdateInternal { shipping_cost: None, order_tax_amount: None, connector_mandate_detail: None, + card_discovery: None, } } PaymentAttemptUpdate::PreprocessingUpdate { @@ -2976,6 +2998,7 @@ impl From for PaymentAttemptUpdateInternal { shipping_cost: None, order_tax_amount: None, connector_mandate_detail: None, + card_discovery: None, } } PaymentAttemptUpdate::CaptureUpdate { @@ -3034,6 +3057,7 @@ impl From for PaymentAttemptUpdateInternal { order_tax_amount: None, connector_transaction_data: None, connector_mandate_detail: None, + card_discovery: None, }, PaymentAttemptUpdate::AmountToCaptureUpdate { status, @@ -3091,6 +3115,7 @@ impl From for PaymentAttemptUpdateInternal { order_tax_amount: None, connector_transaction_data: None, connector_mandate_detail: None, + card_discovery: None, }, PaymentAttemptUpdate::ConnectorResponse { authentication_data, @@ -3157,6 +3182,7 @@ impl From for PaymentAttemptUpdateInternal { shipping_cost: None, order_tax_amount: None, connector_mandate_detail: None, + card_discovery: None, } } PaymentAttemptUpdate::IncrementalAuthorizationAmountUpdate { @@ -3214,6 +3240,7 @@ impl From for PaymentAttemptUpdateInternal { order_tax_amount: None, connector_transaction_data: None, connector_mandate_detail: None, + card_discovery: None, }, PaymentAttemptUpdate::AuthenticationUpdate { status, @@ -3273,6 +3300,7 @@ impl From for PaymentAttemptUpdateInternal { order_tax_amount: None, connector_transaction_data: None, connector_mandate_detail: None, + card_discovery: None, }, PaymentAttemptUpdate::ManualUpdate { status, @@ -3341,6 +3369,7 @@ impl From for PaymentAttemptUpdateInternal { shipping_cost: None, order_tax_amount: None, connector_mandate_detail: None, + card_discovery: None, } } PaymentAttemptUpdate::PostSessionTokensUpdate { @@ -3398,6 +3427,7 @@ impl From for PaymentAttemptUpdateInternal { order_tax_amount: None, connector_transaction_data: None, connector_mandate_detail: None, + card_discovery: None, }, } } diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs index 7930ad5d9a..40343e4436 100644 --- a/crates/diesel_models/src/schema.rs +++ b/crates/diesel_models/src/schema.rs @@ -907,6 +907,7 @@ diesel::table! { #[max_length = 512] connector_transaction_data -> Nullable, connector_mandate_detail -> Nullable, + card_discovery -> Nullable, } } diff --git a/crates/diesel_models/src/schema_v2.rs b/crates/diesel_models/src/schema_v2.rs index 13abf8ee64..99d6139f31 100644 --- a/crates/diesel_models/src/schema_v2.rs +++ b/crates/diesel_models/src/schema_v2.rs @@ -877,6 +877,7 @@ diesel::table! { shipping_cost -> Nullable, order_tax_amount -> Nullable, connector_mandate_detail -> Nullable, + card_discovery -> Nullable, } } diff --git a/crates/diesel_models/src/user/sample_data.rs b/crates/diesel_models/src/user/sample_data.rs index cfc9e1c4c8..4262276c46 100644 --- a/crates/diesel_models/src/user/sample_data.rs +++ b/crates/diesel_models/src/user/sample_data.rs @@ -203,6 +203,7 @@ pub struct PaymentAttemptBatchNew { pub order_tax_amount: Option, pub connector_transaction_data: Option, pub connector_mandate_detail: Option, + pub card_discovery: Option, } #[cfg(feature = "v1")] @@ -282,6 +283,7 @@ impl PaymentAttemptBatchNew { shipping_cost: self.shipping_cost, order_tax_amount: self.order_tax_amount, connector_mandate_detail: self.connector_mandate_detail, + card_discovery: self.card_discovery, } } } diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index 0a7ada39ec..74804e658a 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -402,6 +402,8 @@ pub struct PaymentAttempt { pub id: id_type::GlobalAttemptId, /// The connector mandate details which are stored temporarily pub connector_mandate_detail: Option, + /// Indicates the method by which a card is discovered during a payment + pub card_discovery: Option, } impl PaymentAttempt { @@ -520,6 +522,7 @@ impl PaymentAttempt { error: None, connector_mandate_detail: None, id, + card_discovery: None, }) } } @@ -590,6 +593,7 @@ pub struct PaymentAttempt { pub profile_id: id_type::ProfileId, pub organization_id: id_type::OrganizationId, pub connector_mandate_detail: Option, + pub card_discovery: Option, } #[cfg(feature = "v1")] @@ -836,6 +840,7 @@ pub struct PaymentAttemptNew { pub profile_id: id_type::ProfileId, pub organization_id: id_type::OrganizationId, pub connector_mandate_detail: Option, + pub card_discovery: Option, } #[cfg(feature = "v1")] @@ -902,6 +907,7 @@ pub enum PaymentAttemptUpdate { client_version: Option, customer_acceptance: Option, connector_mandate_detail: Option, + card_discovery: Option, }, RejectUpdate { status: storage_enums::AttemptStatus, @@ -1154,6 +1160,7 @@ impl PaymentAttemptUpdate { client_version, customer_acceptance, connector_mandate_detail, + card_discovery, } => DieselPaymentAttemptUpdate::ConfirmUpdate { amount: net_amount.get_order_amount(), currency, @@ -1188,6 +1195,7 @@ impl PaymentAttemptUpdate { shipping_cost: net_amount.get_shipping_cost(), order_tax_amount: net_amount.get_order_tax_amount(), connector_mandate_detail, + card_discovery, }, Self::VoidUpdate { status, @@ -1551,6 +1559,7 @@ 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, + card_discovery: self.card_discovery, }) } @@ -1632,6 +1641,7 @@ 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, + card_discovery: storage_model.card_discovery, }) } .await @@ -1714,6 +1724,7 @@ 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, + card_discovery: self.card_discovery, }) } } @@ -1781,6 +1792,7 @@ impl behaviour::Conversion for PaymentAttempt { payment_method_billing_address, connector, connector_mandate_detail, + card_discovery, } = self; let AttemptAmountDetails { @@ -1858,6 +1870,7 @@ impl behaviour::Conversion for PaymentAttempt { payment_method_billing_address: payment_method_billing_address.map(Encryption::from), connector_payment_data, connector_mandate_detail, + card_discovery, }) } @@ -1969,6 +1982,7 @@ impl behaviour::Conversion for PaymentAttempt { connector: storage_model.connector, payment_method_billing_address, connector_mandate_detail: storage_model.connector_mandate_detail, + card_discovery: storage_model.card_discovery, }) } .await @@ -2053,6 +2067,7 @@ impl behaviour::Conversion for PaymentAttempt { payment_method_type_v2: self.payment_method_type, id: self.id, connector_mandate_detail: self.connector_mandate_detail, + card_discovery: self.card_discovery, }) } } diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index e991593b4b..e9d3c01378 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -4450,6 +4450,28 @@ pub struct PaymentEvent { } impl PaymentData { + // Get the method by which a card is discovered during a payment + #[cfg(feature = "v1")] + fn get_card_discovery_for_card_payment_method(&self) -> Option { + match self.payment_attempt.payment_method { + Some(storage_enums::PaymentMethod::Card) => { + if self + .token_data + .as_ref() + .map(storage::PaymentTokenData::is_permanent_card) + .unwrap_or(false) + { + Some(common_enums::CardDiscovery::SavedCard) + } else if self.service_details.is_some() { + Some(common_enums::CardDiscovery::ClickToPay) + } else { + Some(common_enums::CardDiscovery::Manual) + } + } + _ => None, + } + } + fn to_event(&self) -> PaymentEvent { PaymentEvent { payment_intent: self.payment_intent.clone(), diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index 3833d316be..0d7a3b57fc 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -4289,6 +4289,7 @@ impl AttemptType { organization_id: old_payment_attempt.organization_id, profile_id: old_payment_attempt.profile_id, connector_mandate_detail: None, + card_discovery: None, } } diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index edcd798ba9..9b1c2ea3be 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -1585,7 +1585,7 @@ impl UpdateTracker, api::PaymentsRequest> for let m_payment_token = payment_token.clone(); let m_additional_pm_data = encoded_additional_pm_data .clone() - .or(payment_data.payment_attempt.payment_method_data); + .or(payment_data.payment_attempt.payment_method_data.clone()); let m_business_sub_label = business_sub_label.clone(); let m_straight_through_algorithm = straight_through_algorithm.clone(); let m_error_code = error_code.clone(); @@ -1614,6 +1614,8 @@ impl UpdateTracker, api::PaymentsRequest> for None => (None, None, None), }; + let card_discovery = payment_data.get_card_discovery_for_card_payment_method(); + let payment_attempt_fut = tokio::spawn( async move { m_db.update_payment_attempt_with_attempt_id( @@ -1661,6 +1663,7 @@ impl UpdateTracker, api::PaymentsRequest> for connector_mandate_detail: payment_data .payment_attempt .connector_mandate_detail, + card_discovery, }, storage_scheme, ) diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index ed5c93489c..6ace8c3018 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -1306,6 +1306,7 @@ impl PaymentCreate { organization_id: organization_id.clone(), profile_id, connector_mandate_detail: None, + card_discovery: None, }, additional_pm_data, diff --git a/crates/router/src/core/payments/retry.rs b/crates/router/src/core/payments/retry.rs index 7ae536a1f1..0401575bc6 100644 --- a/crates/router/src/core/payments/retry.rs +++ b/crates/router/src/core/payments/retry.rs @@ -654,6 +654,7 @@ pub fn make_new_payment_attempt( charge_id: Default::default(), customer_acceptance: Default::default(), connector_mandate_detail: Default::default(), + card_discovery: old_payment_attempt.card_discovery, } } diff --git a/crates/router/src/types/storage/payment_attempt.rs b/crates/router/src/types/storage/payment_attempt.rs index 0291374d54..5958435abc 100644 --- a/crates/router/src/types/storage/payment_attempt.rs +++ b/crates/router/src/types/storage/payment_attempt.rs @@ -217,6 +217,7 @@ mod tests { profile_id: common_utils::generate_profile_id_of_default_length(), organization_id: Default::default(), connector_mandate_detail: Default::default(), + card_discovery: Default::default(), }; let store = state @@ -301,6 +302,7 @@ mod tests { profile_id: common_utils::generate_profile_id_of_default_length(), organization_id: Default::default(), connector_mandate_detail: Default::default(), + card_discovery: Default::default(), }; let store = state .stores @@ -398,6 +400,7 @@ mod tests { profile_id: common_utils::generate_profile_id_of_default_length(), organization_id: Default::default(), connector_mandate_detail: Default::default(), + card_discovery: Default::default(), }; let store = state .stores diff --git a/crates/router/src/types/storage/payment_method.rs b/crates/router/src/types/storage/payment_method.rs index bc5f6651b6..21c15c23b3 100644 --- a/crates/router/src/types/storage/payment_method.rs +++ b/crates/router/src/types/storage/payment_method.rs @@ -103,6 +103,10 @@ impl PaymentTokenData { pub fn wallet_token(payment_method_id: String) -> Self { Self::WalletToken(WalletTokenData { payment_method_id }) } + + pub fn is_permanent_card(&self) -> bool { + matches!(self, Self::PermanentCard(_) | Self::Permanent(_)) + } } #[cfg(all( diff --git a/crates/router/src/utils/user/sample_data.rs b/crates/router/src/utils/user/sample_data.rs index bf84dd568a..c5652e6cbf 100644 --- a/crates/router/src/utils/user/sample_data.rs +++ b/crates/router/src/utils/user/sample_data.rs @@ -361,6 +361,7 @@ pub async fn generate_sample_data( order_tax_amount: None, connector_transaction_data, connector_mandate_detail: None, + card_discovery: 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 0415625f7e..3a45cfad9a 100644 --- a/crates/storage_impl/src/mock_db/payment_attempt.rs +++ b/crates/storage_impl/src/mock_db/payment_attempt.rs @@ -195,6 +195,7 @@ impl PaymentAttemptInterface for MockDb { organization_id: payment_attempt.organization_id, profile_id: payment_attempt.profile_id, connector_mandate_detail: payment_attempt.connector_mandate_detail, + card_discovery: payment_attempt.card_discovery, }; 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 06c7fefe85..3480f8f4ba 100644 --- a/crates/storage_impl/src/payments/payment_attempt.rs +++ b/crates/storage_impl/src/payments/payment_attempt.rs @@ -564,6 +564,7 @@ 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(), + card_discovery: payment_attempt.card_discovery, }; let field = format!("pa_{}", created_attempt.attempt_id); @@ -1511,6 +1512,7 @@ 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, + card_discovery: self.card_discovery, } } @@ -1587,6 +1589,7 @@ impl DataModelExt for PaymentAttempt { organization_id: storage_model.organization_id, profile_id: storage_model.profile_id, connector_mandate_detail: storage_model.connector_mandate_detail, + card_discovery: storage_model.card_discovery, } } } @@ -1670,6 +1673,7 @@ 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, + card_discovery: self.card_discovery, } } @@ -1742,6 +1746,7 @@ impl DataModelExt for PaymentAttemptNew { organization_id: storage_model.organization_id, profile_id: storage_model.profile_id, connector_mandate_detail: storage_model.connector_mandate_detail, + card_discovery: storage_model.card_discovery, } } } diff --git a/migrations/2025-01-13-060852_add_card_discovery_in_payment_attempt/down.sql b/migrations/2025-01-13-060852_add_card_discovery_in_payment_attempt/down.sql new file mode 100644 index 0000000000..9b7be0e960 --- /dev/null +++ b/migrations/2025-01-13-060852_add_card_discovery_in_payment_attempt/down.sql @@ -0,0 +1,4 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE payment_attempt DROP COLUMN IF EXISTS card_discovery; + +DROP TYPE IF EXISTS "CardDiscovery"; diff --git a/migrations/2025-01-13-060852_add_card_discovery_in_payment_attempt/up.sql b/migrations/2025-01-13-060852_add_card_discovery_in_payment_attempt/up.sql new file mode 100644 index 0000000000..657d670bfc --- /dev/null +++ b/migrations/2025-01-13-060852_add_card_discovery_in_payment_attempt/up.sql @@ -0,0 +1,4 @@ +-- Your SQL goes here +CREATE TYPE "CardDiscovery" AS ENUM ('manual', 'saved_card', 'click_to_pay'); + +ALTER TABLE payment_attempt ADD COLUMN IF NOT EXISTS card_discovery "CardDiscovery";