mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 10:06:32 +08:00 
			
		
		
		
	feat(router): add gateway_status_map interface (#2804)
				
					
				
			This commit is contained in:
		 Sai Harsha Vardhan
					Sai Harsha Vardhan
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							7623ea93be
						
					
				
				
					commit
					a429b23c7f
				
			
							
								
								
									
										97
									
								
								crates/diesel_models/src/gsm.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								crates/diesel_models/src/gsm.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,97 @@ | ||||
| //! Gateway status mapping | ||||
|  | ||||
| use common_utils::custom_serde; | ||||
| use diesel::{AsChangeset, Identifiable, Insertable, Queryable}; | ||||
| use time::PrimitiveDateTime; | ||||
|  | ||||
| use crate::schema::gateway_status_map; | ||||
|  | ||||
| #[derive( | ||||
|     Clone, | ||||
|     Debug, | ||||
|     Eq, | ||||
|     PartialEq, | ||||
|     router_derive::DebugAsDisplay, | ||||
|     Identifiable, | ||||
|     Queryable, | ||||
|     serde::Serialize, | ||||
| )] | ||||
| #[diesel(table_name = gateway_status_map, primary_key(connector, flow, sub_flow, code, message))] | ||||
| pub struct GatewayStatusMap { | ||||
|     pub connector: String, | ||||
|     pub flow: String, | ||||
|     pub sub_flow: String, | ||||
|     pub code: String, | ||||
|     pub message: String, | ||||
|     pub status: String, | ||||
|     pub router_error: Option<String>, | ||||
|     pub decision: String, | ||||
|     #[serde(with = "custom_serde::iso8601")] | ||||
|     pub created_at: PrimitiveDateTime, | ||||
|     #[serde(with = "custom_serde::iso8601")] | ||||
|     pub last_modified: PrimitiveDateTime, | ||||
|     pub step_up_possible: bool, | ||||
| } | ||||
|  | ||||
| #[derive(Clone, Debug, Eq, PartialEq, Insertable)] | ||||
| #[diesel(table_name = gateway_status_map)] | ||||
| pub struct GatewayStatusMappingNew { | ||||
|     pub connector: String, | ||||
|     pub flow: String, | ||||
|     pub sub_flow: String, | ||||
|     pub code: String, | ||||
|     pub message: String, | ||||
|     pub status: String, | ||||
|     pub router_error: Option<String>, | ||||
|     pub decision: String, | ||||
|     pub step_up_possible: bool, | ||||
| } | ||||
|  | ||||
| #[derive( | ||||
|     Clone, | ||||
|     Debug, | ||||
|     PartialEq, | ||||
|     Eq, | ||||
|     AsChangeset, | ||||
|     router_derive::DebugAsDisplay, | ||||
|     Default, | ||||
|     serde::Deserialize, | ||||
| )] | ||||
| #[diesel(table_name = gateway_status_map)] | ||||
| pub struct GatewayStatusMapperUpdateInternal { | ||||
|     pub connector: Option<String>, | ||||
|     pub flow: Option<String>, | ||||
|     pub sub_flow: Option<String>, | ||||
|     pub code: Option<String>, | ||||
|     pub message: Option<String>, | ||||
|     pub status: Option<String>, | ||||
|     pub router_error: Option<Option<String>>, | ||||
|     pub decision: Option<String>, | ||||
|     pub step_up_possible: Option<bool>, | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub struct GatewayStatusMappingUpdate { | ||||
|     pub status: Option<String>, | ||||
|     pub router_error: Option<Option<String>>, | ||||
|     pub decision: Option<String>, | ||||
|     pub step_up_possible: Option<bool>, | ||||
| } | ||||
|  | ||||
| impl From<GatewayStatusMappingUpdate> for GatewayStatusMapperUpdateInternal { | ||||
|     fn from(value: GatewayStatusMappingUpdate) -> Self { | ||||
|         let GatewayStatusMappingUpdate { | ||||
|             decision, | ||||
|             status, | ||||
|             router_error, | ||||
|             step_up_possible, | ||||
|         } = value; | ||||
|         Self { | ||||
|             status, | ||||
|             router_error, | ||||
|             decision, | ||||
|             step_up_possible, | ||||
|             ..Default::default() | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -15,6 +15,7 @@ pub mod events; | ||||
| pub mod file; | ||||
| #[allow(unused)] | ||||
| pub mod fraud_check; | ||||
| pub mod gsm; | ||||
| #[cfg(feature = "kv_store")] | ||||
| pub mod kv; | ||||
| pub mod locker_mock_up; | ||||
|  | ||||
| @ -11,6 +11,7 @@ pub mod events; | ||||
| pub mod file; | ||||
| pub mod fraud_check; | ||||
| pub mod generics; | ||||
| pub mod gsm; | ||||
| pub mod locker_mock_up; | ||||
| pub mod mandate; | ||||
| pub mod merchant_account; | ||||
|  | ||||
							
								
								
									
										100
									
								
								crates/diesel_models/src/query/gsm.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								crates/diesel_models/src/query/gsm.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,100 @@ | ||||
| use diesel::{associations::HasTable, BoolExpressionMethods, ExpressionMethods}; | ||||
| use error_stack::report; | ||||
|  | ||||
| use crate::{ | ||||
|     errors, gsm::*, query::generics, schema::gateway_status_map::dsl, PgPooledConn, StorageResult, | ||||
| }; | ||||
|  | ||||
| impl GatewayStatusMappingNew { | ||||
|     pub async fn insert(self, conn: &PgPooledConn) -> StorageResult<GatewayStatusMap> { | ||||
|         generics::generic_insert(conn, self).await | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl GatewayStatusMap { | ||||
|     pub async fn find( | ||||
|         conn: &PgPooledConn, | ||||
|         connector: String, | ||||
|         flow: String, | ||||
|         sub_flow: String, | ||||
|         code: String, | ||||
|         message: String, | ||||
|     ) -> StorageResult<Self> { | ||||
|         generics::generic_find_one::<<Self as HasTable>::Table, _, _>( | ||||
|             conn, | ||||
|             dsl::connector | ||||
|                 .eq(connector) | ||||
|                 .and(dsl::flow.eq(flow)) | ||||
|                 .and(dsl::sub_flow.eq(sub_flow)) | ||||
|                 .and(dsl::code.eq(code)) | ||||
|                 .and(dsl::message.eq(message)), | ||||
|         ) | ||||
|         .await | ||||
|     } | ||||
|  | ||||
|     pub async fn retrieve_decision( | ||||
|         conn: &PgPooledConn, | ||||
|         connector: String, | ||||
|         flow: String, | ||||
|         sub_flow: String, | ||||
|         code: String, | ||||
|         message: String, | ||||
|     ) -> StorageResult<String> { | ||||
|         Self::find(conn, connector, flow, sub_flow, code, message) | ||||
|             .await | ||||
|             .map(|item| item.decision) | ||||
|     } | ||||
|  | ||||
|     pub async fn update( | ||||
|         conn: &PgPooledConn, | ||||
|         connector: String, | ||||
|         flow: String, | ||||
|         sub_flow: String, | ||||
|         code: String, | ||||
|         message: String, | ||||
|         gsm: GatewayStatusMappingUpdate, | ||||
|     ) -> StorageResult<Self> { | ||||
|         generics::generic_update_with_results::< | ||||
|             <Self as HasTable>::Table, | ||||
|             GatewayStatusMapperUpdateInternal, | ||||
|             _, | ||||
|             _, | ||||
|         >( | ||||
|             conn, | ||||
|             dsl::connector | ||||
|                 .eq(connector) | ||||
|                 .and(dsl::flow.eq(flow)) | ||||
|                 .and(dsl::sub_flow.eq(sub_flow)) | ||||
|                 .and(dsl::code.eq(code)) | ||||
|                 .and(dsl::message.eq(message)), | ||||
|             gsm.into(), | ||||
|         ) | ||||
|         .await? | ||||
|         .first() | ||||
|         .cloned() | ||||
|         .ok_or_else(|| { | ||||
|             report!(errors::DatabaseError::NotFound) | ||||
|                 .attach_printable("Error while updating gsm entry") | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     pub async fn delete( | ||||
|         conn: &PgPooledConn, | ||||
|         connector: String, | ||||
|         flow: String, | ||||
|         sub_flow: String, | ||||
|         code: String, | ||||
|         message: String, | ||||
|     ) -> StorageResult<bool> { | ||||
|         generics::generic_delete::<<Self as HasTable>::Table, _>( | ||||
|             conn, | ||||
|             dsl::connector | ||||
|                 .eq(connector) | ||||
|                 .and(dsl::flow.eq(flow)) | ||||
|                 .and(dsl::sub_flow.eq(sub_flow)) | ||||
|                 .and(dsl::code.eq(code)) | ||||
|                 .and(dsl::message.eq(message)), | ||||
|         ) | ||||
|         .await | ||||
|     } | ||||
| } | ||||
| @ -332,6 +332,33 @@ diesel::table! { | ||||
|     } | ||||
| } | ||||
|  | ||||
| diesel::table! { | ||||
|     use diesel::sql_types::*; | ||||
|     use crate::enums::diesel_exports::*; | ||||
|  | ||||
|     gateway_status_map (connector, flow, sub_flow, code, message) { | ||||
|         #[max_length = 64] | ||||
|         connector -> Varchar, | ||||
|         #[max_length = 64] | ||||
|         flow -> Varchar, | ||||
|         #[max_length = 64] | ||||
|         sub_flow -> Varchar, | ||||
|         #[max_length = 255] | ||||
|         code -> Varchar, | ||||
|         #[max_length = 1024] | ||||
|         message -> Varchar, | ||||
|         #[max_length = 64] | ||||
|         status -> Varchar, | ||||
|         #[max_length = 64] | ||||
|         router_error -> Nullable<Varchar>, | ||||
|         #[max_length = 64] | ||||
|         decision -> Varchar, | ||||
|         created_at -> Timestamp, | ||||
|         last_modified -> Timestamp, | ||||
|         step_up_possible -> Bool, | ||||
|     } | ||||
| } | ||||
|  | ||||
| diesel::table! { | ||||
|     use diesel::sql_types::*; | ||||
|     use crate::enums::diesel_exports::*; | ||||
| @ -909,6 +936,7 @@ diesel::allow_tables_to_appear_in_same_query!( | ||||
|     events, | ||||
|     file_metadata, | ||||
|     fraud_check, | ||||
|     gateway_status_map, | ||||
|     locker_mock_up, | ||||
|     mandate, | ||||
|     merchant_account, | ||||
|  | ||||
| @ -12,6 +12,7 @@ pub mod ephemeral_key; | ||||
| pub mod events; | ||||
| pub mod file; | ||||
| pub mod fraud_check; | ||||
| pub mod gsm; | ||||
| pub mod locker_mock_up; | ||||
| pub mod mandate; | ||||
| pub mod merchant_account; | ||||
| @ -80,6 +81,7 @@ pub trait StorageInterface: | ||||
|     + business_profile::BusinessProfileInterface | ||||
|     + organization::OrganizationInterface | ||||
|     + routing_algorithm::RoutingAlgorithmInterface | ||||
|     + gsm::GsmInterface | ||||
|     + 'static | ||||
| { | ||||
|     fn get_scheduler_db(&self) -> Box<dyn scheduler::SchedulerInterface>; | ||||
|  | ||||
							
								
								
									
										180
									
								
								crates/router/src/db/gsm.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								crates/router/src/db/gsm.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,180 @@ | ||||
| use diesel_models::gsm as storage; | ||||
| use error_stack::IntoReport; | ||||
|  | ||||
| use super::MockDb; | ||||
| use crate::{ | ||||
|     connection, | ||||
|     core::errors::{self, CustomResult}, | ||||
|     services::Store, | ||||
| }; | ||||
|  | ||||
| #[async_trait::async_trait] | ||||
| pub trait GsmInterface { | ||||
|     async fn add_gsm_rule( | ||||
|         &self, | ||||
|         rule: storage::GatewayStatusMappingNew, | ||||
|     ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError>; | ||||
|     async fn find_gsm_decision( | ||||
|         &self, | ||||
|         connector: String, | ||||
|         flow: String, | ||||
|         sub_flow: String, | ||||
|         code: String, | ||||
|         message: String, | ||||
|     ) -> CustomResult<String, errors::StorageError>; | ||||
|     async fn find_gsm_rule( | ||||
|         &self, | ||||
|         connector: String, | ||||
|         flow: String, | ||||
|         sub_flow: String, | ||||
|         code: String, | ||||
|         message: String, | ||||
|     ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError>; | ||||
|     async fn update_gsm_rule( | ||||
|         &self, | ||||
|         connector: String, | ||||
|         flow: String, | ||||
|         sub_flow: String, | ||||
|         code: String, | ||||
|         message: String, | ||||
|         data: storage::GatewayStatusMappingUpdate, | ||||
|     ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError>; | ||||
|  | ||||
|     async fn delete_gsm_rule( | ||||
|         &self, | ||||
|         connector: String, | ||||
|         flow: String, | ||||
|         sub_flow: String, | ||||
|         code: String, | ||||
|         message: String, | ||||
|     ) -> CustomResult<bool, errors::StorageError>; | ||||
| } | ||||
|  | ||||
| #[async_trait::async_trait] | ||||
| impl GsmInterface for Store { | ||||
|     async fn add_gsm_rule( | ||||
|         &self, | ||||
|         rule: storage::GatewayStatusMappingNew, | ||||
|     ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError> { | ||||
|         let conn = connection::pg_connection_write(self).await?; | ||||
|         rule.insert(&conn).await.map_err(Into::into).into_report() | ||||
|     } | ||||
|  | ||||
|     async fn find_gsm_decision( | ||||
|         &self, | ||||
|         connector: String, | ||||
|         flow: String, | ||||
|         sub_flow: String, | ||||
|         code: String, | ||||
|         message: String, | ||||
|     ) -> CustomResult<String, errors::StorageError> { | ||||
|         let conn = connection::pg_connection_read(self).await?; | ||||
|         storage::GatewayStatusMap::retrieve_decision( | ||||
|             &conn, connector, flow, sub_flow, code, message, | ||||
|         ) | ||||
|         .await | ||||
|         .map_err(Into::into) | ||||
|         .into_report() | ||||
|     } | ||||
|  | ||||
|     async fn find_gsm_rule( | ||||
|         &self, | ||||
|         connector: String, | ||||
|         flow: String, | ||||
|         sub_flow: String, | ||||
|         code: String, | ||||
|         message: String, | ||||
|     ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError> { | ||||
|         let conn = connection::pg_connection_read(self).await?; | ||||
|         storage::GatewayStatusMap::find(&conn, connector, flow, sub_flow, code, message) | ||||
|             .await | ||||
|             .map_err(Into::into) | ||||
|             .into_report() | ||||
|     } | ||||
|  | ||||
|     async fn update_gsm_rule( | ||||
|         &self, | ||||
|         connector: String, | ||||
|         flow: String, | ||||
|         sub_flow: String, | ||||
|         code: String, | ||||
|         message: String, | ||||
|         data: storage::GatewayStatusMappingUpdate, | ||||
|     ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError> { | ||||
|         let conn = connection::pg_connection_write(self).await?; | ||||
|         storage::GatewayStatusMap::update(&conn, connector, flow, sub_flow, code, message, data) | ||||
|             .await | ||||
|             .map_err(Into::into) | ||||
|             .into_report() | ||||
|     } | ||||
|  | ||||
|     async fn delete_gsm_rule( | ||||
|         &self, | ||||
|         connector: String, | ||||
|         flow: String, | ||||
|         sub_flow: String, | ||||
|         code: String, | ||||
|         message: String, | ||||
|     ) -> CustomResult<bool, errors::StorageError> { | ||||
|         let conn = connection::pg_connection_write(self).await?; | ||||
|         storage::GatewayStatusMap::delete(&conn, connector, flow, sub_flow, code, message) | ||||
|             .await | ||||
|             .map_err(Into::into) | ||||
|             .into_report() | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[async_trait::async_trait] | ||||
| impl GsmInterface for MockDb { | ||||
|     async fn add_gsm_rule( | ||||
|         &self, | ||||
|         _rule: storage::GatewayStatusMappingNew, | ||||
|     ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError> { | ||||
|         Err(errors::StorageError::MockDbError)? | ||||
|     } | ||||
|  | ||||
|     async fn find_gsm_decision( | ||||
|         &self, | ||||
|         _connector: String, | ||||
|         _flow: String, | ||||
|         _sub_flow: String, | ||||
|         _code: String, | ||||
|         _message: String, | ||||
|     ) -> CustomResult<String, errors::StorageError> { | ||||
|         Err(errors::StorageError::MockDbError)? | ||||
|     } | ||||
|  | ||||
|     async fn find_gsm_rule( | ||||
|         &self, | ||||
|         _connector: String, | ||||
|         _flow: String, | ||||
|         _sub_flow: String, | ||||
|         _code: String, | ||||
|         _message: String, | ||||
|     ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError> { | ||||
|         Err(errors::StorageError::MockDbError)? | ||||
|     } | ||||
|  | ||||
|     async fn update_gsm_rule( | ||||
|         &self, | ||||
|         _connector: String, | ||||
|         _flow: String, | ||||
|         _sub_flow: String, | ||||
|         _code: String, | ||||
|         _message: String, | ||||
|         _data: storage::GatewayStatusMappingUpdate, | ||||
|     ) -> CustomResult<storage::GatewayStatusMap, errors::StorageError> { | ||||
|         Err(errors::StorageError::MockDbError)? | ||||
|     } | ||||
|  | ||||
|     async fn delete_gsm_rule( | ||||
|         &self, | ||||
|         _connector: String, | ||||
|         _flow: String, | ||||
|         _sub_flow: String, | ||||
|         _code: String, | ||||
|         _message: String, | ||||
|     ) -> CustomResult<bool, errors::StorageError> { | ||||
|         Err(errors::StorageError::MockDbError)? | ||||
|     } | ||||
| } | ||||
| @ -11,6 +11,7 @@ pub mod enums; | ||||
| pub mod ephemeral_key; | ||||
| pub mod events; | ||||
| pub mod file; | ||||
| pub mod gsm; | ||||
| #[cfg(feature = "kv_store")] | ||||
| pub mod kv; | ||||
| pub mod locker_mock_up; | ||||
| @ -41,10 +42,10 @@ pub use data_models::payments::{ | ||||
|  | ||||
| pub use self::{ | ||||
|     address::*, api_keys::*, capture::*, cards_info::*, configs::*, connector_response::*, | ||||
|     customers::*, dispute::*, ephemeral_key::*, events::*, file::*, locker_mock_up::*, mandate::*, | ||||
|     merchant_account::*, merchant_connector_account::*, merchant_key_store::*, payment_link::*, | ||||
|     payment_method::*, payout_attempt::*, payouts::*, process_tracker::*, refund::*, | ||||
|     reverse_lookup::*, routing_algorithm::*, | ||||
|     customers::*, dispute::*, ephemeral_key::*, events::*, file::*, gsm::*, locker_mock_up::*, | ||||
|     mandate::*, merchant_account::*, merchant_connector_account::*, merchant_key_store::*, | ||||
|     payment_link::*, payment_method::*, payout_attempt::*, payouts::*, process_tracker::*, | ||||
|     refund::*, reverse_lookup::*, routing_algorithm::*, | ||||
| }; | ||||
| use crate::types::api::routing; | ||||
|  | ||||
|  | ||||
							
								
								
									
										4
									
								
								crates/router/src/types/storage/gsm.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								crates/router/src/types/storage/gsm.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| pub use diesel_models::gsm::{ | ||||
|     GatewayStatusMap, GatewayStatusMapperUpdateInternal, GatewayStatusMappingNew, | ||||
|     GatewayStatusMappingUpdate, | ||||
| }; | ||||
							
								
								
									
										2
									
								
								migrations/2023-11-07-110139_add_gsm_table/down.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								migrations/2023-11-07-110139_add_gsm_table/down.sql
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| -- Tables | ||||
| DROP TABLE gateway_status_map; | ||||
							
								
								
									
										16
									
								
								migrations/2023-11-07-110139_add_gsm_table/up.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								migrations/2023-11-07-110139_add_gsm_table/up.sql
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| -- Your SQL goes here | ||||
| -- Tables | ||||
| CREATE TABLE IF NOT EXISTS gateway_status_map ( | ||||
|     connector VARCHAR(64) NOT NULL, | ||||
|     flow VARCHAR(64) NOT NULL, | ||||
|     sub_flow VARCHAR(64) NOT NULL, | ||||
|     code VARCHAR(255) NOT NULL, | ||||
|     message VARCHAR(1024), | ||||
|     status VARCHAR(64) NOT NULL, | ||||
|     router_error VARCHAR(64), | ||||
|     decision VARCHAR(64) NOT NULL, | ||||
|     created_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP, | ||||
|     last_modified TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP, | ||||
|     step_up_possible BOOLEAN NOT NULL DEFAULT FALSE, | ||||
|     PRIMARY KEY (connector, flow, sub_flow, code, message) | ||||
| ); | ||||
		Reference in New Issue
	
	Block a user