Skip to content

Commit

Permalink
fix(core): Add column mandate_data for storing the details of a manda…
Browse files Browse the repository at this point in the history
…te in PaymentAttempt (#3606)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
  • Loading branch information
Aprabhat19 and hyperswitch-bot[bot] authored Feb 9, 2024
1 parent 3cef73b commit 74f3721
Show file tree
Hide file tree
Showing 14 changed files with 91 additions and 144 deletions.
8 changes: 0 additions & 8 deletions crates/data_models/src/mandates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use time::PrimitiveDateTime;
#[serde(rename_all = "snake_case")]
pub struct MandateDetails {
pub update_mandate_id: Option<String>,
pub mandate_type: Option<MandateDataType>,
}

#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)]
Expand All @@ -23,13 +22,6 @@ pub enum MandateDataType {
MultiUse(Option<MandateAmountData>),
}

#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
#[serde(untagged)]
pub enum MandateTypeDetails {
MandateType(MandateDataType),
MandateDetails(MandateDetails),
}
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
pub struct MandateAmountData {
pub amount: i64,
Expand Down
12 changes: 9 additions & 3 deletions crates/data_models/src/payments/payment_attempt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ use serde::{Deserialize, Serialize};
use time::PrimitiveDateTime;

use super::PaymentIntent;
use crate::{errors, mandates::MandateTypeDetails, ForeignIDRef};
use crate::{
errors,
mandates::{MandateDataType, MandateDetails},
ForeignIDRef,
};

#[async_trait::async_trait]
pub trait PaymentAttemptInterface {
Expand Down Expand Up @@ -143,7 +147,7 @@ pub struct PaymentAttempt {
pub straight_through_algorithm: Option<serde_json::Value>,
pub preprocessing_step_id: Option<String>,
// providing a location to store mandate details intermediately for transaction
pub mandate_details: Option<MandateTypeDetails>,
pub mandate_details: Option<MandateDataType>,
pub error_reason: Option<String>,
pub multiple_capture_count: Option<i16>,
// reference to the payment at connector side
Expand All @@ -155,6 +159,7 @@ pub struct PaymentAttempt {
pub merchant_connector_id: Option<String>,
pub unified_code: Option<String>,
pub unified_message: Option<String>,
pub mandate_data: Option<MandateDetails>,
}

impl PaymentAttempt {
Expand Down Expand Up @@ -221,7 +226,7 @@ pub struct PaymentAttemptNew {
pub business_sub_label: Option<String>,
pub straight_through_algorithm: Option<serde_json::Value>,
pub preprocessing_step_id: Option<String>,
pub mandate_details: Option<MandateTypeDetails>,
pub mandate_details: Option<MandateDataType>,
pub error_reason: Option<String>,
pub connector_response_reference_id: Option<String>,
pub multiple_capture_count: Option<i16>,
Expand All @@ -232,6 +237,7 @@ pub struct PaymentAttemptNew {
pub merchant_connector_id: Option<String>,
pub unified_code: Option<String>,
pub unified_message: Option<String>,
pub mandate_data: Option<MandateDetails>,
}

impl PaymentAttemptNew {
Expand Down
29 changes: 8 additions & 21 deletions crates/diesel_models/src/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,20 +174,8 @@ use diesel::{
#[serde(rename_all = "snake_case")]
pub struct MandateDetails {
pub update_mandate_id: Option<String>,
pub mandate_type: Option<MandateDataType>,
}

#[derive(
serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, FromSqlRow, AsExpression,
)]
#[diesel(sql_type = Jsonb)]
#[serde(rename_all = "snake_case")]
pub enum MandateDataType {
SingleUse(MandateAmountData),
MultiUse(Option<MandateAmountData>),
}

impl<DB: Backend> FromSql<Jsonb, DB> for MandateDataType
impl<DB: Backend> FromSql<Jsonb, DB> for MandateDetails
where
serde_json::Value: FromSql<Jsonb, DB>,
{
Expand All @@ -197,7 +185,7 @@ where
}
}

impl ToSql<Jsonb, diesel::pg::Pg> for MandateDataType
impl ToSql<Jsonb, diesel::pg::Pg> for MandateDetails
where
serde_json::Value: ToSql<Jsonb, diesel::pg::Pg>,
{
Expand All @@ -210,19 +198,17 @@ where
<serde_json::Value as ToSql<Jsonb, diesel::pg::Pg>>::to_sql(&value, &mut out.reborrow())
}
}

#[derive(
serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, FromSqlRow, AsExpression,
)]
#[diesel(sql_type = Jsonb)]
#[serde(untagged)]
#[serde(rename_all = "snake_case")]
pub enum MandateTypeDetails {
MandateType(MandateDataType),
MandateDetails(MandateDetails),
pub enum MandateDataType {
SingleUse(MandateAmountData),
MultiUse(Option<MandateAmountData>),
}

impl<DB: Backend> FromSql<Jsonb, DB> for MandateTypeDetails
impl<DB: Backend> FromSql<Jsonb, DB> for MandateDataType
where
serde_json::Value: FromSql<Jsonb, DB>,
{
Expand All @@ -231,7 +217,8 @@ where
Ok(serde_json::from_value(value)?)
}
}
impl ToSql<Jsonb, diesel::pg::Pg> for MandateTypeDetails

impl ToSql<Jsonb, diesel::pg::Pg> for MandateDataType
where
serde_json::Value: ToSql<Jsonb, diesel::pg::Pg>,
{
Expand Down
6 changes: 4 additions & 2 deletions crates/diesel_models/src/payment_attempt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub struct PaymentAttempt {
pub straight_through_algorithm: Option<serde_json::Value>,
pub preprocessing_step_id: Option<String>,
// providing a location to store mandate details intermediately for transaction
pub mandate_details: Option<storage_enums::MandateTypeDetails>,
pub mandate_details: Option<storage_enums::MandateDataType>,
pub error_reason: Option<String>,
pub multiple_capture_count: Option<i16>,
// reference to the payment at connector side
Expand All @@ -64,6 +64,7 @@ pub struct PaymentAttempt {
pub unified_code: Option<String>,
pub unified_message: Option<String>,
pub net_amount: Option<i64>,
pub mandate_data: Option<storage_enums::MandateDetails>,
}

impl PaymentAttempt {
Expand Down Expand Up @@ -126,7 +127,7 @@ pub struct PaymentAttemptNew {
pub business_sub_label: Option<String>,
pub straight_through_algorithm: Option<serde_json::Value>,
pub preprocessing_step_id: Option<String>,
pub mandate_details: Option<storage_enums::MandateTypeDetails>,
pub mandate_details: Option<storage_enums::MandateDataType>,
pub error_reason: Option<String>,
pub connector_response_reference_id: Option<String>,
pub multiple_capture_count: Option<i16>,
Expand All @@ -138,6 +139,7 @@ pub struct PaymentAttemptNew {
pub unified_code: Option<String>,
pub unified_message: Option<String>,
pub net_amount: Option<i64>,
pub mandate_data: Option<storage_enums::MandateDetails>,
}

impl PaymentAttemptNew {
Expand Down
1 change: 1 addition & 0 deletions crates/diesel_models/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,7 @@ diesel::table! {
#[max_length = 1024]
unified_message -> Nullable<Varchar>,
net_amount -> Nullable<Int8>,
mandate_data -> Nullable<Jsonb>,
}
}

Expand Down
10 changes: 8 additions & 2 deletions crates/diesel_models/src/user/sample_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ use common_enums::{
use serde::{Deserialize, Serialize};
use time::PrimitiveDateTime;

use crate::{enums::MandateTypeDetails, schema::payment_attempt, PaymentAttemptNew};
use crate::{
enums::{MandateDataType, MandateDetails},
schema::payment_attempt,
PaymentAttemptNew,
};

#[derive(
Clone, Debug, Default, diesel::Insertable, router_derive::DebugAsDisplay, Serialize, Deserialize,
Expand Down Expand Up @@ -50,7 +54,7 @@ pub struct PaymentAttemptBatchNew {
pub business_sub_label: Option<String>,
pub straight_through_algorithm: Option<serde_json::Value>,
pub preprocessing_step_id: Option<String>,
pub mandate_details: Option<MandateTypeDetails>,
pub mandate_details: Option<MandateDataType>,
pub error_reason: Option<String>,
pub connector_response_reference_id: Option<String>,
pub connector_transaction_id: Option<String>,
Expand All @@ -63,6 +67,7 @@ pub struct PaymentAttemptBatchNew {
pub unified_code: Option<String>,
pub unified_message: Option<String>,
pub net_amount: Option<i64>,
pub mandate_data: Option<MandateDetails>,
}

#[allow(dead_code)]
Expand Down Expand Up @@ -116,6 +121,7 @@ impl PaymentAttemptBatchNew {
unified_code: self.unified_code,
unified_message: self.unified_message,
net_amount: self.net_amount,
mandate_data: self.mandate_data,
}
}
}
62 changes: 27 additions & 35 deletions crates/router/src/core/payment_methods/cards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2000,17 +2000,8 @@ pub async fn list_payment_methods(
merchant_name: merchant_account.merchant_name,
payment_type,
payment_methods: payment_method_responses,
mandate_payment: payment_attempt
.and_then(|inner| inner.mandate_details)
.and_then(|man_type_details| match man_type_details {
data_models::mandates::MandateTypeDetails::MandateType(mandate_type) => {
Some(mandate_type)
}
data_models::mandates::MandateTypeDetails::MandateDetails(mandate_details) => {
mandate_details.mandate_type
}
})
.map(|d| match d {
mandate_payment: payment_attempt.and_then(|inner| inner.mandate_details).map(
|d| match d {
data_models::mandates::MandateDataType::SingleUse(i) => {
api::MandateType::SingleUse(api::MandateAmountData {
amount: i.amount,
Expand All @@ -2032,7 +2023,8 @@ pub async fn list_payment_methods(
data_models::mandates::MandateDataType::MultiUse(None) => {
api::MandateType::MultiUse(None)
}
}),
},
),
show_surcharge_breakup_screen: merchant_surcharge_configs
.show_surcharge_breakup_screen
.unwrap_or_default(),
Expand Down Expand Up @@ -2242,28 +2234,20 @@ pub async fn filter_payment_methods(
})?;
let filter7 = payment_attempt
.and_then(|attempt| attempt.mandate_details.as_ref())
.map(|mandate_details| {
let (mandate_type_present, update_mandate_id_present) =
match mandate_details {
data_models::mandates::MandateTypeDetails::MandateType(_) => {
(true, false)
}
data_models::mandates::MandateTypeDetails::MandateDetails(
mand_details,
) => (
mand_details.mandate_type.is_some(),
mand_details.update_mandate_id.is_some(),
),
};

if mandate_type_present {
filter_pm_based_on_supported_payments_for_mandate(
supported_payment_methods_for_mandate,
&payment_method,
&payment_method_object.payment_method_type,
connector_variant,
)
} else if update_mandate_id_present {
.map(|_mandate_details| {
filter_pm_based_on_supported_payments_for_mandate(
supported_payment_methods_for_mandate,
&payment_method,
&payment_method_object.payment_method_type,
connector_variant,
)
})
.unwrap_or(true);

let filter8 = payment_attempt
.and_then(|attempt| attempt.mandate_data.as_ref())
.map(|mandate_detail| {
if mandate_detail.update_mandate_id.is_some() {
filter_pm_based_on_update_mandate_support_for_connector(
supported_payment_methods_for_update_mandate,
&payment_method,
Expand All @@ -2284,7 +2268,15 @@ pub async fn filter_payment_methods(
payment_method,
);

if filter && filter2 && filter3 && filter4 && filter5 && filter6 && filter7 {
if filter
&& filter2
&& filter3
&& filter4
&& filter5
&& filter6
&& filter7
&& filter8
{
resp.push(response_pm_type);
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/core/payments/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3201,6 +3201,7 @@ impl AttemptType {
unified_code: None,
unified_message: None,
net_amount: old_payment_attempt.amount,
mandate_data: old_payment_attempt.mandate_data,
}
}

Expand Down
23 changes: 3 additions & 20 deletions crates/router/src/core/payments/operations/payment_confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,28 +441,11 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>

// The operation merges mandate data from both request and payment_attempt
setup_mandate = setup_mandate.map(|mut sm| {
sm.mandate_type = payment_attempt
.mandate_details
.clone()
.and_then(|mandate| match mandate {
data_models::mandates::MandateTypeDetails::MandateType(mandate_type) => {
Some(mandate_type)
}
data_models::mandates::MandateTypeDetails::MandateDetails(mandate_details) => {
mandate_details.mandate_type
}
})
.or(sm.mandate_type);
sm.mandate_type = payment_attempt.mandate_details.clone().or(sm.mandate_type);
sm.update_mandate_id = payment_attempt
.mandate_details
.mandate_data
.clone()
.and_then(|mandate| match mandate {
data_models::mandates::MandateTypeDetails::MandateType(_) => None,
data_models::mandates::MandateTypeDetails::MandateDetails(update_id) => {
Some(update_id.update_mandate_id)
}
})
.flatten()
.and_then(|mandate| mandate.update_mandate_id)
.or(sm.update_mandate_id);
sm
});
Expand Down
26 changes: 10 additions & 16 deletions crates/router/src/core/payments/operations/payment_create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use api_models::enums::FrmSuggestion;
use async_trait::async_trait;
use common_utils::ext_traits::{AsyncExt, Encode, ValueExt};
use data_models::{
mandates::{MandateData, MandateDetails, MandateTypeDetails},
mandates::{MandateData, MandateDetails},
payments::payment_attempt::PaymentAttempt,
};
use diesel_models::ephemeral_key;
Expand Down Expand Up @@ -733,27 +733,17 @@ impl PaymentCreate {
Err(errors::ApiErrorResponse::InvalidRequestData {message:"Only one field out of 'mandate_type' and 'update_mandate_id' was expected, found both".to_string()})?
}

let mandate_details = if request.mandate_data.is_none() {
None
} else if let Some(update_id) = request
let mandate_data = if let Some(update_id) = request
.mandate_data
.as_ref()
.and_then(|inner| inner.update_mandate_id.clone())
{
let mandate_data = MandateDetails {
let mandate_details = MandateDetails {
update_mandate_id: Some(update_id),
mandate_type: None,
};
Some(MandateTypeDetails::MandateDetails(mandate_data))
Some(mandate_details)
} else {
let mandate_data = MandateDetails {
update_mandate_id: None,
mandate_type: request
.mandate_data
.as_ref()
.and_then(|inner| inner.mandate_type.clone().map(Into::into)),
};
Some(MandateTypeDetails::MandateDetails(mandate_data))
None
};

Ok((
Expand Down Expand Up @@ -782,7 +772,11 @@ impl PaymentCreate {
business_sub_label: request.business_sub_label.clone(),
surcharge_amount,
tax_amount,
mandate_details,
mandate_details: request
.mandate_data
.as_ref()
.and_then(|inner| inner.mandate_type.clone().map(Into::into)),
mandate_data,
..storage::PaymentAttemptNew::default()
},
additional_pm_data,
Expand Down
Loading

0 comments on commit 74f3721

Please sign in to comment.