Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(bank-debit): remove billingdetails from bankdebit pmd #4371

Merged
merged 16 commits into from May 8, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
59 changes: 34 additions & 25 deletions crates/api_models/src/payments.rs
Expand Up @@ -1091,7 +1091,7 @@ pub enum BankDebitData {
/// Payment Method data for Ach bank debit
AchBankDebit {
/// Billing details for bank debit
billing_details: BankDebitBilling,
billing_details: Option<BankDebitBilling>,
/// Account number for ach bank debit payment
#[schema(value_type = String, example = "000123456789")]
account_number: Secret<String>,
Expand All @@ -1116,7 +1116,7 @@ pub enum BankDebitData {
},
SepaBankDebit {
/// Billing details for bank debit
billing_details: BankDebitBilling,
billing_details: Option<BankDebitBilling>,
/// International bank account number (iban) for SEPA
#[schema(value_type = String, example = "DE89370400440532013000")]
iban: Secret<String>,
Expand All @@ -1126,7 +1126,7 @@ pub enum BankDebitData {
},
BecsBankDebit {
/// Billing details for bank debit
billing_details: BankDebitBilling,
billing_details: Option<BankDebitBilling>,
/// Account number for Becs payment method
#[schema(value_type = String, example = "000123456")]
account_number: Secret<String>,
Expand All @@ -1139,7 +1139,7 @@ pub enum BankDebitData {
},
BacsBankDebit {
/// Billing details for bank debit
billing_details: BankDebitBilling,
billing_details: Option<BankDebitBilling>,
/// Account number for Bacs payment method
#[schema(value_type = String, example = "00012345")]
account_number: Secret<String>,
Expand All @@ -1155,20 +1155,26 @@ pub enum BankDebitData {
impl GetAddressFromPaymentMethodData for BankDebitData {
fn get_billing_address(&self) -> Option<Address> {
fn get_billing_address_inner(
bank_debit_billing: &BankDebitBilling,
bank_debit_billing: Option<&BankDebitBilling>,
bank_account_holder_name: Option<&Secret<String>>,
) -> Option<Address> {
// We will always have address here
let mut address = bank_debit_billing.get_billing_address()?;
let mut address =
bank_debit_billing.and_then(GetAddressFromPaymentMethodData::get_billing_address);

// Prefer `account_holder_name` over `name`
address.address.as_mut().map(|address| {
address.first_name = bank_account_holder_name
.or(address.first_name.as_ref())
.cloned();
address = address.map(|mut address| -> Address {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this changed?

address.address = address
.address
.map(|mut address_details| -> AddressDetails {
address_details.first_name = bank_account_holder_name
.or(address_details.first_name.as_ref())
.cloned();
address_details
});
address
});

Some(address)
address
}

match self {
Expand All @@ -1191,7 +1197,10 @@ impl GetAddressFromPaymentMethodData for BankDebitData {
billing_details,
bank_account_holder_name,
..
} => get_billing_address_inner(billing_details, bank_account_holder_name.as_ref()),
} => get_billing_address_inner(
billing_details.as_ref(),
bank_account_holder_name.as_ref(),
),
}
}
}
Expand Down Expand Up @@ -1345,7 +1354,7 @@ impl GetAddressFromPaymentMethodData for PaymentMethodData {
Self::Wallet(wallet_data) => wallet_data.get_billing_address(),
Self::PayLater(_) => None,
Self::BankRedirect(_) => None,
Self::BankDebit(_) => None,
Self::BankDebit(bank_debit_data) => bank_debit_data.get_billing_address(),
Self::BankTransfer(_) => None,
Self::Voucher(voucher_data) => voucher_data.get_billing_address(),
Self::Crypto(_)
Expand Down Expand Up @@ -2139,31 +2148,31 @@ impl GetAddressFromPaymentMethodData for BankTransferData {
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, ToSchema, Eq, PartialEq)]
pub struct BankDebitBilling {
/// The billing name for bank debits
#[schema(value_type = String, example = "John Doe")]
pub name: Secret<String>,
#[schema(value_type = Option<String>, example = "John Doe")]
pub name: Option<Secret<String>>,
/// The billing email for bank debits
#[schema(value_type = String, example = "example@example.com")]
pub email: Email,
#[schema(value_type = Option<String>, example = "example@example.com")]
pub email: Option<Email>,
/// The billing address for bank debits
pub address: Option<AddressDetails>,
}

impl GetAddressFromPaymentMethodData for BankDebitBilling {
fn get_billing_address(&self) -> Option<Address> {
let address = if let Some(mut address) = self.address.clone() {
address.first_name = Some(self.name.clone());
address.first_name = self.name.clone();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, what if self.name is none, won't we be overriding the value of address.first_name? Instead you can put an or() and then consider address.first_name. Something like this

address.first_name = self.name.clone().or(address.first_name)

Address {
address: Some(address),
email: Some(self.email.clone()),
email: self.email.clone(),
phone: None,
}
} else {
Address {
address: Some(AddressDetails {
first_name: Some(self.name.clone()),
first_name: self.name.clone(),
..AddressDetails::default()
}),
email: Some(self.email.clone()),
email: self.email.clone(),
phone: None,
}
};
Expand Down Expand Up @@ -4772,14 +4781,14 @@ mod billing_from_payment_method_data {
let test_first_name = Secret::new(String::from("Chaser"));

let bank_redirect_billing = BankDebitBilling {
name: test_first_name.clone(),
name: Some(test_first_name.clone()),
address: None,
email: test_email.clone(),
email: Some(test_email.clone()),
};

let ach_bank_debit_payment_method_data =
PaymentMethodData::BankDebit(BankDebitData::AchBankDebit {
billing_details: bank_redirect_billing,
billing_details: Some(bank_redirect_billing),
account_number: Secret::new("1234".to_string()),
routing_number: Secret::new("1235".to_string()),
card_holder_name: None,
Expand Down
42 changes: 14 additions & 28 deletions crates/router/src/connector/adyen/transformers.rs
Expand Up @@ -1822,56 +1822,42 @@ fn build_shopper_reference(customer_id: &Option<String>, merchant_id: String) ->
.map(|c_id| format!("{}_{}", merchant_id, c_id))
}

impl<'a> TryFrom<&domain::BankDebitData> for AdyenPaymentMethod<'a> {
impl<'a> TryFrom<(&domain::BankDebitData, &types::PaymentsAuthorizeRouterData)>
for AdyenPaymentMethod<'a>
{
type Error = Error;
fn try_from(bank_debit_data: &domain::BankDebitData) -> Result<Self, Self::Error> {
fn try_from(
(bank_debit_data, item): (&domain::BankDebitData, &types::PaymentsAuthorizeRouterData),
) -> Result<Self, Self::Error> {
match bank_debit_data {
domain::BankDebitData::AchBankDebit {
account_number,
routing_number,
card_holder_name,
..
} => Ok(AdyenPaymentMethod::AchDirectDebit(Box::new(
AchDirectDebitData {
payment_type: PaymentType::AchDirectDebit,
bank_account_number: account_number.clone(),
bank_location_id: routing_number.clone(),
owner_name: card_holder_name.clone().ok_or(
errors::ConnectorError::MissingRequiredField {
field_name: "card_holder_name",
},
)?,
owner_name: item.get_billing_full_name()?,
},
))),
domain::BankDebitData::SepaBankDebit {
iban,
bank_account_holder_name,
..
} => Ok(AdyenPaymentMethod::SepaDirectDebit(Box::new(
SepaDirectDebitData {
owner_name: bank_account_holder_name.clone().ok_or(
errors::ConnectorError::MissingRequiredField {
field_name: "bank_account_holder_name",
},
)?,
domain::BankDebitData::SepaBankDebit { iban, .. } => Ok(
AdyenPaymentMethod::SepaDirectDebit(Box::new(SepaDirectDebitData {
owner_name: item.get_billing_full_name()?,
iban_number: iban.clone(),
},
))),
})),
),
domain::BankDebitData::BacsBankDebit {
account_number,
sort_code,
bank_account_holder_name,
..
} => Ok(AdyenPaymentMethod::BacsDirectDebit(Box::new(
BacsDirectDebitData {
payment_type: PaymentType::BacsDirectDebit,
bank_account_number: account_number.clone(),
bank_location_id: sort_code.clone(),
holder_name: bank_account_holder_name.clone().ok_or(
errors::ConnectorError::MissingRequiredField {
field_name: "bank_account_holder_name",
},
)?,
holder_name: item.get_billing_full_name()?,
},
))),
domain::BankDebitData::BecsBankDebit { .. } => {
Expand Down Expand Up @@ -2715,7 +2701,7 @@ impl<'a>
let browser_info = get_browser_info(item.router_data)?;
let additional_data = get_additional_data(item.router_data);
let return_url = item.router_data.request.get_return_url()?;
let payment_method = AdyenPaymentMethod::try_from(bank_debit_data)?;
let payment_method = AdyenPaymentMethod::try_from((bank_debit_data, item.router_data))?;
let country_code = get_country_code(item.router_data.get_optional_billing());
let request = AdyenPaymentRequest {
amount,
Expand Down