diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json index 6b9ba4afd0..783d4751bc 100644 --- a/api-reference-v2/openapi_spec.json +++ b/api-reference-v2/openapi_spec.json @@ -11073,7 +11073,8 @@ "payment_methods", "mandate_payment", "show_surcharge_breakup_screen", - "request_external_three_ds_authentication" + "request_external_three_ds_authentication", + "is_tax_calculation_enabled" ], "properties": { "redirect_url": { @@ -11135,6 +11136,10 @@ "type": "boolean", "description": "flag that indicates whether to collect billing details from wallets or from the customer", "nullable": true + }, + "is_tax_calculation_enabled": { + "type": "boolean", + "description": "flag that indicates whether to calculate tax on the order amount" } } }, @@ -11923,6 +11928,11 @@ "example": "Custom_Order_id_123", "nullable": true, "maxLength": 255 + }, + "skip_external_tax_calculation": { + "type": "boolean", + "description": "Whether to calculate tax for this payment intent", + "nullable": true } } }, @@ -12288,6 +12298,11 @@ "example": "Custom_Order_id_123", "nullable": true, "maxLength": 255 + }, + "skip_external_tax_calculation": { + "type": "boolean", + "description": "Whether to calculate tax for this payment intent", + "nullable": true } } }, @@ -13347,6 +13362,11 @@ "example": "Custom_Order_id_123", "nullable": true, "maxLength": 255 + }, + "skip_external_tax_calculation": { + "type": "boolean", + "description": "Whether to calculate tax for this payment intent", + "nullable": true } }, "additionalProperties": false @@ -14355,6 +14375,11 @@ "example": "Custom_Order_id_123", "nullable": true, "maxLength": 255 + }, + "skip_external_tax_calculation": { + "type": "boolean", + "description": "Whether to calculate tax for this payment intent", + "nullable": true } } }, diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index 2a758cc06d..43845f83f2 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -15071,7 +15071,8 @@ "payment_methods", "mandate_payment", "show_surcharge_breakup_screen", - "request_external_three_ds_authentication" + "request_external_three_ds_authentication", + "is_tax_calculation_enabled" ], "properties": { "redirect_url": { @@ -15133,6 +15134,10 @@ "type": "boolean", "description": "flag that indicates whether to collect billing details from wallets or from the customer", "nullable": true + }, + "is_tax_calculation_enabled": { + "type": "boolean", + "description": "flag that indicates whether to calculate tax on the order amount" } } }, @@ -15921,6 +15926,11 @@ "example": "Custom_Order_id_123", "nullable": true, "maxLength": 255 + }, + "skip_external_tax_calculation": { + "type": "boolean", + "description": "Whether to calculate tax for this payment intent", + "nullable": true } } }, @@ -16286,6 +16296,11 @@ "example": "Custom_Order_id_123", "nullable": true, "maxLength": 255 + }, + "skip_external_tax_calculation": { + "type": "boolean", + "description": "Whether to calculate tax for this payment intent", + "nullable": true } } }, @@ -17365,6 +17380,11 @@ "example": "Custom_Order_id_123", "nullable": true, "maxLength": 255 + }, + "skip_external_tax_calculation": { + "type": "boolean", + "description": "Whether to calculate tax for this payment intent", + "nullable": true } }, "additionalProperties": false @@ -18373,6 +18393,11 @@ "example": "Custom_Order_id_123", "nullable": true, "maxLength": 255 + }, + "skip_external_tax_calculation": { + "type": "boolean", + "description": "Whether to calculate tax for this payment intent", + "nullable": true } } }, diff --git a/crates/api_models/src/payment_methods.rs b/crates/api_models/src/payment_methods.rs index 2204a7fc58..c6cf638015 100644 --- a/crates/api_models/src/payment_methods.rs +++ b/crates/api_models/src/payment_methods.rs @@ -1482,6 +1482,9 @@ pub struct PaymentMethodListResponse { /// flag that indicates whether to collect billing details from wallets or from the customer pub collect_billing_details_from_wallets: Option, + + /// flag that indicates whether to calculate tax on the order amount + pub is_tax_calculation_enabled: bool, } #[derive(Eq, PartialEq, Hash, Debug, serde::Deserialize, ToSchema)] diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index d512d487e5..cd32c045f1 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -560,6 +560,9 @@ pub struct PaymentsRequest { example = "Custom_Order_id_123" )] pub merchant_order_reference_id: Option, + + /// Whether to calculate tax for this payment intent + pub skip_external_tax_calculation: Option, } /// Checks if the inner values of two options are equal diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index c80e9e5f4d..b2f314a0fe 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -72,6 +72,7 @@ pub struct PaymentIntent { pub shipping_cost: Option, pub organization_id: common_utils::id_type::OrganizationId, pub tax_details: Option, + pub skip_external_tax_calculation: Option, } #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))] @@ -136,6 +137,7 @@ pub struct PaymentIntent { pub shipping_cost: Option, pub organization_id: common_utils::id_type::OrganizationId, pub tax_details: Option, + pub skip_external_tax_calculation: Option, } #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, diesel::AsExpression)] @@ -219,6 +221,7 @@ pub struct PaymentIntentNew { pub shipping_cost: Option, pub organization_id: common_utils::id_type::OrganizationId, pub tax_details: Option, + pub skip_external_tax_calculation: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs index 213687431d..8e6c72eb5b 100644 --- a/crates/diesel_models/src/schema.rs +++ b/crates/diesel_models/src/schema.rs @@ -919,6 +919,7 @@ diesel::table! { #[max_length = 32] organization_id -> Varchar, tax_details -> Nullable, + skip_external_tax_calculation -> Nullable, } } diff --git a/crates/diesel_models/src/schema_v2.rs b/crates/diesel_models/src/schema_v2.rs index de4adf7984..2deaa3d4ee 100644 --- a/crates/diesel_models/src/schema_v2.rs +++ b/crates/diesel_models/src/schema_v2.rs @@ -899,6 +899,7 @@ diesel::table! { #[max_length = 32] organization_id -> Varchar, tax_details -> Nullable, + skip_external_tax_calculation -> Nullable, } } diff --git a/crates/hyperswitch_domain_models/src/business_profile.rs b/crates/hyperswitch_domain_models/src/business_profile.rs index cfc0d07e0c..c6b76680d4 100644 --- a/crates/hyperswitch_domain_models/src/business_profile.rs +++ b/crates/hyperswitch_domain_models/src/business_profile.rs @@ -659,6 +659,14 @@ impl From for BusinessProfile { } impl BusinessProfile { + pub fn get_is_tax_connector_enabled(&self) -> bool { + let is_tax_connector_enabled = self.is_tax_connector_enabled; + match &self.tax_connector_id { + Some(_id) => is_tax_connector_enabled, + _ => false, + } + } + #[cfg(feature = "v1")] pub fn get_order_fulfillment_time(&self) -> Option { self.intent_fulfillment_time diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs index 1365a7f082..14d7e43450 100644 --- a/crates/hyperswitch_domain_models/src/payments.rs +++ b/crates/hyperswitch_domain_models/src/payments.rs @@ -71,4 +71,5 @@ pub struct PaymentIntent { pub is_payment_processor_token_flow: Option, pub organization_id: id_type::OrganizationId, pub tax_details: Option, + pub skip_external_tax_calculation: Option, } diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index c39e5b8c09..427ca967b9 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -551,6 +551,7 @@ impl behaviour::Conversion for PaymentIntent { organization_id: self.organization_id, shipping_cost: self.shipping_cost, tax_details: self.tax_details, + skip_external_tax_calculation: self.skip_external_tax_calculation, }) } async fn convert_back( @@ -636,6 +637,7 @@ impl behaviour::Conversion for PaymentIntent { organization_id: storage_model.organization_id, shipping_cost: storage_model.shipping_cost, tax_details: storage_model.tax_details, + skip_external_tax_calculation: storage_model.skip_external_tax_calculation, }) } .await @@ -697,6 +699,7 @@ impl behaviour::Conversion for PaymentIntent { organization_id: self.organization_id, shipping_cost: self.shipping_cost, tax_details: self.tax_details, + skip_external_tax_calculation: self.skip_external_tax_calculation, }) } } @@ -760,6 +763,7 @@ impl behaviour::Conversion for PaymentIntent { organization_id: self.organization_id, shipping_cost: self.shipping_cost, tax_details: self.tax_details, + skip_external_tax_calculation: self.skip_external_tax_calculation, }) } @@ -846,6 +850,7 @@ impl behaviour::Conversion for PaymentIntent { .await?, 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, }) } .await @@ -907,6 +912,7 @@ impl behaviour::Conversion for PaymentIntent { organization_id: self.organization_id, shipping_cost: self.shipping_cost, tax_details: self.tax_details, + skip_external_tax_calculation: self.skip_external_tax_calculation, }) } } diff --git a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs index 3f62b16c42..e5b0e8b912 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs @@ -152,6 +152,7 @@ pub struct PaymentIntentNew { pub shipping_details: Option>>, pub is_payment_processor_token_flow: Option, pub organization_id: id_type::OrganizationId, + pub skip_external_tax_calculation: Option, } #[derive(Debug, Clone, Serialize)] diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index cee4e9d1dd..c553840347 100644 --- a/crates/router/src/core/payment_methods/cards.rs +++ b/crates/router/src/core/payment_methods/cards.rs @@ -3626,6 +3626,10 @@ pub async fn list_payment_methods( }); } let currency = payment_intent.as_ref().and_then(|pi| pi.currency); + let skip_external_tax_calculation = payment_intent + .as_ref() + .and_then(|intent| intent.skip_external_tax_calculation) + .unwrap_or(false); let request_external_three_ds_authentication = payment_intent .as_ref() .and_then(|intent| intent.request_external_three_ds_authentication) @@ -3670,6 +3674,10 @@ pub async fn list_payment_methods( business_profile.collect_billing_details_from_wallet_connector })); + let is_tax_connector_enabled = business_profile.as_ref().map_or(false, |business_profile| { + business_profile.get_is_tax_connector_enabled() + }); + Ok(services::ApplicationResponse::Json( api::PaymentMethodListResponse { redirect_url: business_profile @@ -3710,6 +3718,7 @@ pub async fn list_payment_methods( request_external_three_ds_authentication, collect_shipping_details_from_wallets, collect_billing_details_from_wallets, + is_tax_calculation_enabled: is_tax_connector_enabled && !skip_external_tax_calculation, }, )) } diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index d97e609aee..1ad86c7df2 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -3108,6 +3108,7 @@ mod tests { organization_id: id_type::OrganizationId::default(), shipping_cost: None, tax_details: None, + skip_external_tax_calculation: None, }; let req_cs = Some("1".to_string()); assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent).is_ok()); @@ -3176,6 +3177,7 @@ mod tests { organization_id: id_type::OrganizationId::default(), shipping_cost: None, tax_details: None, + skip_external_tax_calculation: None, }; let req_cs = Some("1".to_string()); assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent,).is_err()) @@ -3242,6 +3244,7 @@ mod tests { organization_id: id_type::OrganizationId::default(), shipping_cost: None, tax_details: None, + skip_external_tax_calculation: None, }; let req_cs = Some("1".to_string()); assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent).is_err()) diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 257a3156bb..9a662dc589 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -1283,6 +1283,8 @@ impl PaymentCreate { .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Unable to encrypt customer details")?; + let skip_external_tax_calculation = request.skip_external_tax_calculation; + Ok(storage::PaymentIntent { payment_id: payment_id.to_owned(), merchant_id: merchant_account.get_id().to_owned(), @@ -1338,6 +1340,7 @@ impl PaymentCreate { organization_id: merchant_account.organization_id.clone(), shipping_cost: request.shipping_cost, tax_details: None, + skip_external_tax_calculation, }) } diff --git a/crates/router/src/utils/user/sample_data.rs b/crates/router/src/utils/user/sample_data.rs index 07bfe74f1d..32728fd8fc 100644 --- a/crates/router/src/utils/user/sample_data.rs +++ b/crates/router/src/utils/user/sample_data.rs @@ -250,6 +250,7 @@ pub async fn generate_sample_data( organization_id: org_id.clone(), shipping_cost: None, tax_details: None, + skip_external_tax_calculation: None, }; let payment_attempt = PaymentAttemptBatchNew { attempt_id: attempt_id.clone(), diff --git a/migrations/2024-08-28-044317_add_skip_external_tax_calcualtion_in_payment_intent_table/down.sql b/migrations/2024-08-28-044317_add_skip_external_tax_calcualtion_in_payment_intent_table/down.sql new file mode 100644 index 0000000000..4ca933a4e3 --- /dev/null +++ b/migrations/2024-08-28-044317_add_skip_external_tax_calcualtion_in_payment_intent_table/down.sql @@ -0,0 +1,2 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE payment_intent DROP COLUMN if EXISTS skip_external_tax_calculation; \ No newline at end of file diff --git a/migrations/2024-08-28-044317_add_skip_external_tax_calcualtion_in_payment_intent_table/up.sql b/migrations/2024-08-28-044317_add_skip_external_tax_calcualtion_in_payment_intent_table/up.sql new file mode 100644 index 0000000000..cf185dcdb7 --- /dev/null +++ b/migrations/2024-08-28-044317_add_skip_external_tax_calcualtion_in_payment_intent_table/up.sql @@ -0,0 +1,2 @@ +-- Your SQL goes here +ALTER TABLE payment_intent ADD COLUMN IF NOT EXISTS skip_external_tax_calculation BOOLEAN; \ No newline at end of file