Nice db split
This commit is contained in:
parent
ca88ce1268
commit
37241b2357
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3279,6 +3279,7 @@ name = "migration"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-std",
|
"async-std",
|
||||||
|
"async-trait",
|
||||||
"clap 3.2.25",
|
"clap 3.2.25",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
"sea-orm-migration",
|
"sea-orm-migration",
|
||||||
|
@ -14,6 +14,7 @@ clap = { version = "3.2.25", features = ['derive'] }
|
|||||||
tracing = { version = "0.1.37" }
|
tracing = { version = "0.1.37" }
|
||||||
tracing-subscriber = { version = "0.3.17", features = ['env-filter'] }
|
tracing-subscriber = { version = "0.3.17", features = ['env-filter'] }
|
||||||
dotenv = { version = "0.15.0" }
|
dotenv = { version = "0.15.0" }
|
||||||
|
async-trait = { version = "0.1.68" }
|
||||||
|
|
||||||
[dependencies.sea-orm-migration]
|
[dependencies.sea-orm-migration]
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
|
22
migration/src/carts/m20230603_102634_types.rs
Normal file
22
migration/src/carts/m20230603_102634_types.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use sea_orm::Iterable;
|
||||||
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
|
use crate::extension::postgres::Type;
|
||||||
|
use crate::types::*;
|
||||||
|
use crate::{create_type, drop_type};
|
||||||
|
|
||||||
|
#[derive(DeriveMigrationName)]
|
||||||
|
pub struct Migration;
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl MigrationTrait for Migration {
|
||||||
|
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
create_type!(manager, CartType);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
drop_type!(manager, CartType);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
104
migration/src/carts/m20230603_120814_carts.rs
Normal file
104
migration/src/carts/m20230603_120814_carts.rs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
use sea_orm_migration::prelude::*;
|
||||||
|
use sea_query::expr::SimpleExpr;
|
||||||
|
|
||||||
|
/// ```sql
|
||||||
|
/// id character varying NOT NULL,
|
||||||
|
/// email character varying,
|
||||||
|
/// billing_address_id character varying,
|
||||||
|
/// shipping_address_id character varying,
|
||||||
|
/// region_id character varying NOT NULL,
|
||||||
|
/// customer_id character varying,
|
||||||
|
/// payment_id character varying,
|
||||||
|
/// type public.cart_types DEFAULT 'default'::public.cart_types NOT NULL,
|
||||||
|
/// completed_at timestamp with time zone,
|
||||||
|
/// created_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
/// updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
/// deleted_at timestamp with time zone,
|
||||||
|
/// metadata jsonb,
|
||||||
|
/// idempotency_key character varying,
|
||||||
|
/// context jsonb,
|
||||||
|
/// payment_authorized_at timestamp with time zone,
|
||||||
|
/// sales_channel_id character varying
|
||||||
|
/// ```
|
||||||
|
#[derive(DeriveMigrationName)]
|
||||||
|
pub struct Migration;
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl MigrationTrait for Migration {
|
||||||
|
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(Cart::Carts)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Cart::Id)
|
||||||
|
.uuid()
|
||||||
|
.not_null()
|
||||||
|
.default(SimpleExpr::Custom("public.uuid_generate_v4()".into()))
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Cart::Email).string())
|
||||||
|
.col(ColumnDef::new(Cart::BillingAddressId).uuid())
|
||||||
|
.col(ColumnDef::new(Cart::ShippingAddressId).uuid())
|
||||||
|
.col(ColumnDef::new(Cart::RegionId).uuid().not_null())
|
||||||
|
.col(ColumnDef::new(Cart::CustomerId).uuid())
|
||||||
|
.col(ColumnDef::new(Cart::PaymentId).uuid())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Cart::CartType)
|
||||||
|
.string()
|
||||||
|
.default(SimpleExpr::Custom("'default'::public.cart_types".into()))
|
||||||
|
.not_null(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Cart::CompletedAt).timestamp())
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Cart::CreatedAt)
|
||||||
|
.timestamp()
|
||||||
|
.default(SimpleExpr::Custom("now()".into()))
|
||||||
|
.not_null(),
|
||||||
|
)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Cart::UpdatedAt)
|
||||||
|
.timestamp()
|
||||||
|
.default(SimpleExpr::Custom("now()".into()))
|
||||||
|
.not_null(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Cart::DeletedAt).timestamp())
|
||||||
|
.col(ColumnDef::new(Cart::Metadata).json_binary())
|
||||||
|
.col(ColumnDef::new(Cart::IdempotencyKey).uuid())
|
||||||
|
.col(ColumnDef::new(Cart::Context).json_binary())
|
||||||
|
.col(ColumnDef::new(Cart::PaymentAuthorizedAt).timestamp())
|
||||||
|
.col(ColumnDef::new(Cart::SalesChannelId).uuid())
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(Cart::Carts).to_owned())
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Iden)]
|
||||||
|
enum Cart {
|
||||||
|
Carts,
|
||||||
|
Id,
|
||||||
|
Email,
|
||||||
|
BillingAddressId,
|
||||||
|
ShippingAddressId,
|
||||||
|
RegionId,
|
||||||
|
CustomerId,
|
||||||
|
PaymentId,
|
||||||
|
CartType,
|
||||||
|
CompletedAt,
|
||||||
|
CreatedAt,
|
||||||
|
UpdatedAt,
|
||||||
|
DeletedAt,
|
||||||
|
Metadata,
|
||||||
|
IdempotencyKey,
|
||||||
|
Context,
|
||||||
|
PaymentAuthorizedAt,
|
||||||
|
SalesChannelId,
|
||||||
|
}
|
16
migration/src/carts/mod.rs
Normal file
16
migration/src/carts/mod.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
use sea_orm_migration::{MigrationTrait, MigratorTrait};
|
||||||
|
|
||||||
|
mod m20230603_102634_types;
|
||||||
|
mod m20230603_120814_carts;
|
||||||
|
|
||||||
|
pub struct CartsMigrator;
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl MigratorTrait for CartsMigrator {
|
||||||
|
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
|
||||||
|
vec![
|
||||||
|
Box::new(m20230603_102634_types::Migration),
|
||||||
|
Box::new(m20230603_120814_carts::Migration),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -1,23 +1,12 @@
|
|||||||
use sea_orm_migration::prelude::*;
|
use sea_orm_migration::prelude::*;
|
||||||
use sea_orm_migration::sea_orm::Statement;
|
|
||||||
use sea_query::expr::SimpleExpr;
|
use sea_query::expr::SimpleExpr;
|
||||||
|
|
||||||
use crate::sea_orm::DatabaseBackend;
|
|
||||||
|
|
||||||
#[derive(DeriveMigrationName)]
|
#[derive(DeriveMigrationName)]
|
||||||
pub struct Migration;
|
pub struct Migration;
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl MigrationTrait for Migration {
|
impl MigrationTrait for Migration {
|
||||||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
manager
|
|
||||||
.get_connection()
|
|
||||||
.execute(Statement::from_string(
|
|
||||||
DatabaseBackend::Postgres,
|
|
||||||
"CREATE EXTENSION \"uuid-ossp\"".to_string(),
|
|
||||||
))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
manager
|
manager
|
||||||
.create_table(
|
.create_table(
|
||||||
Table::create()
|
Table::create()
|
||||||
@ -41,7 +30,7 @@ impl MigrationTrait for Migration {
|
|||||||
ColumnDef::new(BatchJob::Id)
|
ColumnDef::new(BatchJob::Id)
|
||||||
.uuid()
|
.uuid()
|
||||||
.not_null()
|
.not_null()
|
||||||
.default(SimpleExpr::Custom("uuid_generate_v4()".into()))
|
.default(SimpleExpr::Custom("public.uuid_generate_v4()".into()))
|
||||||
.primary_key(),
|
.primary_key(),
|
||||||
)
|
)
|
||||||
.col(ColumnDef::new(BatchJob::BatchType).string().not_null())
|
.col(ColumnDef::new(BatchJob::BatchType).string().not_null())
|
13
migration/src/jobs/mod.rs
Normal file
13
migration/src/jobs/mod.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
use sea_orm_migration::{MigrationTrait, MigratorTrait};
|
||||||
|
|
||||||
|
pub mod m20230603_120814_batch_jobs;
|
||||||
|
|
||||||
|
pub struct JobsMigrator;
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl MigratorTrait for JobsMigrator {
|
||||||
|
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
|
||||||
|
eprintln!("JobsMigrator");
|
||||||
|
vec![Box::new(m20230603_120814_batch_jobs::Migration)]
|
||||||
|
}
|
||||||
|
}
|
@ -1,30 +1,7 @@
|
|||||||
pub use sea_orm_migration::prelude::*;
|
pub use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
mod m20230603_102630_schema;
|
pub mod carts;
|
||||||
mod m20230603_102634_types;
|
pub mod jobs;
|
||||||
mod m20230603_120814_addresses;
|
pub mod public;
|
||||||
mod m20230603_120814_jobs;
|
|
||||||
pub mod schema_list;
|
pub mod schema_list;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
||||||
pub struct PublicMigrator;
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
impl MigratorTrait for PublicMigrator {
|
|
||||||
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
|
|
||||||
vec![
|
|
||||||
Box::new(m20230603_102630_schema::Migration),
|
|
||||||
Box::new(m20230603_102634_types::Migration),
|
|
||||||
Box::new(m20230603_120814_addresses::Migration),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct JobsMigrator;
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
impl MigratorTrait for JobsMigrator {
|
|
||||||
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
|
|
||||||
vec![Box::new(m20230603_120814_jobs::Migration)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -20,14 +20,27 @@ async fn main() {
|
|||||||
|
|
||||||
init_logger(cli.verbose);
|
init_logger(cli.verbose);
|
||||||
|
|
||||||
cli.database_schema = Some(PostgreSQLSchema::Public.as_str().into());
|
run_cli(
|
||||||
run_cli(&cli, migration::PublicMigrator).await;
|
&mut cli,
|
||||||
|
PostgreSQLSchema::Public,
|
||||||
cli.database_schema = Some(PostgreSQLSchema::Jobs.as_str().into());
|
migration::public::PublicMigrator,
|
||||||
run_cli(&cli, migration::JobsMigrator).await;
|
)
|
||||||
|
.await;
|
||||||
|
run_cli(
|
||||||
|
&mut cli,
|
||||||
|
PostgreSQLSchema::Jobs,
|
||||||
|
migration::jobs::JobsMigrator,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
run_cli(
|
||||||
|
&mut cli,
|
||||||
|
PostgreSQLSchema::Carts,
|
||||||
|
migration::carts::CartsMigrator,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run_cli<M>(cli: &Cli, migrator: M)
|
pub async fn run_cli<M>(cli: &mut Cli, schema: PostgreSQLSchema, migrator: M)
|
||||||
where
|
where
|
||||||
M: MigratorTrait,
|
M: MigratorTrait,
|
||||||
{
|
{
|
||||||
@ -35,22 +48,25 @@ where
|
|||||||
.database_url
|
.database_url
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("Environment variable 'DATABASE_URL' not set");
|
.expect("Environment variable 'DATABASE_URL' not set");
|
||||||
let schema = cli
|
|
||||||
.database_schema
|
|
||||||
.as_ref()
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or_else(|| "public".to_owned());
|
|
||||||
|
|
||||||
|
let schema = schema.as_str().to_string();
|
||||||
let connect_options = ConnectOptions::new(url.clone())
|
let connect_options = ConnectOptions::new(url.clone())
|
||||||
.set_schema_search_path(schema)
|
.set_schema_search_path(schema.clone())
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let db = &Database::connect(connect_options)
|
let db = Database::connect(connect_options)
|
||||||
.await
|
.await
|
||||||
.expect("Fail to acquire database connection");
|
.expect("Fail to acquire database connection");
|
||||||
|
|
||||||
run_migrate(migrator, db, cli.command.clone())
|
db.execute_unprepared(&format!("SET search_path = '{}'", schema))
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(handle_error);
|
.unwrap();
|
||||||
|
|
||||||
|
let res = run_migrate(migrator, &db, cli.command.clone()).await;
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
res.unwrap();
|
||||||
|
} else {
|
||||||
|
res.unwrap_or_else(handle_error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run_migrate<M>(
|
pub async fn run_migrate<M>(
|
||||||
@ -83,7 +99,7 @@ where
|
|||||||
fn init_logger(verbose: bool) {
|
fn init_logger(verbose: bool) {
|
||||||
let filter = match verbose {
|
let filter = match verbose {
|
||||||
true => "debug",
|
true => "debug",
|
||||||
false => "sea_orm_migration=info",
|
false => "sea_orm_migration=trace",
|
||||||
};
|
};
|
||||||
|
|
||||||
let filter_layer = EnvFilter::try_new(filter).unwrap();
|
let filter_layer = EnvFilter::try_new(filter).unwrap();
|
||||||
@ -96,8 +112,8 @@ fn init_logger(verbose: bool) {
|
|||||||
.init()
|
.init()
|
||||||
} else {
|
} else {
|
||||||
let fmt_layer = tracing_subscriber::fmt::layer()
|
let fmt_layer = tracing_subscriber::fmt::layer()
|
||||||
.with_target(false)
|
.with_target(true)
|
||||||
.with_level(false)
|
.with_level(true)
|
||||||
.without_time();
|
.without_time();
|
||||||
tracing_subscriber::registry()
|
tracing_subscriber::registry()
|
||||||
.with(filter_layer)
|
.with(filter_layer)
|
||||||
@ -120,18 +136,6 @@ pub struct Cli {
|
|||||||
#[clap(action, short = 'v', long, global = true, help = "Show debug messages")]
|
#[clap(action, short = 'v', long, global = true, help = "Show debug messages")]
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
|
|
||||||
#[clap(
|
|
||||||
value_parser,
|
|
||||||
global = true,
|
|
||||||
short = 's',
|
|
||||||
long,
|
|
||||||
env = "DATABASE_SCHEMA",
|
|
||||||
long_help = "Database schema\n \
|
|
||||||
- For MySQL and SQLite, this argument is ignored.\n \
|
|
||||||
- For PostgreSQL, this argument is optional with default value 'public'.\n"
|
|
||||||
)]
|
|
||||||
database_schema: Option<String>,
|
|
||||||
|
|
||||||
#[clap(
|
#[clap(
|
||||||
value_parser,
|
value_parser,
|
||||||
global = true,
|
global = true,
|
||||||
@ -173,18 +177,6 @@ you should provide the directory of that submodule.",
|
|||||||
)]
|
)]
|
||||||
migration_dir: String,
|
migration_dir: String,
|
||||||
|
|
||||||
#[clap(
|
|
||||||
value_parser,
|
|
||||||
global = true,
|
|
||||||
short = 's',
|
|
||||||
long,
|
|
||||||
env = "DATABASE_SCHEMA",
|
|
||||||
long_help = "Database schema\n \
|
|
||||||
- For MySQL and SQLite, this argument is ignored.\n \
|
|
||||||
- For PostgreSQL, this argument is optional with default value 'public'.\n"
|
|
||||||
)]
|
|
||||||
database_schema: Option<String>,
|
|
||||||
|
|
||||||
#[clap(
|
#[clap(
|
||||||
value_parser,
|
value_parser,
|
||||||
global = true,
|
global = true,
|
||||||
|
@ -3,32 +3,7 @@ use sea_orm_migration::prelude::*;
|
|||||||
|
|
||||||
use crate::extension::postgres::Type;
|
use crate::extension::postgres::Type;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
use crate::{create_type, drop_type};
|
||||||
macro_rules! create_type {
|
|
||||||
($manager: ident, $ty: ident) => {
|
|
||||||
$manager
|
|
||||||
.create_type(
|
|
||||||
Type::create()
|
|
||||||
.as_enum($ty::iter().next().unwrap())
|
|
||||||
.values($ty::iter().skip(1))
|
|
||||||
.to_owned(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
macro_rules! drop_type {
|
|
||||||
($manager: ident, $ty: ident) => {
|
|
||||||
$manager
|
|
||||||
.drop_type(
|
|
||||||
Type::drop()
|
|
||||||
.if_exists()
|
|
||||||
.cascade()
|
|
||||||
.name($ty::iter().next().unwrap())
|
|
||||||
.to_owned(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(DeriveMigrationName)]
|
#[derive(DeriveMigrationName)]
|
||||||
pub struct Migration;
|
pub struct Migration;
|
19
migration/src/public/mod.rs
Normal file
19
migration/src/public/mod.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use sea_orm_migration::{MigrationTrait, MigratorTrait};
|
||||||
|
|
||||||
|
mod m20230603_102630_schema;
|
||||||
|
mod m20230603_102634_types;
|
||||||
|
mod m20230603_120814_addresses;
|
||||||
|
|
||||||
|
pub struct PublicMigrator;
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl MigratorTrait for PublicMigrator {
|
||||||
|
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
|
||||||
|
eprintln!("PublicMigrator");
|
||||||
|
vec![
|
||||||
|
Box::new(m20230603_102630_schema::Migration),
|
||||||
|
Box::new(m20230603_102634_types::Migration),
|
||||||
|
Box::new(m20230603_120814_addresses::Migration),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@ use sea_orm_migration::prelude::*;
|
|||||||
pub enum PostgreSQLSchema {
|
pub enum PostgreSQLSchema {
|
||||||
Public,
|
Public,
|
||||||
Jobs,
|
Jobs,
|
||||||
|
Carts,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PostgreSQLSchema {
|
impl PostgreSQLSchema {
|
||||||
@ -13,6 +14,7 @@ impl PostgreSQLSchema {
|
|||||||
match self {
|
match self {
|
||||||
PostgreSQLSchema::Public => "public",
|
PostgreSQLSchema::Public => "public",
|
||||||
PostgreSQLSchema::Jobs => "jobs",
|
PostgreSQLSchema::Jobs => "jobs",
|
||||||
|
PostgreSQLSchema::Carts => "carts",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,34 @@
|
|||||||
use sea_orm::EnumIter;
|
use sea_orm::EnumIter;
|
||||||
use sea_orm_migration::prelude::*;
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! create_type {
|
||||||
|
($manager: ident, $ty: ident) => {
|
||||||
|
$manager
|
||||||
|
.create_type(
|
||||||
|
Type::create()
|
||||||
|
.as_enum($ty::iter().next().unwrap())
|
||||||
|
.values($ty::iter().skip(1))
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! drop_type {
|
||||||
|
($manager: ident, $ty: ident) => {
|
||||||
|
$manager
|
||||||
|
.drop_type(
|
||||||
|
Type::drop()
|
||||||
|
.if_exists()
|
||||||
|
.cascade()
|
||||||
|
.name($ty::iter().next().unwrap())
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Iden, EnumIter)]
|
#[derive(Iden, EnumIter)]
|
||||||
pub enum PaymentCollectionStatus {
|
pub enum PaymentCollectionStatus {
|
||||||
PaymentCollectionStatuses,
|
PaymentCollectionStatuses,
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user