mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 10:06:32 +08:00 
			
		
		
		
	feat(router): add connector mit related columns to the payment methods table (#3764)
This commit is contained in:
		| @ -1177,6 +1177,32 @@ pub enum PaymentMethodIssuerCode { | |||||||
|     JpBacs, |     JpBacs, | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[derive( | ||||||
|  |     Clone, | ||||||
|  |     Copy, | ||||||
|  |     Debug, | ||||||
|  |     PartialEq, | ||||||
|  |     Eq, | ||||||
|  |     Hash, | ||||||
|  |     serde::Serialize, | ||||||
|  |     serde::Deserialize, | ||||||
|  |     strum::Display, | ||||||
|  |     strum::EnumString, | ||||||
|  |     ToSchema, | ||||||
|  | )] | ||||||
|  | #[router_derive::diesel_enum(storage_type = "text")] | ||||||
|  | #[strum(serialize_all = "snake_case")] | ||||||
|  | #[serde(rename_all = "snake_case")] | ||||||
|  | pub enum PaymentMethodStatus { | ||||||
|  |     /// Indicates that the payment method is active and can be used for payments. | ||||||
|  |     Active, | ||||||
|  |     /// Indicates that the payment method is not active and hence cannot be used for payments. | ||||||
|  |     Inactive, | ||||||
|  |     /// Indicates that the payment method is awaiting some data or action before it can be marked | ||||||
|  |     /// as 'active'. | ||||||
|  |     Processing, | ||||||
|  | } | ||||||
|  |  | ||||||
| /// To indicate the type of payment experience that the customer would go through | /// To indicate the type of payment experience that the customer would go through | ||||||
| #[derive( | #[derive( | ||||||
|     Eq, |     Eq, | ||||||
|  | |||||||
| @ -34,6 +34,9 @@ pub struct PaymentMethod { | |||||||
|     pub metadata: Option<pii::SecretSerdeValue>, |     pub metadata: Option<pii::SecretSerdeValue>, | ||||||
|     pub payment_method_data: Option<Encryption>, |     pub payment_method_data: Option<Encryption>, | ||||||
|     pub locker_id: Option<String>, |     pub locker_id: Option<String>, | ||||||
|  |     pub connector_mandate_details: Option<serde_json::Value>, | ||||||
|  |     pub customer_acceptance: Option<pii::SecretSerdeValue>, | ||||||
|  |     pub status: storage_enums::PaymentMethodStatus, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Clone, Debug, Eq, PartialEq, Insertable, Queryable, router_derive::DebugAsDisplay)] | #[derive(Clone, Debug, Eq, PartialEq, Insertable, Queryable, router_derive::DebugAsDisplay)] | ||||||
| @ -61,6 +64,9 @@ pub struct PaymentMethodNew { | |||||||
|     pub metadata: Option<pii::SecretSerdeValue>, |     pub metadata: Option<pii::SecretSerdeValue>, | ||||||
|     pub payment_method_data: Option<Encryption>, |     pub payment_method_data: Option<Encryption>, | ||||||
|     pub locker_id: Option<String>, |     pub locker_id: Option<String>, | ||||||
|  |     pub connector_mandate_details: Option<serde_json::Value>, | ||||||
|  |     pub customer_acceptance: Option<pii::SecretSerdeValue>, | ||||||
|  |     pub status: storage_enums::PaymentMethodStatus, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl Default for PaymentMethodNew { | impl Default for PaymentMethodNew { | ||||||
| @ -90,6 +96,9 @@ impl Default for PaymentMethodNew { | |||||||
|             last_modified: now, |             last_modified: now, | ||||||
|             metadata: Option::default(), |             metadata: Option::default(), | ||||||
|             payment_method_data: Option::default(), |             payment_method_data: Option::default(), | ||||||
|  |             connector_mandate_details: Option::default(), | ||||||
|  |             customer_acceptance: Option::default(), | ||||||
|  |             status: storage_enums::PaymentMethodStatus::Active, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ use router_env::{instrument, tracing}; | |||||||
|  |  | ||||||
| use super::generics; | use super::generics; | ||||||
| use crate::{ | use crate::{ | ||||||
|     errors, |     enums as storage_enums, errors, | ||||||
|     payment_method::{self, PaymentMethod, PaymentMethodNew}, |     payment_method::{self, PaymentMethod, PaymentMethodNew}, | ||||||
|     schema::payment_methods::dsl, |     schema::payment_methods::dsl, | ||||||
|     PgPooledConn, StorageResult, |     PgPooledConn, StorageResult, | ||||||
| @ -108,6 +108,31 @@ impl PaymentMethod { | |||||||
|         .await |         .await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     #[instrument(skip(conn))] | ||||||
|  |     pub async fn find_by_customer_id_merchant_id_status( | ||||||
|  |         conn: &PgPooledConn, | ||||||
|  |         customer_id: &str, | ||||||
|  |         merchant_id: &str, | ||||||
|  |         status: storage_enums::PaymentMethodStatus, | ||||||
|  |     ) -> StorageResult<Vec<Self>> { | ||||||
|  |         generics::generic_filter::< | ||||||
|  |             <Self as HasTable>::Table, | ||||||
|  |             _, | ||||||
|  |             <<Self as HasTable>::Table as Table>::PrimaryKey, | ||||||
|  |             _, | ||||||
|  |         >( | ||||||
|  |             conn, | ||||||
|  |             dsl::customer_id | ||||||
|  |                 .eq(customer_id.to_owned()) | ||||||
|  |                 .and(dsl::merchant_id.eq(merchant_id.to_owned())) | ||||||
|  |                 .and(dsl::status.eq(status)), | ||||||
|  |             None, | ||||||
|  |             None, | ||||||
|  |             None, | ||||||
|  |         ) | ||||||
|  |         .await | ||||||
|  |     } | ||||||
|  |  | ||||||
|     pub async fn update_with_payment_method_id( |     pub async fn update_with_payment_method_id( | ||||||
|         self, |         self, | ||||||
|         conn: &PgPooledConn, |         conn: &PgPooledConn, | ||||||
|  | |||||||
| @ -831,6 +831,10 @@ diesel::table! { | |||||||
|         payment_method_data -> Nullable<Bytea>, |         payment_method_data -> Nullable<Bytea>, | ||||||
|         #[max_length = 64] |         #[max_length = 64] | ||||||
|         locker_id -> Nullable<Varchar>, |         locker_id -> Nullable<Varchar>, | ||||||
|  |         connector_mandate_details -> Nullable<Jsonb>, | ||||||
|  |         customer_acceptance -> Nullable<Jsonb>, | ||||||
|  |         #[max_length = 64] | ||||||
|  |         status -> Varchar, | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -2667,9 +2667,10 @@ pub async fn list_customer_payment_method( | |||||||
|     let requires_cvv = is_requires_cvv.config != "false"; |     let requires_cvv = is_requires_cvv.config != "false"; | ||||||
|  |  | ||||||
|     let resp = db |     let resp = db | ||||||
|         .find_payment_method_by_customer_id_merchant_id_list( |         .find_payment_method_by_customer_id_merchant_id_status( | ||||||
|             customer_id, |             customer_id, | ||||||
|             &merchant_account.merchant_id, |             &merchant_account.merchant_id, | ||||||
|  |             common_enums::PaymentMethodStatus::Active, | ||||||
|         ) |         ) | ||||||
|         .await |         .await | ||||||
|         .to_not_found_response(errors::ApiErrorResponse::PaymentMethodNotFound)?; |         .to_not_found_response(errors::ApiErrorResponse::PaymentMethodNotFound)?; | ||||||
|  | |||||||
| @ -1273,6 +1273,17 @@ impl PaymentMethodInterface for KafkaStore { | |||||||
|             .await |             .await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     async fn find_payment_method_by_customer_id_merchant_id_status( | ||||||
|  |         &self, | ||||||
|  |         customer_id: &str, | ||||||
|  |         merchant_id: &str, | ||||||
|  |         status: common_enums::PaymentMethodStatus, | ||||||
|  |     ) -> CustomResult<Vec<storage::PaymentMethod>, errors::StorageError> { | ||||||
|  |         self.diesel_store | ||||||
|  |             .find_payment_method_by_customer_id_merchant_id_status(customer_id, merchant_id, status) | ||||||
|  |             .await | ||||||
|  |     } | ||||||
|  |  | ||||||
|     async fn find_payment_method_by_locker_id( |     async fn find_payment_method_by_locker_id( | ||||||
|         &self, |         &self, | ||||||
|         locker_id: &str, |         locker_id: &str, | ||||||
|  | |||||||
| @ -26,6 +26,13 @@ pub trait PaymentMethodInterface { | |||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<storage::PaymentMethod>, errors::StorageError>; |     ) -> CustomResult<Vec<storage::PaymentMethod>, errors::StorageError>; | ||||||
|  |  | ||||||
|  |     async fn find_payment_method_by_customer_id_merchant_id_status( | ||||||
|  |         &self, | ||||||
|  |         customer_id: &str, | ||||||
|  |         merchant_id: &str, | ||||||
|  |         status: common_enums::PaymentMethodStatus, | ||||||
|  |     ) -> CustomResult<Vec<storage::PaymentMethod>, errors::StorageError>; | ||||||
|  |  | ||||||
|     async fn insert_payment_method( |     async fn insert_payment_method( | ||||||
|         &self, |         &self, | ||||||
|         payment_method_new: storage::PaymentMethodNew, |         payment_method_new: storage::PaymentMethodNew, | ||||||
| @ -105,6 +112,24 @@ impl PaymentMethodInterface for Store { | |||||||
|             .into_report() |             .into_report() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     async fn find_payment_method_by_customer_id_merchant_id_status( | ||||||
|  |         &self, | ||||||
|  |         customer_id: &str, | ||||||
|  |         merchant_id: &str, | ||||||
|  |         status: common_enums::PaymentMethodStatus, | ||||||
|  |     ) -> CustomResult<Vec<storage::PaymentMethod>, errors::StorageError> { | ||||||
|  |         let conn = connection::pg_connection_read(self).await?; | ||||||
|  |         storage::PaymentMethod::find_by_customer_id_merchant_id_status( | ||||||
|  |             &conn, | ||||||
|  |             customer_id, | ||||||
|  |             merchant_id, | ||||||
|  |             status, | ||||||
|  |         ) | ||||||
|  |         .await | ||||||
|  |         .map_err(Into::into) | ||||||
|  |         .into_report() | ||||||
|  |     } | ||||||
|  |  | ||||||
|     async fn delete_payment_method_by_merchant_id_payment_method_id( |     async fn delete_payment_method_by_merchant_id_payment_method_id( | ||||||
|         &self, |         &self, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
| @ -196,6 +221,9 @@ impl PaymentMethodInterface for MockDb { | |||||||
|             payment_method_issuer_code: payment_method_new.payment_method_issuer_code, |             payment_method_issuer_code: payment_method_new.payment_method_issuer_code, | ||||||
|             metadata: payment_method_new.metadata, |             metadata: payment_method_new.metadata, | ||||||
|             payment_method_data: payment_method_new.payment_method_data, |             payment_method_data: payment_method_new.payment_method_data, | ||||||
|  |             connector_mandate_details: payment_method_new.connector_mandate_details, | ||||||
|  |             customer_acceptance: payment_method_new.customer_acceptance, | ||||||
|  |             status: payment_method_new.status, | ||||||
|         }; |         }; | ||||||
|         payment_methods.push(payment_method.clone()); |         payment_methods.push(payment_method.clone()); | ||||||
|         Ok(payment_method) |         Ok(payment_method) | ||||||
| @ -223,6 +251,33 @@ impl PaymentMethodInterface for MockDb { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     async fn find_payment_method_by_customer_id_merchant_id_status( | ||||||
|  |         &self, | ||||||
|  |         customer_id: &str, | ||||||
|  |         merchant_id: &str, | ||||||
|  |         status: common_enums::PaymentMethodStatus, | ||||||
|  |     ) -> CustomResult<Vec<storage::PaymentMethod>, errors::StorageError> { | ||||||
|  |         let payment_methods = self.payment_methods.lock().await; | ||||||
|  |         let payment_methods_found: Vec<storage::PaymentMethod> = payment_methods | ||||||
|  |             .iter() | ||||||
|  |             .filter(|pm| { | ||||||
|  |                 pm.customer_id == customer_id | ||||||
|  |                     && pm.merchant_id == merchant_id | ||||||
|  |                     && pm.status == status | ||||||
|  |             }) | ||||||
|  |             .cloned() | ||||||
|  |             .collect(); | ||||||
|  |  | ||||||
|  |         if payment_methods_found.is_empty() { | ||||||
|  |             Err(errors::StorageError::ValueNotFound( | ||||||
|  |                 "cannot find payment methods".to_string(), | ||||||
|  |             )) | ||||||
|  |             .into_report() | ||||||
|  |         } else { | ||||||
|  |             Ok(payment_methods_found) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     async fn delete_payment_method_by_merchant_id_payment_method_id( |     async fn delete_payment_method_by_merchant_id_payment_method_id( | ||||||
|         &self, |         &self, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|  | |||||||
| @ -0,0 +1,10 @@ | |||||||
|  | -- This file should undo anything in `up.sql` | ||||||
|  |  | ||||||
|  | ALTER TABLE payment_methods | ||||||
|  | DROP COLUMN status; | ||||||
|  |  | ||||||
|  | ALTER TABLE payment_methods | ||||||
|  | DROP COLUMN customer_acceptance; | ||||||
|  |  | ||||||
|  | ALTER TABLE payment_methods | ||||||
|  | DROP COLUMN connector_mandate_details; | ||||||
| @ -0,0 +1,13 @@ | |||||||
|  | -- Your SQL goes here | ||||||
|  |  | ||||||
|  | ALTER TABLE payment_methods | ||||||
|  | ADD COLUMN connector_mandate_details JSONB | ||||||
|  | DEFAULT NULL; | ||||||
|  |  | ||||||
|  | ALTER TABLE payment_methods | ||||||
|  | ADD COLUMN customer_acceptance JSONB | ||||||
|  | DEFAULT NULL; | ||||||
|  |  | ||||||
|  | ALTER TABLE payment_methods | ||||||
|  | ADD COLUMN status VARCHAR(64) | ||||||
|  | NOT NULL DEFAULT 'active'; | ||||||
		Reference in New Issue
	
	Block a user
	 Shanks
					Shanks