mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 09:07:09 +08:00
feat(router): add gateway_status_map interface (#2804)
This commit is contained in:
committed by
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