From 82e1bf0d168c60733775f933c838b6f9a6301cad Mon Sep 17 00:00:00 2001 From: Sai Harsha Vardhan <56996463+sai-harsha-vardhan@users.noreply.github.com> Date: Tue, 4 Jul 2023 19:12:52 +0530 Subject: [PATCH] feat(router): modify attempt_id generation logic to accommodate payment_id as prefix (#1596) --- crates/router/src/core/payments/helpers.rs | 12 +++++++++++- .../src/core/payments/operations/payment_create.rs | 6 +++--- .../payments/operations/payment_method_validate.rs | 4 ++-- crates/router/src/db/payment_intent.rs | 2 ++ crates/router/src/utils.rs | 5 +++++ crates/storage_models/src/payment_intent.rs | 6 ++++++ crates/storage_models/src/schema.rs | 1 + .../down.sql | 2 ++ .../up.sql | 6 ++++++ 9 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 migrations/2023-07-03-093552_add_attempt_count_in_payment_intent/down.sql create mode 100644 migrations/2023-07-03-093552_add_attempt_count_in_payment_intent/up.sql diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index c17dbb4868..f47f67707a 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -1907,6 +1907,7 @@ mod tests { business_label: "no".to_string(), order_details: None, udf: None, + attempt_count: 1, }; let req_cs = Some("1".to_string()); let merchant_fulfillment_time = Some(900); @@ -1948,6 +1949,7 @@ mod tests { business_label: "no".to_string(), order_details: None, udf: None, + attempt_count: 1, }; let req_cs = Some("1".to_string()); let merchant_fulfillment_time = Some(10); @@ -1989,6 +1991,7 @@ mod tests { business_label: "no".to_string(), order_details: None, udf: None, + attempt_count: 1, }; let req_cs = Some("1".to_string()); let merchant_fulfillment_time = Some(10); @@ -2246,13 +2249,17 @@ impl AttemptType { fn make_new_payment_attempt( payment_method_data: &Option, old_payment_attempt: storage::PaymentAttempt, + new_attempt_count: i16, ) -> storage::PaymentAttemptNew { let created_at @ modified_at @ last_synced = Some(common_utils::date_time::now()); storage::PaymentAttemptNew { + attempt_id: utils::get_payment_attempt_id( + &old_payment_attempt.payment_id, + new_attempt_count, + ), payment_id: old_payment_attempt.payment_id, merchant_id: old_payment_attempt.merchant_id, - attempt_id: uuid::Uuid::new_v4().simple().to_string(), // A new payment attempt is getting created so, used the same function which is used to populate status in PaymentCreate Flow. status: payment_attempt_status_fsm(payment_method_data, Some(true)), @@ -2314,11 +2321,13 @@ impl AttemptType { match self { Self::SameOld => Ok((fetched_payment_intent, fetched_payment_attempt)), Self::New => { + let new_attempt_count = fetched_payment_intent.attempt_count + 1; let new_payment_attempt = db .insert_payment_attempt( Self::make_new_payment_attempt( &request.payment_method_data, fetched_payment_attempt, + new_attempt_count, ), storage_scheme, ) @@ -2336,6 +2345,7 @@ impl AttemptType { Some(true), ), active_attempt_id: new_payment_attempt.attempt_id.to_owned(), + attempt_count: new_attempt_count, }, 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 861fc5f18a..a8ae302558 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -7,7 +7,6 @@ use error_stack::{self, ResultExt}; use router_derive::PaymentOperation; use router_env::{instrument, tracing}; use storage_models::ephemeral_key; -use uuid::Uuid; use super::{BoxedOperation, Domain, GetTracker, Operation, UpdateTracker, ValidateRequest}; use crate::{ @@ -30,7 +29,7 @@ use crate::{ }, transformers::ForeignInto, }, - utils::OptionExt, + utils::{self, OptionExt}, }; #[derive(Debug, Clone, Copy, PaymentOperation)] @@ -527,7 +526,7 @@ impl PaymentCreate { Ok(storage::PaymentAttemptNew { payment_id: payment_id.to_string(), merchant_id: merchant_id.to_string(), - attempt_id: Uuid::new_v4().simple().to_string(), + attempt_id: utils::get_payment_attempt_id(payment_id, 1), status, currency, amount: amount.into(), @@ -641,6 +640,7 @@ impl PaymentCreate { active_attempt_id, order_details: order_details_outside_value, udf: request.udf.clone(), + attempt_count: 1, ..storage::PaymentIntentNew::default() }) } diff --git a/crates/router/src/core/payments/operations/payment_method_validate.rs b/crates/router/src/core/payments/operations/payment_method_validate.rs index f0bee3fe4e..9ca447ba82 100644 --- a/crates/router/src/core/payments/operations/payment_method_validate.rs +++ b/crates/router/src/core/payments/operations/payment_method_validate.rs @@ -5,7 +5,6 @@ use common_utils::{date_time, errors::CustomResult, ext_traits::AsyncExt}; use error_stack::ResultExt; use router_derive::PaymentOperation; use router_env::{instrument, tracing}; -use uuid::Uuid; use super::{BoxedOperation, Domain, GetTracker, PaymentCreate, UpdateTracker, ValidateRequest}; use crate::{ @@ -307,7 +306,7 @@ impl PaymentMethodValidate { storage::PaymentAttemptNew { payment_id: payment_id.to_string(), merchant_id: merchant_id.to_string(), - attempt_id: Uuid::new_v4().simple().to_string(), + attempt_id: utils::get_payment_attempt_id(payment_id, 1), status, // Amount & Currency will be zero in this case amount: 0, @@ -347,6 +346,7 @@ impl PaymentMethodValidate { setup_future_usage: request.setup_future_usage.map(ForeignInto::foreign_into), off_session: request.off_session, active_attempt_id, + attempt_count: 1, ..Default::default() } } diff --git a/crates/router/src/db/payment_intent.rs b/crates/router/src/db/payment_intent.rs index b526c8d138..4fa6c9fb5a 100644 --- a/crates/router/src/db/payment_intent.rs +++ b/crates/router/src/db/payment_intent.rs @@ -97,6 +97,7 @@ mod storage { active_attempt_id: new.active_attempt_id.to_owned(), order_details: new.order_details.clone(), udf: new.udf.clone(), + attempt_count: new.attempt_count, }; match self @@ -357,6 +358,7 @@ impl PaymentIntentInterface for MockDb { active_attempt_id: new.active_attempt_id.to_owned(), order_details: new.order_details, udf: new.udf, + attempt_count: new.attempt_count, }; payment_intents.push(payment_intent.clone()); Ok(payment_intent) diff --git a/crates/router/src/utils.rs b/crates/router/src/utils.rs index b7ee1eb92b..8d909ecc77 100644 --- a/crates/router/src/utils.rs +++ b/crates/router/src/utils.rs @@ -150,3 +150,8 @@ pub fn to_currency_base_unit_asf64( }; Ok(amount) } + +#[inline] +pub fn get_payment_attempt_id(payment_id: impl std::fmt::Display, attempt_count: i16) -> String { + format!("{payment_id}_{attempt_count}") +} diff --git a/crates/storage_models/src/payment_intent.rs b/crates/storage_models/src/payment_intent.rs index 411993dfdf..14173879ba 100644 --- a/crates/storage_models/src/payment_intent.rs +++ b/crates/storage_models/src/payment_intent.rs @@ -39,6 +39,7 @@ pub struct PaymentIntent { #[diesel(deserialize_as = super::OptionalDieselArray)] pub order_details: Option>, pub udf: Option, + pub attempt_count: i16, } #[derive( @@ -84,6 +85,7 @@ pub struct PaymentIntentNew { #[diesel(deserialize_as = super::OptionalDieselArray)] pub order_details: Option>, pub udf: Option, + pub attempt_count: i16, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -135,6 +137,7 @@ pub enum PaymentIntentUpdate { StatusAndAttemptUpdate { status: storage_enums::IntentStatus, active_attempt_id: String, + attempt_count: i16, }, } @@ -164,6 +167,7 @@ pub struct PaymentIntentUpdateInternal { #[diesel(deserialize_as = super::OptionalDieselArray)] pub order_details: Option>, pub udf: Option, + pub attempt_count: Option, } impl PaymentIntentUpdate { @@ -302,9 +306,11 @@ impl From for PaymentIntentUpdateInternal { PaymentIntentUpdate::StatusAndAttemptUpdate { status, active_attempt_id, + attempt_count, } => Self { status: Some(status), active_attempt_id: Some(active_attempt_id), + attempt_count: Some(attempt_count), ..Default::default() }, } diff --git a/crates/storage_models/src/schema.rs b/crates/storage_models/src/schema.rs index fe60718cbd..1e1ce1d733 100644 --- a/crates/storage_models/src/schema.rs +++ b/crates/storage_models/src/schema.rs @@ -478,6 +478,7 @@ diesel::table! { business_label -> Varchar, order_details -> Nullable>>, udf -> Nullable, + attempt_count -> Int2, } } diff --git a/migrations/2023-07-03-093552_add_attempt_count_in_payment_intent/down.sql b/migrations/2023-07-03-093552_add_attempt_count_in_payment_intent/down.sql new file mode 100644 index 0000000000..81e736be3a --- /dev/null +++ b/migrations/2023-07-03-093552_add_attempt_count_in_payment_intent/down.sql @@ -0,0 +1,2 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE PAYMENT_INTENT DROP COLUMN attempt_count; diff --git a/migrations/2023-07-03-093552_add_attempt_count_in_payment_intent/up.sql b/migrations/2023-07-03-093552_add_attempt_count_in_payment_intent/up.sql new file mode 100644 index 0000000000..afc95ab83d --- /dev/null +++ b/migrations/2023-07-03-093552_add_attempt_count_in_payment_intent/up.sql @@ -0,0 +1,6 @@ +ALTER TABLE payment_intent ADD COLUMN attempt_count SMALLINT NOT NULL DEFAULT 1; + +UPDATE payment_intent +SET attempt_count = payment_id_count.count +FROM (SELECT payment_id, count(payment_id) FROM payment_attempt GROUP BY payment_id) as payment_id_count +WHERE payment_intent.payment_id = payment_id_count.payment_id;