mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 01:27:31 +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;
|
pub mod file;
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub mod fraud_check;
|
pub mod fraud_check;
|
||||||
|
pub mod gsm;
|
||||||
#[cfg(feature = "kv_store")]
|
#[cfg(feature = "kv_store")]
|
||||||
pub mod kv;
|
pub mod kv;
|
||||||
pub mod locker_mock_up;
|
pub mod locker_mock_up;
|
||||||
|
|||||||
@ -11,6 +11,7 @@ pub mod events;
|
|||||||
pub mod file;
|
pub mod file;
|
||||||
pub mod fraud_check;
|
pub mod fraud_check;
|
||||||
pub mod generics;
|
pub mod generics;
|
||||||
|
pub mod gsm;
|
||||||
pub mod locker_mock_up;
|
pub mod locker_mock_up;
|
||||||
pub mod mandate;
|
pub mod mandate;
|
||||||
pub mod merchant_account;
|
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! {
|
diesel::table! {
|
||||||
use diesel::sql_types::*;
|
use diesel::sql_types::*;
|
||||||
use crate::enums::diesel_exports::*;
|
use crate::enums::diesel_exports::*;
|
||||||
@ -909,6 +936,7 @@ diesel::allow_tables_to_appear_in_same_query!(
|
|||||||
events,
|
events,
|
||||||
file_metadata,
|
file_metadata,
|
||||||
fraud_check,
|
fraud_check,
|
||||||
|
gateway_status_map,
|
||||||
locker_mock_up,
|
locker_mock_up,
|
||||||
mandate,
|
mandate,
|
||||||
merchant_account,
|
merchant_account,
|
||||||
|
|||||||
@ -12,6 +12,7 @@ pub mod ephemeral_key;
|
|||||||
pub mod events;
|
pub mod events;
|
||||||
pub mod file;
|
pub mod file;
|
||||||
pub mod fraud_check;
|
pub mod fraud_check;
|
||||||
|
pub mod gsm;
|
||||||
pub mod locker_mock_up;
|
pub mod locker_mock_up;
|
||||||
pub mod mandate;
|
pub mod mandate;
|
||||||
pub mod merchant_account;
|
pub mod merchant_account;
|
||||||
@ -80,6 +81,7 @@ pub trait StorageInterface:
|
|||||||
+ business_profile::BusinessProfileInterface
|
+ business_profile::BusinessProfileInterface
|
||||||
+ organization::OrganizationInterface
|
+ organization::OrganizationInterface
|
||||||
+ routing_algorithm::RoutingAlgorithmInterface
|
+ routing_algorithm::RoutingAlgorithmInterface
|
||||||
|
+ gsm::GsmInterface
|
||||||
+ 'static
|
+ 'static
|
||||||
{
|
{
|
||||||
fn get_scheduler_db(&self) -> Box<dyn scheduler::SchedulerInterface>;
|
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 ephemeral_key;
|
||||||
pub mod events;
|
pub mod events;
|
||||||
pub mod file;
|
pub mod file;
|
||||||
|
pub mod gsm;
|
||||||
#[cfg(feature = "kv_store")]
|
#[cfg(feature = "kv_store")]
|
||||||
pub mod kv;
|
pub mod kv;
|
||||||
pub mod locker_mock_up;
|
pub mod locker_mock_up;
|
||||||
@ -41,10 +42,10 @@ pub use data_models::payments::{
|
|||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
address::*, api_keys::*, capture::*, cards_info::*, configs::*, connector_response::*,
|
address::*, api_keys::*, capture::*, cards_info::*, configs::*, connector_response::*,
|
||||||
customers::*, dispute::*, ephemeral_key::*, events::*, file::*, locker_mock_up::*, mandate::*,
|
customers::*, dispute::*, ephemeral_key::*, events::*, file::*, gsm::*, locker_mock_up::*,
|
||||||
merchant_account::*, merchant_connector_account::*, merchant_key_store::*, payment_link::*,
|
mandate::*, merchant_account::*, merchant_connector_account::*, merchant_key_store::*,
|
||||||
payment_method::*, payout_attempt::*, payouts::*, process_tracker::*, refund::*,
|
payment_link::*, payment_method::*, payout_attempt::*, payouts::*, process_tracker::*,
|
||||||
reverse_lookup::*, routing_algorithm::*,
|
refund::*, reverse_lookup::*, routing_algorithm::*,
|
||||||
};
|
};
|
||||||
use crate::types::api::routing;
|
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