refactor(payment_methods): allow deletion of default payment method for a customer if only one pm exists (#4027)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Chethan Rao
2024-03-12 10:49:00 +05:30
committed by GitHub
parent abe9c2ac17
commit 45ed56f165
7 changed files with 128 additions and 5 deletions

View File

@ -3201,7 +3201,7 @@ pub async fn set_default_payment_method(
)?;
let customer_update = CustomerUpdate::UpdateDefaultPaymentMethod {
default_payment_method_id: Some(payment_method_id.to_owned()),
default_payment_method_id: Some(Some(payment_method_id.to_owned())),
};
// update the db with the default payment method id
@ -3450,6 +3450,16 @@ pub async fn delete_payment_method(
.await
.to_not_found_response(errors::ApiErrorResponse::PaymentMethodNotFound)?;
let payment_methods_count = db
.get_payment_method_count_by_customer_id_merchant_id_status(
&key.customer_id,
&merchant_account.merchant_id,
api_enums::PaymentMethodStatus::Active,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed to get a count of payment methods for a customer")?;
let customer = db
.find_customer_by_customer_id_merchant_id(
&key.customer_id,
@ -3461,7 +3471,8 @@ pub async fn delete_payment_method(
.attach_printable("Customer not found for the payment method")?;
utils::when(
customer.default_payment_method_id.as_ref() == Some(&pm_id.payment_method_id),
customer.default_payment_method_id.as_ref() == Some(&pm_id.payment_method_id)
&& payment_methods_count > 1,
|| Err(errors::ApiErrorResponse::PaymentMethodDeleteFailed),
)?;
@ -3489,6 +3500,22 @@ pub async fn delete_payment_method(
.await
.to_not_found_response(errors::ApiErrorResponse::PaymentMethodNotFound)?;
if customer.default_payment_method_id.as_ref() == Some(&pm_id.payment_method_id) {
let customer_update = CustomerUpdate::UpdateDefaultPaymentMethod {
default_payment_method_id: Some(None),
};
db.update_customer_by_customer_id_merchant_id(
key.customer_id,
key.merchant_id,
customer_update,
&key_store,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed to update the default payment method id for the customer")?;
};
Ok(services::ApplicationResponse::Json(
api::PaymentMethodDeleteResponse {
payment_method_id: key.payment_method_id,

View File

@ -1299,6 +1299,21 @@ impl PaymentMethodInterface for KafkaStore {
.await
}
async fn get_payment_method_count_by_customer_id_merchant_id_status(
&self,
customer_id: &str,
merchant_id: &str,
status: common_enums::PaymentMethodStatus,
) -> CustomResult<i64, errors::StorageError> {
self.diesel_store
.get_payment_method_count_by_customer_id_merchant_id_status(
customer_id,
merchant_id,
status,
)
.await
}
async fn find_payment_method_by_locker_id(
&self,
locker_id: &str,

View File

@ -36,6 +36,13 @@ pub trait PaymentMethodInterface {
limit: Option<i64>,
) -> CustomResult<Vec<storage::PaymentMethod>, errors::StorageError>;
async fn get_payment_method_count_by_customer_id_merchant_id_status(
&self,
customer_id: &str,
merchant_id: &str,
status: common_enums::PaymentMethodStatus,
) -> CustomResult<i64, errors::StorageError>;
async fn insert_payment_method(
&self,
payment_method_new: storage::PaymentMethodNew,
@ -80,6 +87,25 @@ impl PaymentMethodInterface for Store {
.into_report()
}
#[instrument(skip_all)]
async fn get_payment_method_count_by_customer_id_merchant_id_status(
&self,
customer_id: &str,
merchant_id: &str,
status: common_enums::PaymentMethodStatus,
) -> CustomResult<i64, errors::StorageError> {
let conn = connection::pg_connection_read(self).await?;
storage::PaymentMethod::get_count_by_customer_id_merchant_id_status(
&conn,
customer_id,
merchant_id,
status,
)
.await
.map_err(Into::into)
.into_report()
}
#[instrument(skip_all)]
async fn insert_payment_method(
&self,
@ -204,6 +230,27 @@ impl PaymentMethodInterface for MockDb {
}
}
async fn get_payment_method_count_by_customer_id_merchant_id_status(
&self,
customer_id: &str,
merchant_id: &str,
status: common_enums::PaymentMethodStatus,
) -> CustomResult<i64, errors::StorageError> {
let payment_methods = self.payment_methods.lock().await;
let count = payment_methods
.iter()
.filter(|pm| {
pm.customer_id == customer_id
&& pm.merchant_id == merchant_id
&& pm.status == status
})
.count();
count
.try_into()
.into_report()
.change_context(errors::StorageError::MockDbError)
}
async fn insert_payment_method(
&self,
payment_method_new: storage::PaymentMethodNew,

View File

@ -118,7 +118,7 @@ pub enum CustomerUpdate {
connector_customer: Option<serde_json::Value>,
},
UpdateDefaultPaymentMethod {
default_payment_method_id: Option<String>,
default_payment_method_id: Option<Option<String>>,
},
}