Compare commits

..

79 Commits

Author SHA1 Message Date
86998f183d bug fixed 2022-09-21 14:38:13 +00:00
c3b1ad2023 member_balance is added 2022-09-16 16:44:45 +00:00
aa44d6aab1 version up 2022-09-16 10:34:43 +00:00
4b3ad14674 bug fixed 2022-09-07 04:15:12 +00:00
ad97b8b550 methods are modified 2022-09-07 04:08:37 +00:00
17e993955c version up 2022-09-06 12:36:04 +00:00
654d98aa13 model is modified 2022-09-05 14:41:20 +00:00
b142831820 bug fixed 2022-09-05 13:39:30 +00:00
3a203ad2db bug fixed 2022-09-05 13:01:44 +00:00
496c22af81 bug fixed 2022-09-05 11:50:51 +00:00
ccc3e0c9f1 bug fixed 2022-09-05 08:46:06 +00:00
dfc328b636 model is modified 2022-09-05 08:06:17 +00:00
dc10f5b8c4 bug fixed 2022-09-01 17:57:01 +00:00
d7ddfe5c46 total_count is added 2022-09-01 17:26:54 +00:00
ee98a22899 bug fixed 2022-09-01 16:21:40 +00:00
f828b707a9 model is modified 2022-09-01 09:44:16 +00:00
33b4baccf5 multiple id search is added 2022-09-01 03:46:02 +00:00
67ee99ab60 pagination is added 2022-08-31 14:37:03 +00:00
20c4490eec bug fixed 2022-08-31 14:12:27 +00:00
72bd1ffad8 model is modified 2022-08-31 13:39:40 +00:00
62b501d6bb betting is added 2022-08-31 08:56:37 +00:00
6edcc2d615 synchronization buf fixed 2022-08-31 02:41:53 +00:00
0b16750e01 bug fixed 2022-08-30 15:41:49 +00:00
0ec47aba30 betting history is added 2022-08-30 15:13:29 +00:00
ca75319f20 bug fixed 2022-08-30 09:14:07 +00:00
e9e4a148fa version up 2022-08-30 08:47:07 +00:00
605daab740 data type of money is changed 2022-08-30 08:30:06 +00:00
bcf0c819ad get_game_url is added 2022-08-29 09:34:15 +00:00
f9f245f2a2 bug fixed 2022-08-29 05:53:32 +00:00
4c785f2542 synchronization of member is modified 2022-08-29 05:45:20 +00:00
3ad73b26d3 refactoring 2022-08-29 04:14:38 +00:00
cd36f9eada refactoring 2022-08-29 04:01:16 +00:00
c4d8c03541 checking for id duplication is added 2022-08-29 03:02:37 +00:00
d89d93c9d0 bug fixed 2022-08-28 16:44:01 +00:00
0460aca0d3 bug fixed 2022-08-28 16:33:15 +00:00
ee76ced214 bug fixed 2022-08-28 15:06:53 +00:00
4637972b10 events are added 2022-08-28 14:59:35 +00:00
a1210b7881 version up 2022-08-28 03:19:19 +00:00
d01a9d2ea4 refactoring 2022-08-27 07:29:59 +00:00
93569bc247 version up 2022-08-24 07:12:43 +00:00
57be0b3a6b version up 2022-08-24 06:44:15 +00:00
74e28dcb95 url of api is changed 2022-08-22 12:34:44 +00:00
ec834d8e8e version up 2022-08-22 08:38:58 +00:00
0ba303a454 version up 2022-08-22 07:33:00 +00:00
e55adae3dc refactoring 2022-08-22 02:07:51 +00:00
40e687c5d9 refactoring 2022-08-20 22:33:05 +09:00
60eef0a1a2 openssl 2022-08-20 13:17:09 +00:00
7fd0d9024f version up 2022-08-20 13:02:06 +00:00
7adc6da480 refactoring 2022-08-20 12:22:43 +00:00
7b207909c7 refactoring 2022-08-20 08:58:56 +00:00
51d3e6648f api refactoring 2022-08-20 06:17:17 +00:00
9d0f9f1f34 api is changed 2022-08-19 10:14:06 +00:00
e87060a940 scheduler is changed 2022-08-19 08:59:48 +00:00
a26d5bb6bc development server is changed 2022-08-19 08:03:45 +00:00
bbced41e62 version up 2022-08-19 07:51:07 +00:00
b90b54ba2d game api is added 2022-08-19 07:22:49 +00:00
7502f066fc version up 2022-08-19 06:18:09 +00:00
61bab7ef6a event handler of member is added 2022-08-19 03:20:45 +00:00
0142b2ead3 field name of api is changed 2022-08-19 00:09:33 +00:00
2584bf8a55 bug fixed 2022-08-18 23:35:24 +00:00
e1cf3ebd54 bug fixed 2022-08-18 22:54:20 +00:00
6151ddf478 bug fixed 2022-08-18 22:46:26 +00:00
e7bc00c4c6 implemented 2022-08-18 22:35:22 +00:00
ea2664577a trigger is modified 2022-08-18 07:23:28 +00:00
64364946cc version up 2022-08-18 07:06:22 +00:00
4f6a445617 bug fixed 2022-08-18 06:02:23 +00:00
21436b69a7 types of data are changed 2022-08-18 05:57:23 +00:00
30555e9773 type of data is changed 2022-08-18 05:36:36 +00:00
6b9b7e6b24 implemented 2022-08-18 04:27:11 +00:00
02fe71a486 version up 2022-08-18 04:02:24 +00:00
72f3d63eb5 bug fixed 2022-08-18 02:54:13 +00:00
b2c439de7c bug fixed 2022-08-18 02:48:35 +00:00
0db6f75d61 implemented 2022-08-17 17:45:00 +00:00
88fc45b7c8 implemented 2022-08-16 17:00:26 +00:00
ee705fe250 bug fixed 2022-08-16 10:49:18 +09:00
b867964d65 configuration of devcontainer is changed 2022-08-05 07:30:21 +00:00
918183c190 bug fixed 2022-08-05 04:43:03 +00:00
8e182c0a55 repositories are added 2022-08-05 04:39:20 +00:00
273bbd69fc initialized 2022-08-05 04:23:17 +00:00
124 changed files with 8638 additions and 0 deletions

11
.devcontainer/Dockerfile Normal file
View File

@ -0,0 +1,11 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.245.0/containers/debian/.devcontainer/base.Dockerfile
# [Choice] Debian version (use bullseye on local arm64/Apple Silicon): bullseye, buster
ARG VARIANT="buster"
FROM mcr.microsoft.com/vscode/devcontainers/base:0-${VARIANT}
# ** [Optional] Uncomment this section to install additional packages. **
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends libpq-dev

View File

@ -0,0 +1,66 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.0/containers/ubuntu
{
"name": "beteran-api-kgon-server-service",
"build": {
"dockerfile": "Dockerfile",
"args": {
// Use the VARIANT arg to pick a Debian OS version: buster, bullseye
// Use bullseye when on local on arm64/Apple Silicon.
"VARIANT": "bullseye"
}
},
"runArgs": [
"--cap-add=SYS_PTRACE",
"--security-opt",
"seccomp=unconfined"
],
// Use this environment variable if you need to bind mount your local source code into a new container.
"remoteEnv": {
"LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}"
},
// Configure tool-specific properties.
"customizations": {
// Configure properties specific to VS Code.
"vscode": {
// Set *default* container specific settings.json values on container create.
"settings": {
"lldb.verboseLogging": true,
"lldb.executable": "/usr/bin/lldb",
// VS Code don't watch files under ./target
"files.watcherExclude": {
"**/.git/objects/**": true,
"**/.git/subtree-cache/**": true,
"**/target/**": true
},
"rust-analyzer.checkOnSave.command": "clippy",
"editor.tabSize": 2,
"editor.insertSpaces": true,
"editor.formatOnSave": true
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"donjayamanne.githistory",
"eamodio.gitlens",
"mhutchie.git-graph",
"ms-azuretools.vscode-docker",
"mutantdino.resourcemonitor",
"rust-lang.rust-analyzer",
"serayuzgur.crates",
"tamasfe.even-better-toml",
"vadimcn.vscode-lldb"
]
}
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "uname -a",
"postCreateCommand": "bash ./.devcontainer/scripts/postCreateCommand.sh",
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode",
"features": {
"git": "latest",
"rust": "latest"
}
}

View File

@ -0,0 +1,5 @@
[toolchain]
channel = "stable"
profile = "minimal"
components = ["clippy", "rustfmt"]
targets = []

View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -e

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
.DS_Store
/build
# Added by cargo
/target
Cargo.lock

75
.rustfmt.toml Normal file
View File

@ -0,0 +1,75 @@
# https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=
array_width = 60
attr_fn_like_width = 70
binop_separator = "Front" # "Front", "Back"
blank_lines_lower_bound = 0
blank_lines_upper_bound = 1
brace_style = "SameLineWhere" #"AlwaysNextLine", "PreferSameLine", "SameLineWhere"
chain_width = 60
color = "Auto" #"Auto", "Always", "Never"
combine_control_expr = true # true, false
comment_width = 80
condense_wildcard_suffixes = false # true, false
control_brace_style = "AlwaysSameLine" # "AlwaysNextLine", "AlwaysSameLine", "ClosingNextLine"
disable_all_formatting = false # true, false
edition = "2015" # "2015", "2018", "2021"
empty_item_single_line = true # true, false
enum_discrim_align_threshold = 0
error_on_line_overflow = false # true, false
error_on_unformatted = false # true, false
fn_args_layout = "Tall" # "Compressed", "Tall", "Vertical"
fn_call_width = 60
fn_single_line = false # true, false
force_explicit_abi = true # true, false
force_multiline_blocks = false # true, false
format_code_in_doc_comments = false # true, false
format_generated_files = false # true, false
format_macro_matchers = false # true, false
format_macro_bodies = true # true, false
format_strings = false # true, false
group_imports = "Preserve" # "Preserve", "StdExternalCrate"
hard_tabs = false # true, false
hex_literal_case = "Preserve" # "Upper", "Lower"
hide_parse_errors = false # true, false
ignore = []
imports_indent = "Block" # "Block", "Visual"
imports_layout = "Mixed" # "Horizontal", "HorizontalVertical", "Mixed", "Vertical"
indent_style = "Block" # "Block", "Visual"
inline_attribute_width = 0
license_template_path = ""
match_arm_blocks = true # true, false
match_arm_leading_pipes = "Never" # "Always", "Never", "Preserve"
match_block_trailing_comma = false # true, false
max_width = 100
merge_derives = true # true, false
imports_granularity = "Preserve" # "Preserve", "Crate", "Module", "Item", "One"
merge_imports = false # true, false
newline_style = "Auto" # "Auto", "Native", "Unix", "Windows"
normalize_comments = false # true, false
normalize_doc_attributes = false # true, false
overflow_delimited_expr = false # true, false
remove_nested_parens = true # true, false
reorder_impl_items = false # true, false
reorder_imports = true # true, false
reorder_modules = true # true, false
report_fixme = "Never" # "Always", "Unnumbered", "Never"
report_todo = "Never" # "Always", "Unnumbered", "Never"
skip_children = false # true, false
single_line_if_else_max_width = 50
space_after_colon = true # true, false
space_before_colon = false # true, false
spaces_around_ranges = false # true, false
struct_field_align_threshold = 0
struct_lit_single_line = true # true, false
struct_lit_width = 18
struct_variant_width = 35
tab_spaces = 2
trailing_comma = "Vertical" # "Always", "Never", "Vertical"
trailing_semicolon = true # true, false
type_punctuation_density = "Wide" # "Compressed", "Wide"
unstable_features = false # true, false
use_field_init_shorthand = false # true, false
use_small_heuristics = "Default" # "Default", "Off", "Max"
use_try_shorthand = false # true, false
where_single_line = false # true, false
wrap_comments = false # true, false

61
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,61 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug executable 'beteran-api-kgon-server-service'",
"cargo": {
"args": [
"build",
"--bin=beteran-api-kgon-server-service",
"--package=beteran-api-kgon-server-service"
],
"filter": {
"name": "beteran-api-kgon-server-service",
"kind": "bin"
}
},
"env": {
"URL_DATABASE": "postgresql://beteran:qwer5795QWER@192.168.50.205:25432/beteran",
"URL_BROKER": "nats://192.168.50.205:4222",
"QUEUE_BROKER": "bet.beteran",
"K_URL": "https://dev-mw.kgonapi.com",
"K_USERNAME": "turbo78",
"K_SECRET": "561b6f4d6e4c5f1b8a3473c43c3caa84",
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in executable 'beteran-api-kgon-server-service'",
"cargo": {
"args": [
"test",
"--no-run",
"--bin=beteran-api-kgon-server-service",
"--package=beteran-api-kgon-server-service"
],
"filter": {
"name": "beteran-api-kgon-server-service",
"kind": "bin"
}
},
"env": {
"URL_DATABASE": "postgresql://beteran:qwer5795QWER@192.168.50.205:25432/beteran",
"URL_BROKER": "nats://192.168.50.205:4222",
"QUEUE_BROKER": "bet.beteran",
"K_URL": "https://dev-mw.kgonapi.com",
"K_USERNAME": "turbo78",
"K_SECRET": "561b6f4d6e4c5f1b8a3473c43c3caa84",
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}

42
Cargo.toml Normal file
View File

@ -0,0 +1,42 @@
[package]
name = "beteran-api-kgon-server-service"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]
name = "beteran-api-kgon-server-service"
path = "./src/main.rs"
[dependencies]
chrono = { version = "0" }
diesel = { version = "1", features = [
"chrono",
"r2d2",
"uuidv07",
"postgres",
"serde_json",
"64-column-tables",
] }
diesel_migrations = { version = "1" }
diesel-derive-enum = { version = "1", features = ["postgres"] }
futures = { version = "0", default-features = false, features = [
"async-await",
] }
nats = { version = "0" }
once_cell = { version = "1" }
openssl = { version = "0", features = ["vendored"] }
prost = { version = "0" }
reqwest = { version = "0", features = ["json"] }
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1", features = ["raw_value"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
tokio-cron-scheduler = { version = "0" }
uuid = { version = "0", features = ["serde", "v4", "v5"] }
beteran-protobuf-rust = { git = "https://gitlab.loafle.net/bet/beteran-protobuf-rust.git", tag = "v0.1.99-snapshot" }
beteran-common-rust = { git = "https://gitlab.loafle.net/bet/beteran-common-rust.git", tag = "v0.1.85-snapshot" }
[build-dependencies]

View File

@ -0,0 +1 @@
DROP FUNCTION update_synchronizations;

View File

@ -0,0 +1,16 @@
CREATE OR REPLACE FUNCTION update_synchronizations()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO api_kgon_synchronizations
(item, last_code, synchronized_at)
VALUES
(NEW.item, NEW.code, (extract(epoch from now()) * 1000))
ON CONFLICT (item)
DO UPDATE
SET
last_code = NEW.code,
synchronized_at = (extract(epoch from now()) * 1000);
RETURN NEW;
END;
$$ language 'plpgsql';

View File

@ -0,0 +1,2 @@
CREATE UNIQUE INDEX uidx_api_kgon_synchronizations_item;
DROP TABLE api_kgon_synchronization_members;

View File

@ -0,0 +1,8 @@
CREATE TABLE IF NOT EXISTS api_kgon_synchronizations (
id SERIAL PRIMARY KEY,
item TEXT NOT NULL,
last_code BIGINT NOT NULL,
synchronized_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000)
);
CREATE UNIQUE INDEX uidx_api_kgon_synchronizations_item ON api_kgon_synchronizations (item);

View File

@ -0,0 +1,3 @@
DROP TRIGGER tg_api_kgon_synchronization_history_synchronizations;
DROP INDEX idx_api_kgon_synchronization_history_item;
DROP TABLE api_kgon_synchronization_members;

View File

@ -0,0 +1,21 @@
CREATE TABLE IF NOT EXISTS api_kgon_synchronization_history (
id BIGSERIAL PRIMARY KEY,
item TEXT NOT NULL,
start_at BIGINT NOT NULL,
complete_at BIGINT NOT NULL,
code BIGINT NOT NULL,
message TEXT,
data TEXT,
created_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000)
);
CREATE INDEX idx_api_kgon_synchronization_history_item ON api_kgon_synchronization_history (item);
CREATE INDEX idx_api_kgon_synchronization_history_created_at ON api_kgon_synchronization_history (created_at);
-- trigger (synchronized_at)
CREATE TRIGGER tg_api_kgon_synchronization_history_synchronizations
AFTER INSERT
ON api_kgon_synchronization_history
FOR EACH ROW
EXECUTE PROCEDURE update_synchronizations();

View File

@ -0,0 +1,3 @@
DROP INDEX idx_api_kgon_members_member_id;
DROP TRIGGER tg_api_kgon_members_updated_at;
DROP TABLE api_kgon_members;

View File

@ -0,0 +1,24 @@
CREATE TABLE IF NOT EXISTS api_kgon_members (
id BIGINT NOT NULL,
balance DOUBLE PRECISION NOT NULL DEFAULT 0.00,
balance_bota DOUBLE PRECISION NOT NULL DEFAULT 0.00,
balance_sum DOUBLE PRECISION NOT NULL DEFAULT 0.00,
companies TEXT,
oriental_play CHAR(1) NOT NULL DEFAULT 'n',
member_id UUID NOT NULL,
created_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000),
updated_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000),
PRIMARY KEY (id),
CONSTRAINT fk_api_kgon_members_member_id
FOREIGN KEY(member_id)
REFERENCES members(id)
);
CREATE INDEX idx_api_kgon_members_member_id ON api_kgon_members (member_id);
-- trigger (updated_at)
CREATE TRIGGER tg_api_kgon_members_updated_at
BEFORE UPDATE
ON api_kgon_members
FOR EACH ROW
EXECUTE PROCEDURE update_updated_at_column();

View File

@ -0,0 +1,2 @@
DROP TRIGGER tg_api_kgon_balances_updated_at;
DROP TABLE api_kgon_balances;

View File

@ -0,0 +1,14 @@
CREATE TABLE IF NOT EXISTS api_kgon_balances (
id SERIAL PRIMARY KEY,
balance DOUBLE PRECISION NOT NULL DEFAULT 0.00,
balance_bota DOUBLE PRECISION NOT NULL DEFAULT 0.00,
created_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000),
updated_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000)
);
-- trigger (updated_at)
CREATE TRIGGER tg_api_kgon_balances_updated_at
BEFORE UPDATE
ON api_kgon_balances
FOR EACH ROW
EXECUTE PROCEDURE update_updated_at_column();

View File

@ -0,0 +1,6 @@
DROP INDEX idx_api_kgon_vendors_company_id;
DROP INDEX idx_api_kgon_vendors_vendor_id;
DROP INDEX idx_api_kgon_vendors_key;
DROP INDEX idx_api_kgon_vendors_category;
DROP TRIGGER tg_api_kgon_vendors_updated_at;
DROP TABLE api_kgon_vendors;

View File

@ -0,0 +1,27 @@
CREATE TABLE IF NOT EXISTS api_kgon_vendors (
id BIGINT NOT NULL,
company_id BIGINT NOT NULL,
vendor_id BIGINT NOT NULL,
max_bet_casino DOUBLE PRECISION NOT NULL DEFAULT 0.00,
max_bet_slot DOUBLE PRECISION NOT NULL DEFAULT 0.00,
is_enable CHAR(1) NOT NULL,
bet_count BIGINT NOT NULL,
key TEXT NOT NULL,
name TEXT NOT NULL,
category TEXT NOT NULL,
created_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000),
updated_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000),
PRIMARY KEY (id)
);
CREATE INDEX idx_api_kgon_vendors_company_id ON api_kgon_vendors (company_id);
CREATE INDEX idx_api_kgon_vendors_vendor_id ON api_kgon_vendors (vendor_id);
CREATE INDEX idx_api_kgon_vendors_key ON api_kgon_vendors (key);
CREATE INDEX idx_api_kgon_vendors_category ON api_kgon_vendors (category);
-- trigger (updated_at)
CREATE TRIGGER tg_api_kgon_vendors_updated_at
BEFORE UPDATE
ON api_kgon_vendors
FOR EACH ROW
EXECUTE PROCEDURE update_updated_at_column();

View File

@ -0,0 +1,6 @@
DROP INDEX idx_api_kgon_games_parent_id;
DROP INDEX idx_api_kgon_games_key;
DROP INDEX idx_api_kgon_games_category;
DROP INDEX idx_api_kgon_games_game_type;
DROP TRIGGER tg_api_kgon_games_updated_at;
DROP TABLE api_kgon_games;

View File

@ -0,0 +1,28 @@
CREATE TABLE IF NOT EXISTS api_kgon_games (
id BIGINT NOT NULL,
parent_id BIGINT NOT NULL,
key TEXT NOT NULL,
names TEXT NOT NULL,
platform TEXT NOT NULL,
category TEXT NOT NULL,
game_type TEXT NOT NULL,
image TEXT,
created_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000),
updated_at BIGINT NOT NULL DEFAULT (extract(epoch from now()) * 1000),
PRIMARY KEY (id),
CONSTRAINT fk_api_kgon_games_parent_id
FOREIGN KEY(parent_id)
REFERENCES api_kgon_vendors(id)
);
CREATE INDEX idx_api_kgon_games_parent_id ON api_kgon_games (parent_id);
CREATE INDEX idx_api_kgon_games_key ON api_kgon_games (key);
CREATE INDEX idx_api_kgon_games_category ON api_kgon_games (category);
CREATE INDEX idx_api_kgon_games_game_type ON api_kgon_games (game_type);
-- trigger (updated_at)
CREATE TRIGGER tg_api_kgon_games_updated_at
BEFORE UPDATE
ON api_kgon_games
FOR EACH ROW
EXECUTE PROCEDURE update_updated_at_column();

View File

@ -0,0 +1,6 @@
DROP INDEX idx_api_kgon_betting_history_vendor_id;
DROP INDEX idx_api_kgon_betting_history_game_id;
DROP INDEX idx_api_kgon_betting_history_created_at;
DROP INDEX idx_api_kgon_betting_history_utc_created_at;
DROP INDEX idx_api_kgon_betting_history_site_username;
DROP TABLE api_kgon_betting_history;

View File

@ -0,0 +1,33 @@
CREATE TABLE IF NOT EXISTS api_kgon_betting_history (
id TEXT NOT NULL,
vendor_id BIGINT NOT NULL,
vendor_name TEXT NOT NULL,
game_id BIGINT NOT NULL,
game_name TEXT NOT NULL,
game_category TEXT NOT NULL,
game_type TEXT NOT NULL,
currency TEXT NOT NULL,
cash DOUBLE PRECISION,
before_cash DOUBLE PRECISION,
after_cash DOUBLE PRECISION,
group_key TEXT,
detail TEXT,
is_bonus BOOLEAN NOT NULL,
is_promo BOOLEAN NOT NULL,
is_jackpot BOOLEAN NOT NULL,
site_username TEXT NOT NULL,
key TEXT NOT NULL,
ref_id TEXT NOT NULL,
o_ref_id TEXT,
betting_type TEXT NOT NULL,
category TEXT NOT NULL,
created_at BIGINT NOT NULL,
utc_created_at BIGINT NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_api_kgon_betting_history_vendor_id ON api_kgon_betting_history (vendor_id);
CREATE INDEX idx_api_kgon_betting_history_game_id ON api_kgon_betting_history (game_id);
CREATE INDEX idx_api_kgon_betting_history_created_at ON api_kgon_betting_history (created_at);
CREATE INDEX idx_api_kgon_betting_history_utc_created_at ON api_kgon_betting_history (utc_created_at);
CREATE INDEX idx_api_kgon_betting_history_site_username ON api_kgon_betting_history (site_username);

292
src/api/betting/api.rs Normal file
View File

@ -0,0 +1,292 @@
use super::models;
use crate::api::core::models::Error;
use crate::core;
use std::collections::HashMap;
///
pub struct Api {
client: reqwest::Client,
api_config: core::config::ApiConfig,
}
impl std::fmt::Debug for Api {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Api of api.kgon.identity").finish()
}
}
impl Api {
///
pub fn new(api_config: core::config::ApiConfig) -> Api {
Api {
client: reqwest::Client::new(),
api_config,
}
}
///
pub async fn list_bettings(
&self,
data: models::ListBettingsRequest,
) -> Result<models::ListBettingsResponse, Error> {
let mut params = HashMap::new();
if let Some(vendor_key) = data.vendor_key {
params.insert("vendorKey", vendor_key);
}
if let Some(sdate) = data.sdate {
params.insert("sdate", sdate);
}
if let Some(edate) = data.edate {
params.insert("edate", edate);
}
if let Some(group_key) = data.group_key {
params.insert("groupKey", group_key);
}
if let Some(username) = data.username {
params.insert("username", username);
}
params.insert("limit", data.limit.to_string());
let res = match self
.client
.post(format!("{}/transaction", self.api_config.k_url))
.header(reqwest::header::ACCEPT, "application/json")
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
)
.header("k-secret", self.api_config.k_secret.as_str())
.header("k-username", self.api_config.k_username.as_str())
.send()
.await
{
Ok(res) => res,
Err(e) => {
return Err(Error {
code: -1,
msg: Some(e.to_string()),
});
}
};
match res.status() {
reqwest::StatusCode::OK => match res.json::<models::_ListBettingsResponse>().await {
Ok(r) => {
if r.code != 0 {
return Err(Error {
code: r.code,
msg: r.msg,
});
}
let transactions = r.transactions.unwrap_or_default();
let last_object_id = r.last_object_id;
Ok(models::ListBettingsResponse {
transactions,
last_object_id,
})
}
Err(e) => Err(Error {
code: -1,
msg: Some(e.to_string()),
}),
},
_ => Err(Error {
code: -1,
msg: None,
}),
}
}
///
pub async fn get_gragmatic_betting(
&self,
data: models::GetPragmaticBettingRequest,
) -> Result<models::GetPragmaticBettingResponse, Error> {
let mut params = HashMap::new();
params.insert("id", data.id);
let res = match self
.client
.post(format!("{}/pragmatic/history", self.api_config.k_url))
.header(reqwest::header::ACCEPT, "application/json")
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
)
.header("k-secret", self.api_config.k_secret.as_str())
.header("k-username", self.api_config.k_username.as_str())
.form(&params)
.send()
.await
{
Ok(res) => res,
Err(e) => {
return Err(Error {
code: -1,
msg: Some(e.to_string()),
});
}
};
match res.status() {
reqwest::StatusCode::OK => match res.json::<models::_GetPragmaticBettingResponse>().await {
Ok(r) => {
if r.code != 0 {
return Err(Error {
code: r.code,
msg: r.msg,
});
}
let url = match r.url {
Some(v) => v,
None => "".to_string(),
};
Ok(models::GetPragmaticBettingResponse { url })
}
Err(e) => Err(Error {
code: -1,
msg: Some(e.to_string()),
}),
},
_ => Err(Error {
code: -1,
msg: None,
}),
}
}
///
pub async fn get_evolution_betting_detail(
&self,
data: models::GetEvolutionBettingDetailRequest,
) -> Result<models::GetEvolutionBettingDetailResponse, Error> {
let mut params = HashMap::new();
params.insert("ids", data.ids);
let res = match self
.client
.post(format!(
"{}/evolution/transaction/detail",
self.api_config.k_url
))
.header(reqwest::header::ACCEPT, "application/json")
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
)
.header("k-secret", self.api_config.k_secret.as_str())
.header("k-username", self.api_config.k_username.as_str())
.form(&params)
.send()
.await
{
Ok(res) => res,
Err(e) => {
return Err(Error {
code: -1,
msg: Some(e.to_string()),
});
}
};
match res.status() {
reqwest::StatusCode::OK => match res
.json::<models::_GetEvolutionBettingDetailResponse>()
.await
{
Ok(r) => {
if r.code != 0 {
return Err(Error {
code: r.code,
msg: r.msg,
});
}
let transactions = r.transactions.unwrap_or_default();
Ok(models::GetEvolutionBettingDetailResponse { transactions })
}
Err(e) => Err(Error {
code: -1,
msg: Some(e.to_string()),
}),
},
_ => Err(Error {
code: -1,
msg: None,
}),
}
}
///
pub async fn get_statistic(
&self,
data: models::GetStatisticRequest,
) -> Result<models::GetStatisticResponse, Error> {
let mut params = HashMap::new();
if let Some(vendor_key) = data.vendor_key {
params.insert("vendorKey", vendor_key);
}
if let Some(group_key) = data.group_key {
params.insert("groupKey", group_key);
}
if let Some(date) = data.date {
params.insert("date", date);
}
let res = match self
.client
.post(format!("{}/statistic", self.api_config.k_url))
.header(reqwest::header::ACCEPT, "application/json")
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
)
.header("k-secret", self.api_config.k_secret.as_str())
.header("k-username", self.api_config.k_username.as_str())
.form(&params)
.send()
.await
{
Ok(res) => res,
Err(e) => {
return Err(Error {
code: -1,
msg: Some(e.to_string()),
});
}
};
match res.status() {
reqwest::StatusCode::OK => match res.json::<models::_GetStatisticResponse>().await {
Ok(r) => {
if r.code != 0 {
return Err(Error {
code: r.code,
msg: r.msg,
});
}
Ok(models::GetStatisticResponse { data: r.data })
}
Err(e) => Err(Error {
code: -1,
msg: Some(e.to_string()),
}),
},
_ => Err(Error {
code: -1,
msg: None,
}),
}
}
}

7
src/api/betting/mod.rs Normal file
View File

@ -0,0 +1,7 @@
//!
//!
///
pub mod api;
///
pub mod models;

168
src/api/betting/models.rs Normal file
View File

@ -0,0 +1,168 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
pub struct Betting {
/// KGON 거래 고유 코드
pub _id: String,
/// 게임사 코드
#[serde(rename = "vendorId")]
pub vendor_id: i64,
/// 게임사
#[serde(rename = "vendorName")]
pub vendor_name: String,
/// 게임코드
#[serde(rename = "gameId")]
pub game_id: i64,
/// 게임명
#[serde(rename = "gameName")]
pub game_name: String,
/// 게임종류
#[serde(rename = "gameCategory")]
pub game_category: String,
/// 게임형식
#[serde(rename = "gameType")]
pub game_type: String,
/// 환율
pub currency: String,
/// 거래금액
pub cash: f64,
/// 이전보유금액
#[serde(rename = "beforeCash")]
pub before_cash: f64,
/// 이후보유금액
#[serde(rename = "afterCash")]
pub after_cash: f64,
/// 사이트 매장 코드
#[serde(rename = "groupKey")]
pub group_key: Option<String>,
/// 게임 데이터
pub detail: Option<Box<serde_json::value::RawValue>>,
/// 보너스 여부
#[serde(rename = "isBonus")]
pub is_bonus: bool,
/// 프로모션 여부
#[serde(rename = "isPromo")]
pub is_promo: bool,
/// 잭팟 여부
#[serde(rename = "isJackpot")]
pub is_jackpot: bool,
/// 사이트 회원 아이디
#[serde(rename = "siteUsername")]
pub site_username: String,
/// 게임사 고유코드
pub key: String,
/// 게임사 상위 배팅 코드
#[serde(rename = "refId")]
pub ref_id: String,
#[serde(rename = "oRefId")]
pub o_ref_id: Option<String>,
/// 결과로서 turn_bet, turn_win, turn_draw, turn_cancel이 존재
#[serde(rename = "type")]
pub betting_type: String,
/// 카테고리
pub category: String,
/// 일자 - 파트너의 timezone 반영
#[serde(rename = "createdAt")]
pub created_at: String,
/// UTC TIME 으로서 한국시간에서 9시간이 빠진 시간입니다. 다음 검색시 sdate에 입력하세요
#[serde(rename = "utcCreatedAt")]
pub utc_created_at: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct ListBettingsRequest {
pub vendor_key: Option<String>,
pub sdate: Option<String>,
pub edate: Option<String>,
pub group_key: Option<String>,
pub username: Option<String>,
pub limit: i64,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct _ListBettingsResponse {
pub code: i64,
pub msg: Option<String>,
pub transactions: Option<Vec<Betting>>,
#[serde(rename = "lastObjectId")]
pub last_object_id: Option<String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct ListBettingsResponse {
pub transactions: Vec<Betting>,
pub last_object_id: Option<String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct GetPragmaticBettingRequest {
pub id: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct _GetPragmaticBettingResponse {
pub code: i64,
pub msg: Option<String>,
pub url: Option<String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct GetPragmaticBettingResponse {
pub url: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct EvolutionBettingDetail {
pub id: String,
pub detail: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct GetEvolutionBettingDetailRequest {
pub ids: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct _GetEvolutionBettingDetailResponse {
pub code: i64,
pub msg: Option<String>,
pub transactions: Option<Vec<EvolutionBettingDetail>>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct GetEvolutionBettingDetailResponse {
pub transactions: Vec<EvolutionBettingDetail>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Statistic {
#[serde(rename = "betAmount")]
pub bet_amount: f64,
#[serde(rename = "drawAmount")]
pub draw_amount: f64,
#[serde(rename = "cancelAmount")]
pub cancel_amount: f64,
#[serde(rename = "winAmount")]
pub win_amount: f64,
#[serde(rename = "revenueAmount")]
pub revenue_amount: f64,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct GetStatisticRequest {
pub vendor_key: Option<String>,
pub group_key: Option<String>,
pub date: Option<String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct _GetStatisticResponse {
pub code: i64,
pub msg: Option<String>,
pub data: Option<Statistic>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct GetStatisticResponse {
pub data: Option<Statistic>,
}

1
src/api/core/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod models;

5
src/api/core/models.rs Normal file
View File

@ -0,0 +1,5 @@
#[derive(Debug)]
pub struct Error {
pub code: i64,
pub msg: Option<String>,
}

166
src/api/game/api.rs Normal file
View File

@ -0,0 +1,166 @@
use super::models;
use crate::api::core::models::Error;
use crate::core;
use std::{collections::HashMap, time::Duration};
///
pub struct Api {
client: reqwest::Client,
api_config: core::config::ApiConfig,
}
impl std::fmt::Debug for Api {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Api of api.kgon.identity").finish()
}
}
impl Api {
///
pub fn new(api_config: core::config::ApiConfig) -> Api {
Api {
client: reqwest::Client::new(),
api_config,
}
}
///
pub async fn list_games(
&self,
data: models::ListGamesRequest,
) -> Result<models::ListGamesResponse, Error> {
let mut params = HashMap::new();
params.insert("vendorKey", data.vendor_key);
let res = match self
.client
.post(format!("{}/games", self.api_config.k_url))
.header(reqwest::header::ACCEPT, "application/json")
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
)
.header("k-secret", self.api_config.k_secret.as_str())
.header("k-username", self.api_config.k_username.as_str())
.form(&params)
.send()
.await
{
Ok(res) => res,
Err(e) => {
return Err(Error {
code: -1,
msg: Some(e.to_string()),
});
}
};
match res.status() {
reqwest::StatusCode::OK => match res.json::<models::_ListGamesResponse>().await {
Ok(r) => {
if r.code != 0 {
return Err(Error {
code: r.code,
msg: r.msg,
});
}
let games = match r.games {
Some(v) => v,
None => vec![],
};
Ok(models::ListGamesResponse { games })
}
Err(e) => Err(Error {
code: -1,
msg: Some(e.to_string()),
}),
},
_ => Err(Error {
code: -1,
msg: None,
}),
}
}
///
pub async fn get_game_url(
&self,
data: models::GetGameUrlRequest,
) -> Result<models::GetGameUrlResponse, Error> {
let mut params = HashMap::new();
params.insert("vendorKey", data.vendor_key);
params.insert("gameKey", data.game_key);
params.insert("username", data.username);
params.insert("nickname", data.nickname);
params.insert("siteUsername", data.site_username);
if let Some(group_key) = data.group_key {
params.insert("groupKey", group_key);
}
params.insert("amount", data.amount.to_string());
if let Some(request_key) = data.request_key {
params.insert("requestKey", request_key);
}
let res = match self
.client
.post(format!("{}/play", self.api_config.k_url))
.header(reqwest::header::ACCEPT, "application/json")
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
)
.header("k-secret", self.api_config.k_secret.as_str())
.header("k-username", self.api_config.k_username.as_str())
.form(&params)
.timeout(Duration::from_secs(10))
.send()
.await
{
Ok(res) => res,
Err(e) => {
return Err(Error {
code: -1,
msg: Some(e.to_string()),
});
}
};
match res.status() {
reqwest::StatusCode::OK => match res.json::<models::_GetGameUrlResponse>().await {
Ok(r) => {
if r.code != 0 {
return Err(Error {
code: r.code,
msg: r.msg,
});
}
let user_id = r.user_id.unwrap_or(0);
let url = r.url.unwrap_or_else(|| "".to_string());
let balance = r.balance.unwrap_or(0.00);
Ok(models::GetGameUrlResponse {
user_id,
url,
balance,
})
}
Err(e) => Err(Error {
code: -1,
msg: Some(e.to_string()),
}),
},
_ => Err(Error {
code: -1,
msg: None,
}),
}
}
}

7
src/api/game/mod.rs Normal file
View File

@ -0,0 +1,7 @@
//!
//!
///
pub mod api;
///
pub mod models;

58
src/api/game/models.rs Normal file
View File

@ -0,0 +1,58 @@
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Serialize, Deserialize, Debug)]
pub struct Game {
pub id: i64,
pub key: String,
pub names: HashMap<String, String>,
pub platform: String,
pub category: String,
#[serde(rename = "type")]
pub game_type: String,
pub image: Option<String>,
}
pub struct ListGamesRequest {
pub vendor_key: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct _ListGamesResponse {
pub code: i64,
pub msg: Option<String>,
pub games: Option<Vec<Game>>,
}
#[derive(Debug)]
pub struct ListGamesResponse {
pub games: Vec<Game>,
}
pub struct GetGameUrlRequest {
pub vendor_key: String,
pub game_key: String,
pub username: String,
pub nickname: String,
pub site_username: String,
pub group_key: Option<String>,
pub amount: f64,
pub request_key: Option<String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct _GetGameUrlResponse {
pub code: i64,
pub msg: Option<String>,
#[serde(rename = "userId")]
pub user_id: Option<i64>,
pub url: Option<String>,
pub balance: Option<f64>,
}
#[derive(Debug)]
pub struct GetGameUrlResponse {
pub user_id: i64,
pub url: String,
pub balance: f64,
}

153
src/api/member/api.rs Normal file
View File

@ -0,0 +1,153 @@
use super::models;
use crate::api::core::models::Error;
use crate::core;
use std::collections::HashMap;
///
pub struct Api {
client: reqwest::Client,
api_config: core::config::ApiConfig,
}
impl std::fmt::Debug for Api {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Api of api.kgon.identity").finish()
}
}
impl Api {
///
pub fn new(api_config: core::config::ApiConfig) -> Api {
Api {
client: reqwest::Client::new(),
api_config,
}
}
///
pub async fn list_members(
&self,
data: models::ListMembersRequest,
) -> Result<models::ListMembersResponse, Error> {
let mut params = HashMap::new();
if let Some(group_key) = data.group_key {
params.insert("groupKey", group_key);
}
let res = match self
.client
.post(format!("{}/users", self.api_config.k_url))
.header(reqwest::header::ACCEPT, "application/json")
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
)
.header("k-secret", self.api_config.k_secret.as_str())
.header("k-username", self.api_config.k_username.as_str())
.form(&params)
.send()
.await
{
Ok(res) => res,
Err(e) => {
return Err(Error {
code: -1,
msg: Some(e.to_string()),
});
}
};
match res.status() {
reqwest::StatusCode::OK => match res.json::<models::_ListMembersResponse>().await {
Ok(r) => {
if r.code != 0 {
return Err(Error {
code: r.code,
msg: r.msg,
});
}
let users = match r.users {
Some(v) => v,
None => vec![],
};
Ok(models::ListMembersResponse { users })
}
Err(e) => Err(Error {
code: -1,
msg: Some(e.to_string()),
}),
},
_ => Err(Error {
code: -1,
msg: None,
}),
}
}
///
pub async fn create_member(
&self,
data: models::CreateMemberRequest,
) -> Result<models::CreateMemberResponse, Error> {
let mut params = HashMap::new();
params.insert("username", data.username);
params.insert("nickname", data.nickname);
params.insert("siteUsername", data.site_username);
if let Some(group_key) = data.group_key {
params.insert("groupKey", group_key);
}
let res = match self
.client
.post(format!("{}/register", self.api_config.k_url))
.header(reqwest::header::ACCEPT, "application/json")
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
)
.header("k-secret", self.api_config.k_secret.as_str())
.header("k-username", self.api_config.k_username.as_str())
.form(&params)
.send()
.await
{
Ok(res) => res,
Err(e) => {
return Err(Error {
code: -1,
msg: Some(e.to_string()),
});
}
};
match res.status() {
reqwest::StatusCode::OK => match res.json::<models::_CreateMemberResponse>().await {
Ok(r) => {
if r.code != 0 {
return Err(Error {
code: r.code,
msg: r.msg,
});
}
let id = r.id.unwrap_or(0);
Ok(models::CreateMemberResponse { id })
}
Err(e) => Err(Error {
code: -1,
msg: Some(e.to_string()),
}),
},
_ => Err(Error {
code: -1,
msg: None,
}),
}
}
}

7
src/api/member/mod.rs Normal file
View File

@ -0,0 +1,7 @@
//!
//!
///
pub mod api;
///
pub mod models;

50
src/api/member/models.rs Normal file
View File

@ -0,0 +1,50 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
pub struct ListMembersRequest {
pub group_key: Option<String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Member {
pub id: i64,
pub username: String,
pub cash: f64,
pub cash_bota: f64,
pub nickname: String,
pub site_username: String,
pub group_key: Option<String>,
pub oriental_play: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct _ListMembersResponse {
pub code: i64,
pub msg: Option<String>,
pub users: Option<Vec<Member>>,
}
#[derive(Debug)]
pub struct ListMembersResponse {
pub users: Vec<Member>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct CreateMemberRequest {
pub username: String,
pub nickname: String,
pub site_username: String,
pub group_key: Option<String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct _CreateMemberResponse {
pub code: i64,
pub msg: Option<String>,
pub id: Option<i64>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct CreateMemberResponse {
pub id: i64,
}

View File

@ -0,0 +1,283 @@
use super::models;
use crate::api::core::models::Error;
use crate::core;
use std::collections::HashMap;
///
pub struct Api {
client: reqwest::Client,
api_config: core::config::ApiConfig,
}
impl std::fmt::Debug for Api {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Api of api.kgon.member_account").finish()
}
}
impl Api {
///
pub fn new(api_config: core::config::ApiConfig) -> Api {
Api {
client: reqwest::Client::new(),
api_config,
}
}
///
pub async fn get_balance_for_user(
&self,
data: models::GetBalanceForUserRequest,
) -> Result<models::GetBalanceForUserResponse, Error> {
let mut params = HashMap::new();
params.insert("username", data.username);
let res = match self
.client
.post(format!("{}/balance", self.api_config.k_url))
.header(reqwest::header::ACCEPT, "application/json")
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
)
.header("k-secret", self.api_config.k_secret.as_str())
.header("k-username", self.api_config.k_username.as_str())
.form(&params)
.send()
.await
{
Ok(res) => res,
Err(e) => {
return Err(Error {
code: -1,
msg: Some(e.to_string()),
});
}
};
match res.status() {
reqwest::StatusCode::OK => match res.json::<models::_GetBalanceForUserResponse>().await {
Ok(r) => {
if r.code != 0 {
return Err(Error {
code: r.code,
msg: r.msg,
});
}
let balance = r.balance.unwrap_or(0.00);
let balance_bota = r.balance_bota.unwrap_or(0.00);
let balance_sum = r.balance_sum.unwrap_or(0.00);
let companies = r.companies.map(|v| v.get().to_string());
Ok(models::GetBalanceForUserResponse {
balance,
balance_bota,
balance_sum,
companies,
})
}
Err(e) => Err(Error {
code: -1,
msg: Some(e.to_string()),
}),
},
_ => Err(Error {
code: -1,
msg: None,
}),
}
}
///
pub async fn get_balance_for_partner(
&self,
data: models::GetBalanceForPartnerRequest,
) -> Result<models::GetBalanceForPartnerResponse, Error> {
let res = match self
.client
.post(format!("{}/partner/balance", self.api_config.k_url))
.header(reqwest::header::ACCEPT, "application/json")
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
)
.header("k-secret", self.api_config.k_secret.as_str())
.header("k-username", self.api_config.k_username.as_str())
.send()
.await
{
Ok(res) => res,
Err(e) => {
return Err(Error {
code: -1,
msg: Some(e.to_string()),
});
}
};
match res.status() {
reqwest::StatusCode::OK => match res.json::<models::_GetBalanceForPartnerResponse>().await {
Ok(r) => {
if r.code != 0 {
return Err(Error {
code: r.code,
msg: r.msg,
});
}
let balance = r.balance.unwrap_or(0.00);
let balance_bota = r.balance_bota.unwrap_or(0.00);
Ok(models::GetBalanceForPartnerResponse {
balance,
balance_bota,
})
}
Err(e) => Err(Error {
code: -1,
msg: Some(e.to_string()),
}),
},
_ => Err(Error {
code: -1,
msg: None,
}),
}
}
///
pub async fn create_deposit(
&self,
data: models::CreateDepositRequest,
) -> Result<models::CreateDepositResponse, Error> {
let mut params = HashMap::new();
params.insert("username", data.username);
if let Some(cash_type) = data.cash_type {
params.insert("cashType", cash_type);
}
params.insert("amount", data.amount.to_string());
if let Some(request_key) = data.request_key {
params.insert("requestKey", request_key);
}
let res = match self
.client
.post(format!("{}/deposit", self.api_config.k_url))
.header(reqwest::header::ACCEPT, "application/json")
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
)
.header("k-secret", self.api_config.k_secret.as_str())
.header("k-username", self.api_config.k_username.as_str())
.form(&params)
.send()
.await
{
Ok(res) => res,
Err(e) => {
return Err(Error {
code: -1,
msg: Some(e.to_string()),
});
}
};
match res.status() {
reqwest::StatusCode::OK => match res.json::<models::_CreateDepositResponse>().await {
Ok(r) => {
if r.code != 0 {
return Err(Error {
code: r.code,
msg: r.msg,
});
}
let balance = r.balance.unwrap_or(0.00);
Ok(models::CreateDepositResponse { balance })
}
Err(e) => Err(Error {
code: -1,
msg: Some(e.to_string()),
}),
},
_ => Err(Error {
code: -1,
msg: None,
}),
}
}
///
pub async fn create_withdraw(
&self,
data: models::CreateWithdrawRequest,
) -> Result<models::CreateWithdrawResponse, Error> {
let mut params = HashMap::new();
params.insert("username", data.username);
if let Some(request_key) = data.request_key {
params.insert("requestKey", request_key);
}
let res = match self
.client
.post(format!("{}/withdraw", self.api_config.k_url))
.header(reqwest::header::ACCEPT, "application/json")
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
)
.header("k-secret", self.api_config.k_secret.as_str())
.header("k-username", self.api_config.k_username.as_str())
.form(&params)
.send()
.await
{
Ok(res) => res,
Err(e) => {
return Err(Error {
code: -1,
msg: Some(e.to_string()),
});
}
};
match res.status() {
reqwest::StatusCode::OK => match res.json::<models::_CreateWithdrawResponse>().await {
Ok(r) => {
if r.code != 0 {
return Err(Error {
code: r.code,
msg: r.msg,
});
}
let balance = r.balance.unwrap_or(0.00);
let balance_cash = r.balance_cash.unwrap_or(0.00);
let balance_cash_bota = r.balance_cash_bota.unwrap_or(0.00);
let amount = r.amount.unwrap_or(0.00);
Ok(models::CreateWithdrawResponse {
balance,
balance_cash,
balance_cash_bota,
amount,
})
}
Err(e) => Err(Error {
code: -1,
msg: Some(e.to_string()),
}),
},
_ => Err(Error {
code: -1,
msg: None,
}),
}
}
}

View File

@ -0,0 +1,7 @@
//!
//!
///
pub mod api;
///
pub mod models;

View File

@ -0,0 +1,87 @@
use serde::{Deserialize, Serialize};
pub struct GetBalanceForUserRequest {
pub username: String,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct _GetBalanceForUserResponse {
pub code: i64,
pub msg: Option<String>,
pub balance: Option<f64>,
#[serde(rename = "balanceBota")]
pub balance_bota: Option<f64>,
#[serde(rename = "balanceSum")]
pub balance_sum: Option<f64>,
pub companies: Option<Box<serde_json::value::RawValue>>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct GetBalanceForUserResponse {
pub balance: f64,
#[serde(rename = "balanceBota")]
pub balance_bota: f64,
#[serde(rename = "balanceSum")]
pub balance_sum: f64,
pub companies: Option<String>,
}
pub struct GetBalanceForPartnerRequest {}
#[derive(Serialize, Deserialize, Debug)]
pub struct _GetBalanceForPartnerResponse {
pub code: i64,
pub msg: Option<String>,
pub balance: Option<f64>,
#[serde(rename = "balanceBota")]
pub balance_bota: Option<f64>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct GetBalanceForPartnerResponse {
pub balance: f64,
#[serde(rename = "balanceBota")]
pub balance_bota: f64,
}
pub struct CreateDepositRequest {
pub username: String,
pub cash_type: Option<String>,
pub amount: f64,
pub request_key: Option<String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct _CreateDepositResponse {
pub code: i64,
pub msg: Option<String>,
pub balance: Option<f64>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct CreateDepositResponse {
pub balance: f64,
}
pub struct CreateWithdrawRequest {
pub username: String,
pub request_key: Option<String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct _CreateWithdrawResponse {
pub code: i64,
pub msg: Option<String>,
pub balance: Option<f64>,
pub balance_cash: Option<f64>,
pub balance_cash_bota: Option<f64>,
pub amount: Option<f64>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct CreateWithdrawResponse {
pub balance: f64,
pub balance_cash: f64,
pub balance_cash_bota: f64,
pub amount: f64,
}

6
src/api/mod.rs Normal file
View File

@ -0,0 +1,6 @@
pub mod betting;
pub mod core;
pub mod game;
pub mod member;
pub mod member_account;
pub mod vendor;

81
src/api/vendor/api.rs vendored Normal file
View File

@ -0,0 +1,81 @@
use super::models;
use crate::api::core::models::Error;
use crate::core;
///
pub struct Api {
client: reqwest::Client,
api_config: core::config::ApiConfig,
}
impl std::fmt::Debug for Api {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Api of api.kgon.identity").finish()
}
}
impl Api {
///
pub fn new(api_config: core::config::ApiConfig) -> Api {
Api {
client: reqwest::Client::new(),
api_config,
}
}
///
pub async fn list_vendors(
&self,
data: models::ListVendorsRequest,
) -> Result<models::ListVendorsResponse, Error> {
let res = match self
.client
.post(format!("{}/vendors", self.api_config.k_url))
.header(reqwest::header::ACCEPT, "application/json")
.header(
reqwest::header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
)
.header("k-secret", self.api_config.k_secret.as_str())
.header("k-username", self.api_config.k_username.as_str())
.send()
.await
{
Ok(res) => res,
Err(e) => {
return Err(Error {
code: -1,
msg: Some(e.to_string()),
});
}
};
match res.status() {
reqwest::StatusCode::OK => match res.json::<models::_ListVendorsResponse>().await {
Ok(r) => {
if r.code != 0 {
return Err(Error {
code: r.code,
msg: r.msg,
});
}
let vendors = match r.vendors {
Some(v) => v,
None => vec![],
};
Ok(models::ListVendorsResponse { vendors })
}
Err(e) => Err(Error {
code: -1,
msg: Some(e.to_string()),
}),
},
_ => Err(Error {
code: -1,
msg: None,
}),
}
}
}

7
src/api/vendor/mod.rs vendored Normal file
View File

@ -0,0 +1,7 @@
//!
//!
///
pub mod api;
///
pub mod models;

29
src/api/vendor/models.rs vendored Normal file
View File

@ -0,0 +1,29 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
pub struct Vendor {
pub id: i64,
pub company_id: i64,
pub vendor_id: i64,
pub max_bet_casino: f64,
pub max_bet_slot: f64,
pub is_enable: String,
pub bet_count: i64,
pub key: String,
pub name: String,
pub category: String,
}
pub struct ListVendorsRequest {}
#[derive(Serialize, Deserialize, Debug)]
pub struct _ListVendorsResponse {
pub code: i64,
pub msg: Option<String>,
pub vendors: Option<Vec<Vendor>>,
}
#[derive(Debug)]
pub struct ListVendorsResponse {
pub vendors: Vec<Vendor>,
}

View File

@ -0,0 +1,615 @@
use super::models;
use beteran_common_rust as bcr;
use diesel::{result::Error, sql_query, RunQueryDsl};
use std::fmt::Write;
static BETTING_HISTORY_COUNT_QUERY: &str = "
SELECT
COUNT(akbh.id)
FROM api_kgon_betting_history as akbh
INNER JOIN members m
ON m.username = akbh.site_username
LEFT OUTER JOIN member_settlement_settings m_mss
ON m_mss.member_id = m.id
";
static BETTING_HISTORY_QUERY: &str = "
SELECT
akbh.id as akbh_id ,
akbh.vendor_id as akbh_vendor_id ,
akbh.vendor_name as akbh_vendor_name ,
akbh.game_id as akbh_game_id ,
akbh.game_name as akbh_game_name ,
akbh.game_category as akbh_game_category ,
akbh.game_type as akbh_game_type ,
akbh.currency as akbh_currency ,
akbh.cash as akbh_cash ,
akbh.before_cash as akbh_before_cash ,
akbh.after_cash as akbh_after_cash ,
akbh.group_key as akbh_group_key ,
akbh.detail as akbh_detail ,
akbh.is_bonus as akbh_is_bonus ,
akbh.is_promo as akbh_is_promo ,
akbh.is_jackpot as akbh_is_jackpot ,
akbh.site_username as akbh_site_username ,
akbh.key as akbh_key ,
akbh.ref_id as akbh_ref_id ,
akbh.o_ref_id as akbh_o_ref_id ,
akbh.betting_type as akbh_betting_type ,
akbh.category as akbh_category ,
akbh.created_at as akbh_created_at ,
akbh.utc_created_at as akbh_utc_created_at,
m.id as m_id,
m.site_id as m_site_id,
m.member_class_id as m_member_class_id,
m.member_level_id as m_member_level_id,
m.username as m_username,
m.password as m_password,
m.nickname as m_nickname,
m.mobile_phone_number as m_mobile_phone_number,
m.state as m_state,
m.state_changed_at as m_state_changed_at,
m.parent_member_id as m_parent_member_id,
m.child_member_count as m_child_member_count,
m.last_signined_ip as m_last_signined_ip,
m.last_signined_at as m_last_signined_at,
m.created_at as m_created_at,
m.updated_at as m_updated_at,
m.deleted_at as m_deleted_at,
m_mss.id as m_mss_id,
m_mss.member_id as m_mss_member_id,
m_mss.can_exchange as m_mss_can_exchange,
m_mss.can_first_charge_comp as m_mss_can_first_charge_comp,
m_mss.can_per_charge_comp as m_mss_can_per_charge_comp,
m_mss.manual_payment_type_for_partner as m_mss_manual_payment_type_for_partner,
m_mss.settlement_type as m_mss_settlement_type,
m_mss.rate_casino as m_mss_rate_casino,
m_mss.rate_casino_loosing as m_mss_rate_casino_loosing,
m_mss.rate_casino_bacara as m_mss_rate_casino_bacara,
m_mss.rate_casino_roulette as m_mss_rate_casino_roulette,
m_mss.rate_casino_dragon_tiger as m_mss_rate_casino_dragon_tiger,
m_mss.rate_slot as m_mss_rate_slot,
m_mss.rate_slot_loosing as m_mss_rate_slot_loosing,
m_mss.rate_powerball_single as m_mss_rate_powerball_single,
m_mss.rate_powerball_combo as m_mss_rate_powerball_combo,
m_mss.rate_powerladder_single as m_mss_rate_powerladder_single,
m_mss.rate_powerladder_combo as m_mss_rate_powerladder_combo,
m_mss.rate_eos_single as m_mss_rate_eos_single,
m_mss.rate_eos_combo as m_mss_rate_eos_combo,
m_mss.rate_bogglepowerball_single as m_mss_rate_bogglepowerball_single,
m_mss.rate_bogglepowerball_combo as m_mss_rate_bogglepowerball_combo,
m_mss.created_at as m_mss_created_at,
m_mss.updated_at as m_mss_updated_at
FROM api_kgon_betting_history as akbh
INNER JOIN members m
ON m.username = akbh.site_username
LEFT OUTER JOIN member_settlement_settings m_mss
ON m_mss.member_id = m.id
";
pub struct Composition {}
impl std::fmt::Debug for Composition {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Composition of members").finish()
}
}
impl Composition {
///
pub fn new() -> Composition {
Composition {}
}
///
pub fn select(
&self,
conn: &diesel::PgConnection,
id: String,
) -> Result<Option<models::BettingHistoryModel>, Error> {
let query = format!(
"
{}
WHERE
akbh.id = $1
",
BETTING_HISTORY_QUERY
);
match sql_query(query)
.bind::<diesel::sql_types::Text, _>(id)
.get_result::<models::BettingHistoryModel>(conn)
{
Ok(m) => Ok(Some(m)),
Err(e) => match e {
diesel::result::Error::NotFound => Ok(None),
_ => Err(e),
},
}
}
///
pub fn select_by_member_id(
&self,
conn: &diesel::PgConnection,
member_id: uuid::Uuid,
) -> Result<Option<models::BettingHistoryModel>, Error> {
let query = format!(
"
{}
WHERE
m.id = $1
",
BETTING_HISTORY_QUERY
);
match sql_query(query)
.bind::<diesel::sql_types::Uuid, _>(member_id)
.get_result::<models::BettingHistoryModel>(conn)
{
Ok(m) => Ok(Some(m)),
Err(e) => match e {
diesel::result::Error::NotFound => Ok(None),
_ => Err(e),
},
}
}
fn get_pagination(&self, find_all: &models::FindAll) -> Result<String, Error> {
let mut query_pagination = String::new();
if let Some(pagination) = &find_all.pagination {
let page = match pagination.page {
Some(v) => {
if v < 1 {
1
} else {
v
}
}
None => 1,
};
if let Some(page_size) = pagination.page_size {
write!(
&mut query_pagination,
" OFFSET {} LIMIT {} ",
((page - 1) * page_size) as i64,
page_size as i64
)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
}
Ok(query_pagination)
}
fn get_ordery_by(&self, find_all: &models::FindAll) -> Result<String, Error> {
let mut query_ordery_by = String::new();
if let Some(sorts) = &find_all.sorts {
for s in sorts {
if !query_ordery_by.is_empty() {
write!(&mut query_ordery_by, " , ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
let (property, sort) = match s {
bcr::pagination::Sort::ASC(property) => (property.clone(), "ASC".to_string()),
bcr::pagination::Sort::DESC(property) => (property.clone(), "DESC".to_string()),
};
let property = match property.as_str() {
"member_id" => "m.id".to_string(),
"username" => "m.username".to_string(),
"nickname" => "m.nickname".to_string(),
"vendor_id" => "akbh.vendor_id".to_string(),
"vendor_name" => "akbh.vendor_name".to_string(),
"game_id" => "akbh.game_id".to_string(),
"game_name" => "akbh.game_name".to_string(),
"game_category" => "akbh.game_category".to_string(),
"game_type" => "akbh.game_type".to_string(),
"currency" => "akbh.currency".to_string(),
"cash" => "akbh.cash".to_string(),
"before_cash" => "akbh.before_cash".to_string(),
"after_cash" => "akbh.after_cash".to_string(),
"key" => "akbh.key".to_string(),
"ref_id" => "akbh.ref_id".to_string(),
"o_ref_id" => "akbh.o_ref_id".to_string(),
"group_key" => "akbh.group_key".to_string(),
"is_bonus" => "akbh.is_bonus".to_string(),
"is_promo" => "akbh.is_promo".to_string(),
"is_jackpot" => "akbh.is_jackpot".to_string(),
"site_username" => "akbh.site_username".to_string(),
"betting_type" => "akbh.betting_type".to_string(),
"category" => "category.id".to_string(),
"created_at" => "akbh.created_at".to_string(),
"utc_created_at" => "akbh.utc_created_at".to_string(),
_ => "".to_string(),
};
if !property.is_empty() {
write!(&mut query_ordery_by, "{} {}", property, sort)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
}
}
Ok(query_ordery_by)
}
fn get_where(&self, find_all: &models::FindAll) -> Result<String, Error> {
let mut query_where = String::new();
if let Some(s) = &find_all.search {
if let Some(sp) = &s.member_id {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "m.id = '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = s.vendor_id {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.vendor_id = {}", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if !s.vendor_ids.is_empty() {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(
&mut query_where,
"akbh.vendor_id IN ({})",
s.vendor_ids
.iter()
.map(|v| v.to_string())
.collect::<Vec<String>>()
.join(",")
)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.vendor_name {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.vendor_name = '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.vendor_name_like {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.vendor_name like '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = s.game_id {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.game_id = {}", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if !s.game_ids.is_empty() {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(
&mut query_where,
"akbh.game_id IN ({})",
s.game_ids
.iter()
.map(|v| v.to_string())
.collect::<Vec<String>>()
.join(",")
)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.game_name {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.game_name = '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.game_name_like {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.game_name like '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.game_category {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.game_category = '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.game_category_like {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.game_category like '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.game_type {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.game_type = '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.game_type_like {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.game_type like '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.currency {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.currency = '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.currency_like {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.currency like '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.key {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.key = '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.key_like {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.key like '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.ref_id {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.ref_id = '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.ref_id_like {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.ref_id like '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.o_ref_id {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.o_ref_id = '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.o_ref_id_like {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.o_ref_id like '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.group_key {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.group_key = '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.group_key_like {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.group_key like '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = s.is_bonus {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.is_bonus = '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = s.is_promo {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.is_promo = '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = s.is_jackpot {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.is_jackpot = '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.site_username {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.site_username = '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.site_username_like {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.site_username like '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.betting_type {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.betting_type = '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.betting_type_like {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.betting_type like '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.category {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.category = '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
if let Some(sp) = &s.category_like {
if !query_where.is_empty() {
write!(&mut query_where, " AND ")
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
write!(&mut query_where, "akbh.category like '{}'", sp)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
}
Ok(query_where)
}
///
pub fn select_all_count(
&self,
conn: &diesel::PgConnection,
find_all: &models::FindAll,
) -> Result<i64, Error> {
use diesel::sql_types::BigInt;
#[derive(QueryableByName)]
struct Count {
#[sql_type = "BigInt"]
count: i64,
}
let mut query = String::new();
write!(&mut query, "{}", BETTING_HISTORY_COUNT_QUERY)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
let query_where = self.get_where(find_all)?;
if !query_where.is_empty() {
write!(&mut query, " WHERE {}", query_where)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
println!("query: {}", query);
match sql_query(query).get_result::<Count>(conn) {
Ok(m) => Ok(m.count),
Err(e) => match e {
diesel::result::Error::NotFound => Ok(0),
_ => Err(e),
},
}
}
///
pub fn select_all(
&self,
conn: &diesel::PgConnection,
find_all: &models::FindAll,
) -> Result<Vec<models::BettingHistoryModel>, Error> {
let mut query = String::new();
write!(&mut query, "{}", BETTING_HISTORY_QUERY)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
let query_where = self.get_where(find_all)?;
if !query_where.is_empty() {
write!(&mut query, " WHERE {}", query_where)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
let query_ordery_by = self.get_ordery_by(find_all)?;
if !query_ordery_by.is_empty() {
write!(&mut query, " ORDER BY {}", query_ordery_by)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
let query_pagination = self.get_pagination(find_all)?;
if !query_pagination.is_empty() {
write!(&mut query, " {} ", query_pagination)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
}
println!("query: {}", query);
match sql_query(query).get_results::<models::BettingHistoryModel>(conn) {
Ok(m) => Ok(m),
Err(e) => match e {
diesel::result::Error::NotFound => Ok(vec![]),
_ => Err(e),
},
}
}
}

View File

@ -0,0 +1,2 @@
pub mod composition;
pub mod models;

View File

@ -0,0 +1,166 @@
use beteran_common_rust as bcr;
use diesel::deserialize::QueryableByName;
///
#[derive(PartialEq, Debug, Clone)]
pub struct BettingHistoryModel {
///
pub id: String,
///
pub vendor_id: i64,
///
pub vendor_name: String,
///
pub game_id: i64,
///
pub game_name: String,
///
pub game_category: String,
///
pub game_type: String,
///
pub currency: String,
///
pub cash: f64,
///
pub before_cash: f64,
///
pub after_cash: f64,
///
pub group_key: Option<String>,
///
pub detail: Option<String>,
///
pub is_bonus: bool,
///
pub is_promo: bool,
///
pub is_jackpot: bool,
///
pub site_username: String,
///
pub key: String,
///
pub ref_id: String,
///
pub o_ref_id: String,
///
pub betting_type: String,
///
pub category: String,
///
pub created_at: i64,
///
pub utc_created_at: i64,
}
impl QueryableByName<diesel::pg::Pg> for BettingHistoryModel {
fn build<R: diesel::row::NamedRow<diesel::pg::Pg>>(row: &R) -> diesel::deserialize::Result<Self> {
Ok(BettingHistoryModel {
id: row.get("akbh_id")?,
vendor_id: row.get("akbh_vendor_id")?,
vendor_name: row.get("akbh_vendor_name")?,
game_id: row.get("akbh_game_id")?,
game_name: row.get("akbh_game_name")?,
game_category: row.get("akbh_game_category")?,
game_type: row.get("akbh_game_type")?,
currency: row.get("akbh_currency")?,
cash: row.get("akbh_cash")?,
before_cash: row.get("akbh_before_cash")?,
after_cash: row.get("akbh_after_cash")?,
group_key: row.get("akbh_group_key")?,
detail: row.get("akbh_detail")?,
is_bonus: row.get("akbh_is_bonus")?,
is_promo: row.get("akbh_is_promo")?,
is_jackpot: row.get("akbh_is_jackpot")?,
site_username: row.get("akbh_site_username")?,
key: row.get("akbh_key")?,
ref_id: row.get("akbh_ref_id")?,
o_ref_id: row.get("akbh_o_ref_id")?,
betting_type: row.get("akbh_betting_type")?,
category: row.get("akbh_category")?,
created_at: row.get("akbh_created_at")?,
utc_created_at: row.get("akbh_utc_created_at")?,
})
}
}
///
#[derive(Debug, Clone)]
pub struct FindAllSearch {
///
pub member_id: Option<String>,
///
pub vendor_id: Option<i64>,
///
pub vendor_ids: Vec<i64>,
///
pub vendor_name: Option<String>,
///
pub vendor_name_like: Option<String>,
///
pub game_id: Option<i64>,
///
pub game_ids: Vec<i64>,
///
pub game_name: Option<String>,
///
pub game_name_like: Option<String>,
///
pub game_category: Option<String>,
///
pub game_category_like: Option<String>,
///
pub game_type: Option<String>,
///
pub game_type_like: Option<String>,
///
pub currency: Option<String>,
///
pub currency_like: Option<String>,
///
pub key: Option<String>,
///
pub key_like: Option<String>,
///
pub ref_id: Option<String>,
///
pub ref_id_like: Option<String>,
///
pub o_ref_id: Option<String>,
///
pub o_ref_id_like: Option<String>,
///
pub group_key: Option<String>,
///
pub group_key_like: Option<String>,
///
pub is_bonus: Option<bool>,
///
pub is_promo: Option<bool>,
///
pub is_jackpot: Option<bool>,
///
pub site_username: Option<String>,
///
pub site_username_like: Option<String>,
///
pub betting_type: Option<String>,
///
pub betting_type_like: Option<String>,
///
pub category: Option<String>,
///
pub category_like: Option<String>,
}
///
#[derive(Debug, Clone)]
pub struct FindAll {
pub search: Option<FindAllSearch>,
///
pub pagination: Option<bcr::pagination::Pagination>,
///
pub sorts: Option<Vec<bcr::pagination::Sort>>,
}
/////////////////////////////// temparary definitions ///////////////////////////////////////////

View File

View File

@ -0,0 +1,211 @@
use super::models;
use crate::repositories;
use beteran_common_rust as bcr;
use beteran_protobuf_rust as bpr;
use prost::Message;
use std::net::{IpAddr, Ipv4Addr};
pub struct Composition {
connection_broker: nats::asynk::Connection,
member_repository: repositories::member::repository::Repository,
}
impl std::fmt::Debug for Composition {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Composition of members").finish()
}
}
impl Composition {
///
pub fn new(connection_broker: nats::asynk::Connection) -> Composition {
Composition {
connection_broker,
member_repository: repositories::member::repository::Repository::new(),
}
}
///
pub async fn select_by_member_id(
&self,
conn: &diesel::PgConnection,
member_id: uuid::Uuid,
) -> Result<Option<models::Member>, bcr::error::rpc::Error> {
let m = match self
.member_repository
.select_by_member_id(conn, member_id)
.map_err(|e| {
bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {}", e),
data: None,
})
})? {
Some(m) => m,
None => {
return Ok(None);
}
};
let ss_get_member_req = bpr::ss::member::GetMemberBRequest {
client: Some(bpr::models::core::network::Client {
client_ip: self
.connection_broker
.client_ip()
.unwrap_or(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)))
.to_string(),
site_url: None,
access_token: None,
}),
request: Some(bpr::ss::member::get_member_b_request::Request {
id: m.member_id.to_string(),
}),
};
let ss_get_member_res_msg = self
.connection_broker
.request(
bpr::ss::member::SUBJECT_GET_MEMBER_B,
ss_get_member_req.encode_to_vec(),
)
.await
.map_err(|e| {
bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {}", e),
data: None,
})
})?;
let ss_get_member_res = bpr::ss::member::GetMemberBResponse::decode(
ss_get_member_res_msg.data.as_slice(),
)
.map_err(|e| {
bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {}", e),
data: None,
})
})?;
if let Some(e) = ss_get_member_res.error {
return Err(bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {}", e),
data: None,
}));
}
let mm = match ss_get_member_res.result {
Some(r) => match r.member {
Some(_m) => Some(models::Member {
id: m.id,
balance: m.balance,
balance_bota: m.balance_bota,
balance_sum: m.balance_sum,
companies: m.companies,
oriental_play: m.oriental_play,
member: _m,
created_at: m.created_at,
updated_at: m.updated_at,
}),
None => None,
},
None => None,
};
Ok(mm)
}
///
pub async fn select_b_by_member_id(
&self,
conn: &diesel::PgConnection,
member_id: uuid::Uuid,
) -> Result<Option<models::MemberModel>, bcr::error::rpc::Error> {
let m = match self
.member_repository
.select_by_member_id(conn, member_id)
.map_err(|e| {
bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {}", e),
data: None,
})
})? {
Some(m) => m,
None => {
return Ok(None);
}
};
let ss_get_member_req = bpr::ss::member::GetMemberRequest {
client: Some(bpr::models::core::network::Client {
client_ip: self
.connection_broker
.client_ip()
.unwrap_or(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)))
.to_string(),
site_url: None,
access_token: None,
}),
request: Some(bpr::ss::member::get_member_request::Request {
id: m.member_id.to_string(),
}),
};
let ss_get_member_res_msg = self
.connection_broker
.request(
bpr::ss::member::SUBJECT_GET_MEMBER,
ss_get_member_req.encode_to_vec(),
)
.await
.map_err(|e| {
bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {}", e),
data: None,
})
})?;
let ss_get_member_res = bpr::ss::member::GetMemberResponse::decode(
ss_get_member_res_msg.data.as_slice(),
)
.map_err(|e| {
bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {}", e),
data: None,
})
})?;
if let Some(e) = ss_get_member_res.error {
return Err(bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {}", e),
data: None,
}));
}
let mm = match ss_get_member_res.result {
Some(r) => match r.member {
Some(_m) => Some(models::MemberModel {
id: m.id,
balance: m.balance,
balance_bota: m.balance_bota,
balance_sum: m.balance_sum,
companies: m.companies,
oriental_play: m.oriental_play,
member: _m,
created_at: m.created_at,
updated_at: m.updated_at,
}),
None => None,
},
None => None,
};
Ok(mm)
}
}

View File

@ -0,0 +1,2 @@
pub mod composition;
pub mod models;

View File

@ -0,0 +1,47 @@
use beteran_protobuf_rust as bpr;
///
#[derive(PartialEq, Debug, Clone)]
pub struct Member {
///
pub id: i64,
///
pub balance: f64,
///
pub balance_bota: f64,
///
pub balance_sum: f64,
///
pub companies: Option<String>,
///
pub oriental_play: String,
///
pub member: bpr::models::member::Member,
///
pub created_at: i64,
///
pub updated_at: i64,
}
///
#[derive(PartialEq, Debug, Clone)]
pub struct MemberModel {
///
pub id: i64,
///
pub balance: f64,
///
pub balance_bota: f64,
///
pub balance_sum: f64,
///
pub companies: Option<String>,
///
pub oriental_play: String,
///
pub member: bpr::models::member::MemberModel,
///
pub created_at: i64,
///
pub updated_at: i64,
}

View File

4
src/compositions/mod.rs Normal file
View File

@ -0,0 +1,4 @@
pub mod betting;
pub mod game;
pub mod member;
pub mod member_account;

6
src/core/config.rs Normal file
View File

@ -0,0 +1,6 @@
#[derive(Debug, Clone)]
pub struct ApiConfig {
pub k_url: String,
pub k_username: String,
pub k_secret: String,
}

1
src/core/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod config;

197
src/events/member/event.rs Normal file
View File

@ -0,0 +1,197 @@
use crate::api;
use crate::core;
use crate::repositories;
use beteran_common_rust as bcr;
use beteran_protobuf_rust as bpr;
use diesel::{
r2d2::{ConnectionManager, Pool},
PgConnection,
};
use prost::Message;
use std::str::FromStr;
static MEMBER_CLASS_ID_MAIN_OFFICE: &str = "4b014ef5-3bab-4413-aaf9-b0040a70ec77";
static MEMBER_CLASS_ID_BRANCH: &str = "ae9b874e-5d0e-4c4d-8432-f45f02691ceb";
static MEMBER_CLASS_ID_DIVISION: &str = "f25a17e9-5c5f-4e9c-bf80-92a9cedf829c";
static MEMBER_CLASS_ID_OFFICE: &str = "cac7b897-2549-4f04-8415-8868f1dcb1da";
static MEMBER_CLASS_ID_STORE: &str = "e11cac11-3825-4f4e-9cd5-39367f23f973";
static MEMBER_CLASS_ID_USER: &str = "4598f07a-86d1-42a4-b038-25706683a7cd";
pub struct EventHandler {
connection_broker: nats::asynk::Connection,
queue_broker: String,
pool: Pool<ConnectionManager<PgConnection>>,
api_config: core::config::ApiConfig,
member_repository: repositories::member::repository::Repository,
member_api: api::member::api::Api,
}
impl std::fmt::Debug for EventHandler {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("EventHandler of members").finish()
}
}
impl EventHandler {
///
pub fn new(
connection_broker: nats::asynk::Connection,
queue_broker: String,
pool: Pool<ConnectionManager<PgConnection>>,
api_config: core::config::ApiConfig,
) -> EventHandler {
EventHandler {
connection_broker,
queue_broker,
pool,
api_config: api_config.clone(),
member_repository: repositories::member::repository::Repository::new(),
member_api: api::member::api::Api::new(api_config.clone()),
}
}
pub async fn subscribe(&self) -> std::result::Result<(), std::boxed::Box<dyn std::error::Error>> {
futures::try_join!(self.event_after_create_member()).map(|_| ())
}
async fn event_after_create_member(&self) -> Result<(), Box<dyn std::error::Error>> {
let s = self
.connection_broker
.queue_subscribe(
bpr::ss::member::EVENT_SUBJECT_AFTER_CREATE_MEMBER,
self.queue_broker.as_str(),
)
.await?;
while let Some(message) = s.next().await {
if let Err(e) = async {
let eve = bpr::ss::member::AfterCreateMemberEvent::decode(message.data.as_slice())
.map_err(|e| {
bcr::error::rpc::Error::InvalidRequest(bcr::error::rpc::InvalidRequest {
message: format!("invalid request: {}", e),
})
})?;
let client = match eve.client {
Some(c) => c,
None => {
return Err(bcr::error::rpc::Error::InvalidParams(
bcr::error::rpc::InvalidParams {
message: "invalid client information".to_string(),
detail: bcr::error::rpc::InvalidParamsDetail {
location: "request".to_string(),
param: "client".to_string(),
value: "".to_string(),
error_type: bcr::error::rpc::InvalidParamsType::Required,
message: "".to_string(),
},
},
));
}
};
let event = match eve.event {
Some(r) => r,
None => {
return Err(bcr::error::rpc::Error::InvalidParams(
bcr::error::rpc::InvalidParams {
message: "invalid event information".to_string(),
detail: bcr::error::rpc::InvalidParamsDetail {
location: "event".to_string(),
param: "event".to_string(),
value: "".to_string(),
error_type: bcr::error::rpc::InvalidParamsType::Required,
message: "".to_string(),
},
},
));
}
};
let member = match event.member {
Some(c) => c,
None => {
return Err(bcr::error::rpc::Error::InvalidParams(
bcr::error::rpc::InvalidParams {
message: "invalid client information".to_string(),
detail: bcr::error::rpc::InvalidParamsDetail {
location: "request".to_string(),
param: "client".to_string(),
value: "".to_string(),
error_type: bcr::error::rpc::InvalidParamsType::Required,
message: "".to_string(),
},
},
));
}
};
let member_id = uuid::Uuid::from_str(member.id.as_str()).map_err(|e| {
bcr::error::rpc::Error::InvalidParams(bcr::error::rpc::InvalidParams {
message: "invalid member.id param".to_string(),
detail: bcr::error::rpc::InvalidParamsDetail {
location: "request".to_string(),
param: "member.id".to_string(),
value: member.id.clone(),
error_type: bcr::error::rpc::InvalidParamsType::Required,
message: e.to_string(),
},
})
})?;
let conn = self.pool.get().map_err(|e| {
bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {}", e),
data: None,
})
})?;
if let Some(mc) = member.member_class {
if mc.id.eq(MEMBER_CLASS_ID_USER) {
let api_create_res = self
.member_api
.create_member(api::member::models::CreateMemberRequest {
username: member.username.clone(),
nickname: member.nickname.clone(),
site_username: member.username.clone(),
group_key: match member.parent_member {
Some(m) => Some(m.username),
None => None,
},
})
.await
.map_err(|e| {
bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {:?}", e),
data: None,
})
})?;
self
.member_repository
.insert(
&conn,
&repositories::member::models::NewMember {
id: api_create_res.id,
member_id,
},
)
.map_err(|e| {
bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {}", e),
data: None,
})
})?;
}
}
Ok::<(), bcr::error::rpc::Error>(())
}
.await
{
println!("error: {}", e);
}
}
Ok(())
}
}

1
src/events/member/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod event;

View File

@ -0,0 +1,208 @@
use crate::api;
use crate::core;
use crate::repositories;
use crate::synchronizations;
use beteran_common_rust as bcr;
use beteran_protobuf_rust as bpr;
use diesel::{
r2d2::{ConnectionManager, Pool},
PgConnection,
};
use prost::Message;
use std::str::FromStr;
pub struct EventHandler {
connection_broker: nats::asynk::Connection,
queue_broker: String,
pool: Pool<ConnectionManager<PgConnection>>,
api_config: core::config::ApiConfig,
member_repository: repositories::member::repository::Repository,
member_account_api: api::member_account::api::Api,
member_account_synchronizer: synchronizations::member_account::synchronizer::Synchronizer,
}
impl std::fmt::Debug for EventHandler {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("EventHandler of members").finish()
}
}
impl EventHandler {
///
pub fn new(
connection_broker: nats::asynk::Connection,
queue_broker: String,
pool: Pool<ConnectionManager<PgConnection>>,
member_account_synchronizer: synchronizations::member_account::synchronizer::Synchronizer,
api_config: core::config::ApiConfig,
) -> EventHandler {
EventHandler {
connection_broker,
queue_broker,
pool,
member_account_synchronizer,
api_config: api_config.clone(),
member_repository: repositories::member::repository::Repository::new(),
member_account_api: api::member_account::api::Api::new(api_config.clone()),
}
}
pub async fn subscribe(&self) -> std::result::Result<(), std::boxed::Box<dyn std::error::Error>> {
futures::try_join!(self.event_after_update_member_bank_deposit_for_state()).map(|_| ())
}
async fn event_after_update_member_bank_deposit_for_state(
&self,
) -> Result<(), Box<dyn std::error::Error>> {
let s = self
.connection_broker
.queue_subscribe(
bpr::ss::member_bank_deposit::EVENT_SUBJECT_AFTER_UPDATE_MEMBER_BANK_DEPOSIT_FOR_STATE,
self.queue_broker.as_str(),
)
.await?;
while let Some(message) = s.next().await {
if let Err(e) = async {
let eve = bpr::ss::member_bank_deposit::AfterUpdateMemberBankDepositForState::decode(
message.data.as_slice(),
)
.map_err(|e| {
bcr::error::rpc::Error::InvalidRequest(bcr::error::rpc::InvalidRequest {
message: format!("invalid request: {}", e),
})
})?;
let client = match eve.client {
Some(c) => c,
None => {
return Err(bcr::error::rpc::Error::InvalidParams(
bcr::error::rpc::InvalidParams {
message: "invalid client information".to_string(),
detail: bcr::error::rpc::InvalidParamsDetail {
location: "request".to_string(),
param: "client".to_string(),
value: "".to_string(),
error_type: bcr::error::rpc::InvalidParamsType::Required,
message: "".to_string(),
},
},
));
}
};
let event = match eve.event {
Some(r) => r,
None => {
return Err(bcr::error::rpc::Error::InvalidParams(
bcr::error::rpc::InvalidParams {
message: "invalid event information".to_string(),
detail: bcr::error::rpc::InvalidParamsDetail {
location: "event".to_string(),
param: "event".to_string(),
value: "".to_string(),
error_type: bcr::error::rpc::InvalidParamsType::Required,
message: "".to_string(),
},
},
));
}
};
let member_bank_deposit = match event.member_bank_deposit {
Some(c) => c,
None => {
return Err(bcr::error::rpc::Error::InvalidParams(
bcr::error::rpc::InvalidParams {
message: "invalid event information".to_string(),
detail: bcr::error::rpc::InvalidParamsDetail {
location: "event".to_string(),
param: "member_bank_deposit".to_string(),
value: "".to_string(),
error_type: bcr::error::rpc::InvalidParamsType::Required,
message: "".to_string(),
},
},
));
}
};
let member = match member_bank_deposit.member {
Some(c) => c,
None => {
return Err(bcr::error::rpc::Error::InvalidParams(
bcr::error::rpc::InvalidParams {
message: "invalid event information".to_string(),
detail: bcr::error::rpc::InvalidParamsDetail {
location: "event".to_string(),
param: "member_bank_deposit.member".to_string(),
value: "".to_string(),
error_type: bcr::error::rpc::InvalidParamsType::Required,
message: "".to_string(),
},
},
));
}
};
let member_id = uuid::Uuid::from_str(member.id.as_str()).map_err(|e| {
bcr::error::rpc::Error::InvalidParams(bcr::error::rpc::InvalidParams {
message: "invalid member.id param".to_string(),
detail: bcr::error::rpc::InvalidParamsDetail {
location: "request".to_string(),
param: "member.id".to_string(),
value: member.id.clone(),
error_type: bcr::error::rpc::InvalidParamsType::Required,
message: e.to_string(),
},
})
})?;
let conn = self.pool.get().map_err(|e| {
bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {}", e),
data: None,
})
})?;
match beteran_protobuf_rust::models::member_bank_deposit::MemberBankDepositState::from_i32(
member_bank_deposit.state,
) {
Some(s) => {
if s == beteran_protobuf_rust::models::member_bank_deposit::MemberBankDepositState::Complete {
self.member_account_api.create_deposit(api::member_account::models::CreateDepositRequest{
username: member.username.clone(),
cash_type: None,
amount: member_bank_deposit.amount,
request_key: None,
}).await
.map_err(|e| {
bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {:?}", e),
data: None,
})
})?;
self.member_account_synchronizer.balance_for_user(member_id, &member.username).await
.map_err(|e| {
bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {:?}", e),
data: None,
})
})?;
}
}
None => {}
};
Ok::<(), bcr::error::rpc::Error>(())
}
.await
{
println!("error: {}", e);
}
}
Ok(())
}
}

View File

@ -0,0 +1 @@
pub mod event;

View File

@ -0,0 +1,206 @@
use crate::api;
use crate::core;
use crate::repositories;
use crate::synchronizations;
use beteran_common_rust as bcr;
use beteran_protobuf_rust as bpr;
use diesel::{
r2d2::{ConnectionManager, Pool},
PgConnection,
};
use prost::Message;
use std::str::FromStr;
pub struct EventHandler {
connection_broker: nats::asynk::Connection,
queue_broker: String,
pool: Pool<ConnectionManager<PgConnection>>,
api_config: core::config::ApiConfig,
member_repository: repositories::member::repository::Repository,
member_account_api: api::member_account::api::Api,
member_account_synchronizer: synchronizations::member_account::synchronizer::Synchronizer,
}
impl std::fmt::Debug for EventHandler {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("EventHandler of members").finish()
}
}
impl EventHandler {
///
pub fn new(
connection_broker: nats::asynk::Connection,
queue_broker: String,
pool: Pool<ConnectionManager<PgConnection>>,
member_account_synchronizer: synchronizations::member_account::synchronizer::Synchronizer,
api_config: core::config::ApiConfig,
) -> EventHandler {
EventHandler {
connection_broker,
queue_broker,
pool,
member_account_synchronizer,
api_config: api_config.clone(),
member_repository: repositories::member::repository::Repository::new(),
member_account_api: api::member_account::api::Api::new(api_config.clone()),
}
}
pub async fn subscribe(&self) -> std::result::Result<(), std::boxed::Box<dyn std::error::Error>> {
futures::try_join!(self.event_after_update_member_bank_withdraw_for_state()).map(|_| ())
}
async fn event_after_update_member_bank_withdraw_for_state(
&self,
) -> Result<(), Box<dyn std::error::Error>> {
let s = self
.connection_broker
.queue_subscribe(
bpr::ss::member_bank_withdraw::EVENT_SUBJECT_AFTER_UPDATE_MEMBER_BANK_WITHDRAW_FOR_STATE,
self.queue_broker.as_str(),
)
.await?;
while let Some(message) = s.next().await {
if let Err(e) = async {
let eve = bpr::ss::member_bank_withdraw::AfterUpdateMemberBankWithdrawForState::decode(
message.data.as_slice(),
)
.map_err(|e| {
bcr::error::rpc::Error::InvalidRequest(bcr::error::rpc::InvalidRequest {
message: format!("invalid request: {}", e),
})
})?;
let client = match eve.client {
Some(c) => c,
None => {
return Err(bcr::error::rpc::Error::InvalidParams(
bcr::error::rpc::InvalidParams {
message: "invalid client information".to_string(),
detail: bcr::error::rpc::InvalidParamsDetail {
location: "request".to_string(),
param: "client".to_string(),
value: "".to_string(),
error_type: bcr::error::rpc::InvalidParamsType::Required,
message: "".to_string(),
},
},
));
}
};
let event = match eve.event {
Some(r) => r,
None => {
return Err(bcr::error::rpc::Error::InvalidParams(
bcr::error::rpc::InvalidParams {
message: "invalid event information".to_string(),
detail: bcr::error::rpc::InvalidParamsDetail {
location: "event".to_string(),
param: "event".to_string(),
value: "".to_string(),
error_type: bcr::error::rpc::InvalidParamsType::Required,
message: "".to_string(),
},
},
));
}
};
let member_bank_withdraw = match event.member_bank_withdraw {
Some(c) => c,
None => {
return Err(bcr::error::rpc::Error::InvalidParams(
bcr::error::rpc::InvalidParams {
message: "invalid event information".to_string(),
detail: bcr::error::rpc::InvalidParamsDetail {
location: "event".to_string(),
param: "member_bank_withdraw".to_string(),
value: "".to_string(),
error_type: bcr::error::rpc::InvalidParamsType::Required,
message: "".to_string(),
},
},
));
}
};
let member = match member_bank_withdraw.member {
Some(c) => c,
None => {
return Err(bcr::error::rpc::Error::InvalidParams(
bcr::error::rpc::InvalidParams {
message: "invalid event information".to_string(),
detail: bcr::error::rpc::InvalidParamsDetail {
location: "event".to_string(),
param: "member_bank_withdraw.member".to_string(),
value: "".to_string(),
error_type: bcr::error::rpc::InvalidParamsType::Required,
message: "".to_string(),
},
},
));
}
};
let member_id = uuid::Uuid::from_str(member.id.as_str()).map_err(|e| {
bcr::error::rpc::Error::InvalidParams(bcr::error::rpc::InvalidParams {
message: "invalid member.id param".to_string(),
detail: bcr::error::rpc::InvalidParamsDetail {
location: "request".to_string(),
param: "member.id".to_string(),
value: member.id.clone(),
error_type: bcr::error::rpc::InvalidParamsType::Required,
message: e.to_string(),
},
})
})?;
let conn = self.pool.get().map_err(|e| {
bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {}", e),
data: None,
})
})?;
match beteran_protobuf_rust::models::member_bank_withdraw::MemberBankWithdrawState::from_i32(
member_bank_withdraw.state,
) {
Some(s) => {
if s == beteran_protobuf_rust::models::member_bank_withdraw::MemberBankWithdrawState::Complete {
self.member_account_api.create_withdraw(api::member_account::models::CreateWithdrawRequest{
username: member.username.clone(),
request_key: None,
}).await
.map_err(|e| {
bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {:?}", e),
data: None,
})
})?;
self.member_account_synchronizer.balance_for_user(member_id, &member.username).await
.map_err(|e| {
bcr::error::rpc::Error::Server(bcr::error::rpc::Server {
code: bpr::protobuf::rpc::Error::SERVER_00,
message: format!("server {:?}", e),
data: None,
})
})?;
}
}
None => {}
};
Ok::<(), bcr::error::rpc::Error>(())
}
.await
{
println!("error: {}", e);
}
}
Ok(())
}
}

View File

@ -0,0 +1 @@
pub mod event;

3
src/events/mod.rs Normal file
View File

@ -0,0 +1,3 @@
pub mod member;
pub mod member_bank_withdraw;
pub mod member_bank_deposit;

183
src/main.rs Normal file
View File

@ -0,0 +1,183 @@
//!
//!
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_migrations;
use diesel::{
r2d2::{ConnectionManager, Pool},
PgConnection,
};
use std::env;
mod api;
mod compositions;
mod core;
mod events;
mod repositories;
mod schedulers;
mod services;
mod synchronizations;
diesel_migrations::embed_migrations!();
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let url_db = match env::var_os("URL_DATABASE") {
Some(v) => v.into_string().unwrap(),
None => "".to_string(),
};
let url_broker = match env::var_os("URL_BROKER") {
Some(v) => v.into_string().unwrap(),
None => "".to_string(),
};
let queue_broker = match env::var_os("QUEUE_BROKER") {
Some(v) => v.into_string().unwrap(),
None => "".to_string(),
};
let k_url = match env::var_os("K_URL") {
Some(v) => v.into_string().unwrap(),
None => "".to_string(),
};
let k_username = match env::var_os("K_USERNAME") {
Some(v) => v.into_string().unwrap(),
None => "".to_string(),
};
let k_secret = match env::var_os("K_SECRET") {
Some(v) => v.into_string().unwrap(),
None => "".to_string(),
};
let api_config = core::config::ApiConfig {
k_url,
k_username,
k_secret,
};
let manager = ConnectionManager::<PgConnection>::new(url_db);
let pool = Pool::builder()
.max_size(10)
.test_on_check_out(true)
.build(manager)?;
let conn = pool.get()?;
embedded_migrations::run(&conn)?;
let broker_opts = nats::asynk::Options::new();
let connection_broker = broker_opts.connect(url_broker).await?;
let vendor_synchronizer =
synchronizations::vendor::synchronizer::Synchronizer::new(pool.clone(), api_config.clone());
let game_synchronizer =
synchronizations::game::synchronizer::Synchronizer::new(pool.clone(), api_config.clone());
let member_synchronizer = synchronizations::member::synchronizer::Synchronizer::new(
connection_broker.clone(),
pool.clone(),
api_config.clone(),
);
let member_account_synchronizer =
synchronizations::member_account::synchronizer::Synchronizer::new(
connection_broker.clone(),
pool.clone(),
api_config.clone(),
);
let betting_history_synchronizer =
synchronizations::betting_history::synchronizer::Synchronizer::new(
pool.clone(),
api_config.clone(),
);
let vendor_service = services::vendor::service::Service::new(
connection_broker.clone(),
queue_broker.clone(),
pool.clone(),
);
let game_service = services::game::service::Service::new(
connection_broker.clone(),
queue_broker.clone(),
pool.clone(),
api_config.clone(),
);
let member_service =
services::member::service::Service::new(connection_broker.clone(), queue_broker.clone());
let member_account_service = services::member_account::service::Service::new(
connection_broker.clone(),
queue_broker.clone(),
);
let betting_service = services::betting::service::Service::new(
connection_broker.clone(),
queue_broker.clone(),
pool.clone(),
);
let member_event_handler = events::member::event::EventHandler::new(
connection_broker.clone(),
queue_broker.clone(),
pool.clone(),
api_config.clone(),
);
let member_bank_deposit_event_handler = events::member_bank_deposit::event::EventHandler::new(
connection_broker.clone(),
queue_broker.clone(),
pool.clone(),
member_account_synchronizer.clone(),
api_config.clone(),
);
let member_bank_withdraw_event_handler = events::member_bank_withdraw::event::EventHandler::new(
connection_broker.clone(),
queue_broker.clone(),
pool.clone(),
member_account_synchronizer.clone(),
api_config.clone(),
);
let mut sched = tokio_cron_scheduler::JobScheduler::new().await?;
let game_scheduler = schedulers::game::scheduler::Scheduler::get_instance(
sched.clone(),
vendor_synchronizer.clone(),
game_synchronizer.clone(),
)?;
game_scheduler.queue().await?;
let member_scheduler = schedulers::member::scheduler::Scheduler::get_instance(
sched.clone(),
member_synchronizer.clone(),
)?;
member_scheduler.queue().await?;
let balance_scheduler = schedulers::balance::scheduler::Scheduler::get_instance(
sched.clone(),
member_account_synchronizer.clone(),
)?;
balance_scheduler.queue().await?;
let betting_history_scheduler = schedulers::betting_history::scheduler::Scheduler::get_instance(
sched.clone(),
betting_history_synchronizer.clone(),
)?;
betting_history_scheduler.queue().await?;
let _h_scheduler = sched.start().await?;
println!("Server service [beteran-api-kgon-server-service] is started");
futures::try_join!(
vendor_service.subscribe(),
game_service.subscribe(),
betting_service.subscribe(),
// member_service.subscribe(),
// member_account_service.subscribe(),
// betting_service.subscribe(),
member_event_handler.subscribe(),
member_bank_deposit_event_handler.subscribe(),
member_bank_withdraw_event_handler.subscribe(),
)?;
sched.shutdown().await?;
Ok(())
}

View File

@ -0,0 +1,9 @@
//!
//!
///
pub mod models;
///
pub mod repository;
///
pub mod schema;

View File

@ -0,0 +1,37 @@
use super::schema::api_kgon_balances;
///
#[derive(Identifiable, Queryable, PartialEq, Debug, Clone)]
#[table_name = "api_kgon_balances"]
pub struct Balance {
///
pub id: i32,
///
pub balance: f64,
///
pub balance_bota: f64,
///
pub created_at: i64,
///
pub updated_at: i64,
}
///
#[derive(Insertable, Debug, Clone)]
#[table_name = "api_kgon_balances"]
pub struct NewBalance {
///
pub balance: f64,
///
pub balance_bota: f64,
}
///
#[derive(AsChangeset, Debug, Clone)]
#[table_name = "api_kgon_balances"]
pub struct ModifyBalance {
///
pub balance: f64,
///
pub balance_bota: f64,
}

View File

@ -0,0 +1,75 @@
//!
//!
use super::{models, schema::api_kgon_balances};
use diesel::prelude::*;
use diesel::result::Error;
///
pub struct Repository {}
impl std::fmt::Debug for Repository {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Repository of api_kgon_balances").finish()
}
}
impl Default for Repository {
fn default() -> Self {
Self::new()
}
}
impl Repository {
///
pub fn new() -> Repository {
Repository {}
}
///
pub fn insert(
&self,
conn: &diesel::PgConnection,
new_member: &models::NewBalance,
) -> Result<models::Balance, Error> {
let inserted = diesel::insert_into(api_kgon_balances::table)
.values(new_member)
.get_result::<models::Balance>(conn)?;
Ok(inserted)
}
///
pub fn select(&self, conn: &diesel::PgConnection) -> Result<Option<models::Balance>, Error> {
match api_kgon_balances::table.first::<models::Balance>(conn) {
Ok(m) => Ok(Some(m)),
Err(e) => match e {
diesel::result::Error::NotFound => Ok(None),
_ => Err(e),
},
}
}
///
pub fn update(
&self,
conn: &diesel::PgConnection,
id: i32,
modify: &models::ModifyBalance,
) -> Result<u64, Error> {
use api_kgon_balances::dsl;
diesel::update(dsl::api_kgon_balances.filter(dsl::id.eq(id)))
.set(modify)
.execute(conn)
.map(|c| c as u64)
}
///
pub fn delete(&self, conn: &diesel::PgConnection, id: i32) -> Result<u64, Error> {
use api_kgon_balances::dsl;
diesel::delete(api_kgon_balances::table.filter(dsl::id.eq(id)))
.execute(conn)
.map(|c| c as u64)
}
}

View File

@ -0,0 +1,18 @@
//!
//!
table! {
///
api_kgon_balances(id) {
///
id -> Integer,
///
balance -> Double,
///
balance_bota -> Double,
///
created_at -> BigInt,
///
updated_at -> BigInt,
}
}

View File

@ -0,0 +1,9 @@
//!
//!
///
pub mod models;
///
pub mod repository;
///
pub mod schema;

View File

@ -0,0 +1,158 @@
use super::schema::api_kgon_betting_history;
use beteran_common_rust as bcr;
///
#[derive(Identifiable, Queryable, PartialEq, Debug, Clone)]
#[table_name = "api_kgon_betting_history"]
pub struct BettingHistory {
///
pub id: String,
///
pub vendor_id: i64,
///
pub vendor_name: String,
///
pub game_id: i64,
///
pub game_name: String,
///
pub game_category: String,
///
pub game_type: String,
///
pub currency: String,
///
pub cash: f64,
///
pub before_cash: f64,
///
pub after_cash: f64,
///
pub group_key: Option<String>,
///
pub detail: Option<String>,
///
pub is_bonus: bool,
///
pub is_promo: bool,
///
pub is_jackpot: bool,
///
pub site_username: String,
///
pub key: String,
///
pub ref_id: String,
///
pub o_ref_id: Option<String>,
///
pub betting_type: String,
///
pub category: String,
///
pub created_at: i64,
///
pub utc_created_at: i64,
}
///
#[derive(Insertable, Debug, Clone)]
#[table_name = "api_kgon_betting_history"]
pub struct NewBettingHistory {
///
pub id: String,
///
pub vendor_id: i64,
///
pub vendor_name: String,
///
pub game_id: i64,
///
pub game_name: String,
///
pub game_category: String,
///
pub game_type: String,
///
pub currency: String,
///
pub cash: f64,
///
pub before_cash: f64,
///
pub after_cash: f64,
///
pub group_key: Option<String>,
///
pub detail: Option<String>,
///
pub is_bonus: bool,
///
pub is_promo: bool,
///
pub is_jackpot: bool,
///
pub site_username: String,
///
pub key: String,
///
pub ref_id: String,
///
pub o_ref_id: Option<String>,
///
pub betting_type: String,
///
pub category: String,
///
pub created_at: i64,
///
pub utc_created_at: i64,
}
///
#[derive(Debug, Clone)]
pub struct FindAllSearch {
///
pub vendor_id: Option<i64>,
///
pub vendor_name_like: Option<String>,
///
pub game_id: Option<i64>,
///
pub game_name_like: Option<String>,
///
pub game_category_like: Option<String>,
///
pub game_type_like: Option<String>,
///
pub currency_like: Option<String>,
///
pub key_like: Option<String>,
///
pub ref_id_like: Option<String>,
///
pub o_ref_id_like: Option<String>,
///
pub group_key_like: Option<String>,
///
pub is_bonus: Option<bool>,
///
pub is_promo: Option<bool>,
///
pub is_jackpot: Option<bool>,
///
pub site_username_like: Option<String>,
///
pub betting_type_like: Option<String>,
///
pub category_like: Option<String>,
}
///
#[derive(Debug, Clone)]
pub struct FindAll {
pub search: Option<FindAllSearch>,
///
pub pagination: Option<bcr::pagination::Pagination>,
///
pub sorts: Option<Vec<bcr::pagination::Sort>>,
}

View File

@ -0,0 +1,366 @@
//!
//!
use super::{models, schema::api_kgon_betting_history};
use beteran_common_rust as bcr;
use diesel::prelude::*;
use diesel::result::Error;
///
pub struct Repository {}
impl std::fmt::Debug for Repository {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Repository of api_kgon_betting_history")
.finish()
}
}
impl Default for Repository {
fn default() -> Self {
Self::new()
}
}
impl Repository {
///
pub fn new() -> Repository {
Repository {}
}
///
pub fn insert(
&self,
conn: &diesel::PgConnection,
new_betting_history: &models::NewBettingHistory,
) -> Result<(), Error> {
diesel::insert_into(api_kgon_betting_history::table)
.values(new_betting_history)
.execute(conn)?;
Ok(())
}
///
pub fn inserts(
&self,
conn: &diesel::PgConnection,
new_betting_history: &Vec<models::NewBettingHistory>,
) -> Result<(), Error> {
use api_kgon_betting_history::dsl;
diesel::insert_into(api_kgon_betting_history::table)
.values(new_betting_history)
.on_conflict(dsl::id)
.do_nothing()
.execute(conn)?;
Ok(())
}
///
pub fn select(
&self,
conn: &diesel::PgConnection,
id: String,
) -> Result<Option<models::BettingHistory>, Error> {
match api_kgon_betting_history::table
.find(id)
.first::<models::BettingHistory>(conn)
{
Ok(m) => Ok(Some(m)),
Err(e) => match e {
diesel::result::Error::NotFound => Ok(None),
_ => Err(e),
},
}
}
///
pub fn select_all_count(
&self,
conn: &diesel::PgConnection,
find_all: &models::FindAll,
) -> Result<i64, Error> {
let mut q = api_kgon_betting_history::table.into_boxed();
if let Some(s) = &find_all.search {
if let Some(sp) = s.vendor_id {
q = q.filter(api_kgon_betting_history::dsl::vendor_id.eq(sp));
}
if let Some(sp) = &s.vendor_name_like {
q = q.filter(api_kgon_betting_history::dsl::vendor_name.like(sp));
}
if let Some(sp) = s.game_id {
q = q.filter(api_kgon_betting_history::dsl::game_id.eq(sp));
}
if let Some(sp) = &s.game_name_like {
q = q.filter(api_kgon_betting_history::dsl::game_name.like(sp));
}
if let Some(sp) = &s.game_category_like {
q = q.filter(api_kgon_betting_history::dsl::game_category.like(sp));
}
if let Some(sp) = &s.game_type_like {
q = q.filter(api_kgon_betting_history::dsl::game_type.like(sp));
}
if let Some(sp) = &s.currency_like {
q = q.filter(api_kgon_betting_history::dsl::currency.like(sp));
}
if let Some(sp) = &s.key_like {
q = q.filter(api_kgon_betting_history::dsl::key.like(sp));
}
if let Some(sp) = &s.ref_id_like {
q = q.filter(api_kgon_betting_history::dsl::ref_id.like(sp));
}
if let Some(sp) = &s.o_ref_id_like {
q = q.filter(api_kgon_betting_history::dsl::o_ref_id.like(sp));
}
if let Some(sp) = &s.group_key_like {
q = q.filter(api_kgon_betting_history::dsl::group_key.like(sp));
}
if let Some(sp) = s.is_bonus {
q = q.filter(api_kgon_betting_history::dsl::is_bonus.eq(sp));
}
if let Some(sp) = s.is_promo {
q = q.filter(api_kgon_betting_history::dsl::is_promo.eq(sp));
}
if let Some(sp) = s.is_jackpot {
q = q.filter(api_kgon_betting_history::dsl::is_jackpot.eq(sp));
}
if let Some(sp) = &s.site_username_like {
q = q.filter(api_kgon_betting_history::dsl::site_username.like(sp));
}
if let Some(sp) = &s.betting_type_like {
q = q.filter(api_kgon_betting_history::dsl::betting_type.like(sp));
}
if let Some(sp) = &s.category_like {
q = q.filter(api_kgon_betting_history::dsl::category.like(sp));
}
}
q.count().get_result(conn)
}
///
pub fn select_all(
&self,
conn: &diesel::PgConnection,
find_all: &models::FindAll,
) -> Result<Vec<models::BettingHistory>, Error> {
let mut q = api_kgon_betting_history::table.into_boxed();
if let Some(s) = &find_all.search {
if let Some(sp) = s.vendor_id {
q = q.filter(api_kgon_betting_history::dsl::vendor_id.eq(sp));
}
if let Some(sp) = &s.vendor_name_like {
q = q.filter(api_kgon_betting_history::dsl::vendor_name.like(sp));
}
if let Some(sp) = s.game_id {
q = q.filter(api_kgon_betting_history::dsl::game_id.eq(sp));
}
if let Some(sp) = &s.game_name_like {
q = q.filter(api_kgon_betting_history::dsl::game_name.like(sp));
}
if let Some(sp) = &s.game_category_like {
q = q.filter(api_kgon_betting_history::dsl::game_category.like(sp));
}
if let Some(sp) = &s.game_type_like {
q = q.filter(api_kgon_betting_history::dsl::game_type.like(sp));
}
if let Some(sp) = &s.currency_like {
q = q.filter(api_kgon_betting_history::dsl::currency.like(sp));
}
if let Some(sp) = &s.key_like {
q = q.filter(api_kgon_betting_history::dsl::key.like(sp));
}
if let Some(sp) = &s.ref_id_like {
q = q.filter(api_kgon_betting_history::dsl::ref_id.like(sp));
}
if let Some(sp) = &s.o_ref_id_like {
q = q.filter(api_kgon_betting_history::dsl::o_ref_id.like(sp));
}
if let Some(sp) = &s.group_key_like {
q = q.filter(api_kgon_betting_history::dsl::group_key.like(sp));
}
if let Some(sp) = s.is_bonus {
q = q.filter(api_kgon_betting_history::dsl::is_bonus.eq(sp));
}
if let Some(sp) = s.is_promo {
q = q.filter(api_kgon_betting_history::dsl::is_promo.eq(sp));
}
if let Some(sp) = s.is_jackpot {
q = q.filter(api_kgon_betting_history::dsl::is_jackpot.eq(sp));
}
if let Some(sp) = &s.site_username_like {
q = q.filter(api_kgon_betting_history::dsl::site_username.like(sp));
}
if let Some(sp) = &s.betting_type_like {
q = q.filter(api_kgon_betting_history::dsl::betting_type.like(sp));
}
if let Some(sp) = &s.category_like {
q = q.filter(api_kgon_betting_history::dsl::category.like(sp));
}
}
if let Some(p) = &find_all.pagination {
let page = p.page.unwrap_or(1);
if let Some(page_size) = p.page_size {
q = q.offset(((page - 1) * page_size) as i64);
q = q.limit(page_size as i64);
}
}
if let Some(orderbys) = &find_all.sorts {
for s in orderbys {
match s {
bcr::pagination::Sort::ASC(property) => match property.as_str() {
"id" => {
q = q.order_by(api_kgon_betting_history::id.asc());
}
"vendor_id" => {
q = q.order_by(api_kgon_betting_history::vendor_id.asc());
}
"vendor_name" => {
q = q.order_by(api_kgon_betting_history::vendor_name.asc());
}
"game_id" => {
q = q.order_by(api_kgon_betting_history::game_id.asc());
}
"game_name" => {
q = q.order_by(api_kgon_betting_history::game_name.asc());
}
"game_category" => {
q = q.order_by(api_kgon_betting_history::game_category.asc());
}
"game_type" => {
q = q.order_by(api_kgon_betting_history::game_type.asc());
}
"currency" => {
q = q.order_by(api_kgon_betting_history::currency.asc());
}
"cash" => {
q = q.order_by(api_kgon_betting_history::cash.asc());
}
"before_cash" => {
q = q.order_by(api_kgon_betting_history::before_cash.asc());
}
"after_cash" => {
q = q.order_by(api_kgon_betting_history::after_cash.asc());
}
"key" => {
q = q.order_by(api_kgon_betting_history::key.asc());
}
"ref_id" => {
q = q.order_by(api_kgon_betting_history::ref_id.asc());
}
"o_ref_id" => {
q = q.order_by(api_kgon_betting_history::o_ref_id.asc());
}
"group_key" => {
q = q.order_by(api_kgon_betting_history::group_key.asc());
}
"is_bonus" => {
q = q.order_by(api_kgon_betting_history::is_bonus.asc());
}
"is_promo" => {
q = q.order_by(api_kgon_betting_history::is_promo.asc());
}
"is_jackpot" => {
q = q.order_by(api_kgon_betting_history::is_jackpot.asc());
}
"site_username" => {
q = q.order_by(api_kgon_betting_history::site_username.asc());
}
"betting_type" => {
q = q.order_by(api_kgon_betting_history::betting_type.asc());
}
"category" => {
q = q.order_by(api_kgon_betting_history::category.asc());
}
"created_at" => {
q = q.order_by(api_kgon_betting_history::created_at.asc());
}
"utc_created_at" => {
q = q.order_by(api_kgon_betting_history::utc_created_at.asc());
}
_ => {}
},
bcr::pagination::Sort::DESC(property) => match property.as_str() {
"id" => {
q = q.order_by(api_kgon_betting_history::id.desc());
}
"vendor_id" => {
q = q.order_by(api_kgon_betting_history::vendor_id.desc());
}
"vendor_name" => {
q = q.order_by(api_kgon_betting_history::vendor_name.desc());
}
"game_id" => {
q = q.order_by(api_kgon_betting_history::game_id.desc());
}
"game_name" => {
q = q.order_by(api_kgon_betting_history::game_name.desc());
}
"game_category" => {
q = q.order_by(api_kgon_betting_history::game_category.desc());
}
"game_type" => {
q = q.order_by(api_kgon_betting_history::game_type.desc());
}
"currency" => {
q = q.order_by(api_kgon_betting_history::currency.desc());
}
"cash" => {
q = q.order_by(api_kgon_betting_history::cash.desc());
}
"before_cash" => {
q = q.order_by(api_kgon_betting_history::before_cash.desc());
}
"after_cash" => {
q = q.order_by(api_kgon_betting_history::after_cash.desc());
}
"key" => {
q = q.order_by(api_kgon_betting_history::key.desc());
}
"ref_id" => {
q = q.order_by(api_kgon_betting_history::ref_id.desc());
}
"o_ref_id" => {
q = q.order_by(api_kgon_betting_history::o_ref_id.desc());
}
"group_key" => {
q = q.order_by(api_kgon_betting_history::group_key.desc());
}
"is_bonus" => {
q = q.order_by(api_kgon_betting_history::is_bonus.desc());
}
"is_promo" => {
q = q.order_by(api_kgon_betting_history::is_promo.desc());
}
"is_jackpot" => {
q = q.order_by(api_kgon_betting_history::is_jackpot.desc());
}
"site_username" => {
q = q.order_by(api_kgon_betting_history::site_username.desc());
}
"betting_type" => {
q = q.order_by(api_kgon_betting_history::betting_type.desc());
}
"category" => {
q = q.order_by(api_kgon_betting_history::category.desc());
}
"created_at" => {
q = q.order_by(api_kgon_betting_history::created_at.desc());
}
"utc_created_at" => {
q = q.order_by(api_kgon_betting_history::utc_created_at.desc());
}
_ => {}
},
};
}
}
q.load::<models::BettingHistory>(conn)
}
}

View File

@ -0,0 +1,56 @@
//!
//!
table! {
///
api_kgon_betting_history(id) {
///
id -> Text,
///
vendor_id -> BigInt,
///
vendor_name -> Text,
///
game_id -> BigInt,
///
game_name -> Text,
///
game_category -> Text,
///
game_type -> Text,
///
currency -> Text,
///
cash -> Double,
///
before_cash -> Double,
///
after_cash -> Double,
///
group_key -> Nullable<Text>,
///
detail -> Nullable<Text>,
///
is_bonus -> Bool,
///
is_promo -> Bool,
///
is_jackpot -> Bool,
///
site_username -> Text,
///
key -> Text,
///
ref_id -> Text,
///
o_ref_id -> Nullable<Text>,
///
betting_type -> Text,
///
category -> Text,
///
created_at -> BigInt,
///
utc_created_at -> BigInt,
}
}

View File

@ -0,0 +1,9 @@
//!
//!
///
pub mod models;
///
pub mod repository;
///
pub mod schema;

View File

@ -0,0 +1,114 @@
use super::schema::api_kgon_games;
use beteran_common_rust as bcr;
///
#[derive(Eq, Hash, Identifiable, Queryable, PartialEq, Debug, Clone)]
#[table_name = "api_kgon_games"]
pub struct Game {
///
pub id: i64,
///
pub parent_id: i64,
///
pub key: String,
///
pub names: String,
///
pub platform: String,
///
pub category: String,
///
pub game_type: String,
///
pub image: Option<String>,
///
pub created_at: i64,
///
pub updated_at: i64,
}
///
#[derive(Insertable, Debug, Clone)]
#[table_name = "api_kgon_games"]
pub struct NewGame {
///
pub id: i64,
///
pub parent_id: i64,
///
pub key: String,
///
pub names: String,
///
pub platform: String,
///
pub category: String,
///
pub game_type: String,
///
pub image: Option<String>,
}
///
#[derive(AsChangeset, Debug, Clone)]
#[table_name = "api_kgon_games"]
pub struct ModifyGame {
///
pub key: String,
///
pub names: String,
///
pub platform: String,
///
pub category: String,
///
pub game_type: String,
///
pub image: Option<String>,
}
///
#[derive(Insertable, AsChangeset, Debug, Clone)]
#[table_name = "api_kgon_games"]
pub struct UpsertGame {
///
pub id: i64,
///
pub parent_id: i64,
///
pub key: String,
///
pub names: String,
///
pub platform: String,
///
pub category: String,
///
pub game_type: String,
///
pub image: Option<String>,
}
///
#[derive(Debug, Clone)]
pub struct FindAllSearch {
///
pub parent_id: Option<i64>,
///
pub key_like: Option<String>,
///
pub platform_like: Option<String>,
///
pub category_like: Option<String>,
///
pub game_type_like: Option<String>,
}
///
#[derive(Debug, Clone)]
pub struct FindAll {
pub search: Option<FindAllSearch>,
///
pub pagination: Option<bcr::pagination::Pagination>,
///
pub sorts: Option<Vec<bcr::pagination::Sort>>,
}

View File

@ -0,0 +1,228 @@
//!
//!
use super::{models, schema::api_kgon_games};
use beteran_common_rust as bcr;
use diesel::prelude::*;
use diesel::result::Error;
///
pub struct Repository {}
impl std::fmt::Debug for Repository {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Repository of api_kgon_games").finish()
}
}
impl Default for Repository {
fn default() -> Self {
Self::new()
}
}
impl Repository {
///
pub fn new() -> Repository {
Repository {}
}
///
pub fn insert(
&self,
conn: &diesel::PgConnection,
new_member: &models::NewGame,
) -> Result<models::Game, Error> {
let inserted = diesel::insert_into(api_kgon_games::table)
.values(new_member)
.get_result::<models::Game>(conn)?;
Ok(inserted)
}
///
pub fn upserts(
&self,
conn: &diesel::PgConnection,
upsert_games: Vec<models::UpsertGame>,
) -> Result<usize, Error> {
use api_kgon_games::dsl;
use diesel::pg::upsert::excluded;
let affected = diesel::insert_into(api_kgon_games::table)
.values(upsert_games)
.on_conflict(dsl::id)
.do_update()
.set((
dsl::parent_id.eq(excluded(dsl::parent_id)),
dsl::key.eq(excluded(dsl::key)),
dsl::names.eq(excluded(dsl::names)),
dsl::platform.eq(excluded(dsl::platform)),
dsl::category.eq(excluded(dsl::category)),
dsl::game_type.eq(excluded(dsl::game_type)),
dsl::image.eq(excluded(dsl::image)),
))
.execute(conn)?;
Ok(affected)
}
///
pub fn select(
&self,
conn: &diesel::PgConnection,
id: i64,
) -> Result<Option<models::Game>, Error> {
match api_kgon_games::table.find(id).first::<models::Game>(conn) {
Ok(m) => Ok(Some(m)),
Err(e) => match e {
diesel::result::Error::NotFound => Ok(None),
_ => Err(e),
},
}
}
///
pub fn select_all_count(
&self,
conn: &diesel::PgConnection,
find_all: &models::FindAll,
) -> Result<i64, Error> {
let mut q = api_kgon_games::table.into_boxed();
if let Some(s) = &find_all.search {
if let Some(sp) = s.parent_id {
q = q.filter(api_kgon_games::dsl::parent_id.eq(sp));
}
if let Some(sp) = &s.key_like {
q = q.filter(api_kgon_games::dsl::key.like(sp));
}
if let Some(sp) = &s.platform_like {
q = q.filter(api_kgon_games::dsl::platform.like(sp));
}
if let Some(sp) = &s.category_like {
q = q.filter(api_kgon_games::dsl::category.like(sp));
}
if let Some(sp) = &s.game_type_like {
q = q.filter(api_kgon_games::dsl::game_type.like(sp));
}
}
q.count().get_result(conn)
}
///
pub fn select_all(
&self,
conn: &diesel::PgConnection,
find_all: &models::FindAll,
) -> Result<Vec<models::Game>, Error> {
let mut q = api_kgon_games::table.into_boxed();
if let Some(s) = &find_all.search {
if let Some(sp) = s.parent_id {
q = q.filter(api_kgon_games::dsl::parent_id.eq(sp));
}
if let Some(sp) = &s.key_like {
q = q.filter(api_kgon_games::dsl::key.like(sp));
}
if let Some(sp) = &s.platform_like {
q = q.filter(api_kgon_games::dsl::platform.like(sp));
}
if let Some(sp) = &s.category_like {
q = q.filter(api_kgon_games::dsl::category.like(sp));
}
if let Some(sp) = &s.game_type_like {
q = q.filter(api_kgon_games::dsl::game_type.like(sp));
}
}
if let Some(p) = &find_all.pagination {
let page = p.page.unwrap_or(1);
if let Some(page_size) = p.page_size {
q = q.offset(((page - 1) * page_size) as i64);
q = q.limit(page_size as i64);
}
}
if let Some(orderbys) = &find_all.sorts {
for s in orderbys {
match s {
bcr::pagination::Sort::ASC(property) => match property.as_str() {
"parent_id" => {
q = q.order_by(api_kgon_games::parent_id.asc());
}
"key" => {
q = q.order_by(api_kgon_games::key.asc());
}
"platform" => {
q = q.order_by(api_kgon_games::platform.asc());
}
"category" => {
q = q.order_by(api_kgon_games::category.asc());
}
"game_type" => {
q = q.order_by(api_kgon_games::game_type.asc());
}
"created_at" => {
q = q.order_by(api_kgon_games::created_at.asc());
}
"updated_at" => {
q = q.order_by(api_kgon_games::updated_at.asc());
}
_ => {}
},
bcr::pagination::Sort::DESC(property) => match property.as_str() {
"parent_id" => {
q = q.order_by(api_kgon_games::parent_id.desc());
}
"key" => {
q = q.order_by(api_kgon_games::key.desc());
}
"platform" => {
q = q.order_by(api_kgon_games::platform.desc());
}
"category" => {
q = q.order_by(api_kgon_games::category.desc());
}
"game_type" => {
q = q.order_by(api_kgon_games::game_type.desc());
}
"created_at" => {
q = q.order_by(api_kgon_games::created_at.desc());
}
"updated_at" => {
q = q.order_by(api_kgon_games::updated_at.desc());
}
_ => {}
},
};
}
}
q.load::<models::Game>(conn)
}
///
pub fn update(
&self,
conn: &diesel::PgConnection,
id: i64,
modify: &models::ModifyGame,
) -> Result<u64, Error> {
use api_kgon_games::dsl;
diesel::update(dsl::api_kgon_games.filter(dsl::id.eq(id)))
.set(modify)
.execute(conn)
.map(|c| c as u64)
}
///
pub fn delete(&self, conn: &diesel::PgConnection, id: i64) -> Result<u64, Error> {
use api_kgon_games::dsl;
diesel::delete(api_kgon_games::table.filter(dsl::id.eq(id)))
.execute(conn)
.map(|c| c as u64)
}
}

View File

@ -0,0 +1,28 @@
//!
//!
table! {
///
api_kgon_games(id) {
///
id -> BigInt,
///
parent_id -> BigInt,
///
key -> Text,
///
names -> Text,
///
platform -> Text,
///
category -> Text,
///
game_type -> Text,
///
image -> Nullable<Text>,
///
created_at -> BigInt,
///
updated_at -> BigInt,
}
}

View File

@ -0,0 +1,9 @@
//!
//!
///
pub mod models;
///
pub mod repository;
///
pub mod schema;

View File

@ -0,0 +1,78 @@
use super::schema::api_kgon_members;
use beteran_common_rust as bcr;
///
#[derive(Identifiable, Queryable, PartialEq, Debug, Clone)]
#[table_name = "api_kgon_members"]
pub struct Member {
///
pub id: i64,
///
pub balance: f64,
///
pub balance_bota: f64,
///
pub balance_sum: f64,
///
pub companies: Option<String>,
///
pub oriental_play: String,
///
pub member_id: uuid::Uuid,
///
pub created_at: i64,
///
pub updated_at: i64,
}
///
#[derive(Insertable, Debug, Clone)]
#[table_name = "api_kgon_members"]
pub struct NewMember {
///
pub id: i64,
///
pub member_id: uuid::Uuid,
}
///
#[derive(AsChangeset, Debug, Clone)]
#[table_name = "api_kgon_members"]
pub struct ModifyMember {
///
pub balance: f64,
///
pub balance_bota: f64,
///
pub oriental_play: String,
}
///
#[derive(AsChangeset, Debug, Clone)]
#[table_name = "api_kgon_members"]
pub struct ModifyMemberForBalance {
///
pub balance: f64,
///
pub balance_bota: f64,
///
pub balance_sum: f64,
///
pub companies: Option<String>,
}
///
#[derive(Debug, Clone)]
pub struct FindAllSearch {
///
pub oriental_play: Option<String>,
}
///
#[derive(Debug, Clone)]
pub struct FindAll {
pub search: Option<FindAllSearch>,
///
pub pagination: Option<bcr::pagination::Pagination>,
///
pub sorts: Option<Vec<bcr::pagination::Sort>>,
}

View File

@ -0,0 +1,215 @@
//!
//!
use super::{models, schema::api_kgon_members};
use beteran_common_rust as bcr;
use diesel::prelude::*;
use diesel::result::Error;
///
pub struct Repository {}
impl std::fmt::Debug for Repository {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Repository of api_kgon_members").finish()
}
}
impl Default for Repository {
fn default() -> Self {
Self::new()
}
}
impl Repository {
///
pub fn new() -> Repository {
Repository {}
}
///
pub fn insert(
&self,
conn: &diesel::PgConnection,
new_member: &models::NewMember,
) -> Result<models::Member, Error> {
let inserted = diesel::insert_into(api_kgon_members::table)
.values(new_member)
.get_result::<models::Member>(conn)?;
Ok(inserted)
}
///
pub fn select(
&self,
conn: &diesel::PgConnection,
id: i64,
) -> Result<Option<models::Member>, Error> {
match api_kgon_members::table
.find(id)
.first::<models::Member>(conn)
{
Ok(m) => Ok(Some(m)),
Err(e) => match e {
diesel::result::Error::NotFound => Ok(None),
_ => Err(e),
},
}
}
///
pub fn select_by_member_id(
&self,
conn: &diesel::PgConnection,
member_id: uuid::Uuid,
) -> Result<Option<models::Member>, Error> {
use api_kgon_members::dsl;
match api_kgon_members::table
.filter(dsl::member_id.eq(member_id))
.first::<models::Member>(conn)
{
Ok(m) => Ok(Some(m)),
Err(e) => match e {
diesel::result::Error::NotFound => Ok(None),
_ => Err(e),
},
}
}
///
pub fn select_all_count(
&self,
conn: &diesel::PgConnection,
find_all: &models::FindAll,
) -> Result<i64, Error> {
let mut q = api_kgon_members::table.into_boxed();
if let Some(s) = &find_all.search {
if let Some(sp) = &s.oriental_play {
q = q.filter(api_kgon_members::dsl::oriental_play.eq(sp));
}
}
q.count().get_result(conn)
}
///
pub fn select_all(
&self,
conn: &diesel::PgConnection,
find_all: &models::FindAll,
) -> Result<Vec<models::Member>, Error> {
let mut q = api_kgon_members::table.into_boxed();
if let Some(s) = &find_all.search {
if let Some(sp) = &s.oriental_play {
q = q.filter(api_kgon_members::dsl::oriental_play.eq(sp));
}
}
if let Some(p) = &find_all.pagination {
let page = p.page.unwrap_or(1);
if let Some(page_size) = p.page_size {
q = q.offset(((page - 1) * page_size) as i64);
q = q.limit(page_size as i64);
}
}
if let Some(orderbys) = &find_all.sorts {
for s in orderbys {
match s {
bcr::pagination::Sort::ASC(property) => match property.as_str() {
"balance" => {
q = q.order_by(api_kgon_members::balance.asc());
}
"balance_bota" => {
q = q.order_by(api_kgon_members::balance_bota.asc());
}
"balance_sum" => {
q = q.order_by(api_kgon_members::balance_sum.asc());
}
"companies" => {
q = q.order_by(api_kgon_members::companies.asc());
}
"oriental_play" => {
q = q.order_by(api_kgon_members::oriental_play.asc());
}
"created_at" => {
q = q.order_by(api_kgon_members::created_at.asc());
}
"updated_at" => {
q = q.order_by(api_kgon_members::updated_at.asc());
}
_ => {}
},
bcr::pagination::Sort::DESC(property) => match property.as_str() {
"balance" => {
q = q.order_by(api_kgon_members::balance.desc());
}
"balance_bota" => {
q = q.order_by(api_kgon_members::balance_bota.desc());
}
"balance_sum" => {
q = q.order_by(api_kgon_members::balance_sum.desc());
}
"companies" => {
q = q.order_by(api_kgon_members::companies.desc());
}
"oriental_play" => {
q = q.order_by(api_kgon_members::oriental_play.desc());
}
"created_at" => {
q = q.order_by(api_kgon_members::created_at.desc());
}
"updated_at" => {
q = q.order_by(api_kgon_members::updated_at.desc());
}
_ => {}
},
};
}
}
q.load::<models::Member>(conn)
}
///
pub fn update(
&self,
conn: &diesel::PgConnection,
id: i64,
modify: &models::ModifyMember,
) -> Result<u64, Error> {
use api_kgon_members::dsl;
diesel::update(dsl::api_kgon_members.filter(dsl::id.eq(id)))
.set(modify)
.execute(conn)
.map(|c| c as u64)
}
///
pub fn update_balance(
&self,
conn: &diesel::PgConnection,
id: i64,
modify: &models::ModifyMemberForBalance,
) -> Result<u64, Error> {
use api_kgon_members::dsl;
diesel::update(dsl::api_kgon_members.filter(dsl::id.eq(id)))
.set(modify)
.execute(conn)
.map(|c| c as u64)
}
///
pub fn delete(&self, conn: &diesel::PgConnection, id: i64) -> Result<u64, Error> {
use api_kgon_members::dsl;
diesel::delete(api_kgon_members::table.filter(dsl::id.eq(id)))
.execute(conn)
.map(|c| c as u64)
}
}

View File

@ -0,0 +1,26 @@
//!
//!
table! {
///
api_kgon_members(id) {
///
id -> BigInt,
///
balance -> Double,
///
balance_bota -> Double,
///
balance_sum -> Double,
///
companies -> Nullable<Text>,
///
oriental_play -> Text,
///
member_id -> Uuid,
///
created_at -> BigInt,
///
updated_at -> BigInt,
}
}

7
src/repositories/mod.rs Normal file
View File

@ -0,0 +1,7 @@
pub mod balance;
pub mod betting_history;
pub mod game;
pub mod member;
pub mod synchronization;
pub mod synchronization_history;
pub mod vendor;

View File

@ -0,0 +1,9 @@
//!
//!
///
pub mod models;
///
pub mod repository;
///
pub mod schema;

View File

@ -0,0 +1,41 @@
use super::schema::api_kgon_synchronizations;
pub static ITEM_MEMBERS: &str = "members";
pub static ITEM_BALANCE_PARTNER: &str = "balance_partner";
pub static ITEM_BALANCE_USER_ALL: &str = "balance_user_all";
pub static ITEM_BALANCE_USER: &str = "balance_user";
pub static ITEM_VENDORS: &str = "vendors";
pub static ITEM_GAMES: &str = "games";
pub static ITEM_BETTING_HISTORY: &str = "betting_history";
///
#[derive(Eq, Hash, Identifiable, Queryable, PartialEq, Debug, Clone)]
#[table_name = "api_kgon_synchronizations"]
pub struct Synchronization {
///
pub id: i32,
///
pub item: String,
///
pub last_code: i64,
///
pub synchronized_at: i64,
}
///
#[derive(Insertable, Debug, Clone)]
#[table_name = "api_kgon_synchronizations"]
pub struct NewSynchronization {
///
pub item: String,
///
pub last_code: i64,
}
///
#[derive(AsChangeset, Debug, Clone)]
#[table_name = "api_kgon_synchronizations"]
pub struct ModifySynchronization {
///
pub last_code: i64,
}

View File

@ -0,0 +1,103 @@
//!
//!
use super::{models, schema::api_kgon_synchronizations};
use diesel::prelude::*;
use diesel::result::Error;
///
pub struct Repository {}
impl std::fmt::Debug for Repository {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Repository of api_kgon_synchronizations")
.finish()
}
}
impl Default for Repository {
fn default() -> Self {
Self::new()
}
}
impl Repository {
///
pub fn new() -> Repository {
Repository {}
}
///
pub fn insert(
&self,
conn: &diesel::PgConnection,
new_member: &models::NewSynchronization,
) -> Result<models::Synchronization, Error> {
let inserted = diesel::insert_into(api_kgon_synchronizations::table)
.values(new_member)
.get_result::<models::Synchronization>(conn)?;
Ok(inserted)
}
///
pub fn select(
&self,
conn: &diesel::PgConnection,
id: i32,
) -> Result<Option<models::Synchronization>, Error> {
match api_kgon_synchronizations::table
.find(id)
.first::<models::Synchronization>(conn)
{
Ok(m) => Ok(Some(m)),
Err(e) => match e {
diesel::result::Error::NotFound => Ok(None),
_ => Err(e),
},
}
}
///
pub fn select_by_item(
&self,
conn: &diesel::PgConnection,
item: String,
) -> Result<Option<models::Synchronization>, Error> {
use api_kgon_synchronizations::dsl;
match api_kgon_synchronizations::table
.filter(dsl::item.eq(item))
.first::<models::Synchronization>(conn)
{
Ok(m) => Ok(Some(m)),
Err(e) => match e {
diesel::result::Error::NotFound => Ok(None),
_ => Err(e),
},
}
}
///
pub fn update(
&self,
conn: &diesel::PgConnection,
id: i32,
modify: &models::ModifySynchronization,
) -> Result<u64, Error> {
use api_kgon_synchronizations::dsl;
diesel::update(dsl::api_kgon_synchronizations.filter(dsl::id.eq(id)))
.set(modify)
.execute(conn)
.map(|c| c as u64)
}
///
pub fn delete(&self, conn: &diesel::PgConnection, id: i32) -> Result<u64, Error> {
use api_kgon_synchronizations::dsl;
diesel::delete(api_kgon_synchronizations::table.filter(dsl::id.eq(id)))
.execute(conn)
.map(|c| c as u64)
}
}

View File

@ -0,0 +1,16 @@
//!
//!
table! {
///
api_kgon_synchronizations(id) {
///
id -> Integer,
///
item -> Text,
///
last_code -> BigInt,
///
synchronized_at -> BigInt,
}
}

View File

@ -0,0 +1,9 @@
//!
//!
///
pub mod models;
///
pub mod repository;
///
pub mod schema;

View File

@ -0,0 +1,76 @@
use super::schema::api_kgon_synchronization_history;
use beteran_common_rust as bcr;
use diesel::deserialize::QueryableByName;
///
#[derive(Eq, Hash, Identifiable, Queryable, PartialEq, Debug, Clone)]
#[table_name = "api_kgon_synchronization_history"]
pub struct SynchronizationHistory {
///
pub id: i64,
///
pub item: String,
///
pub start_at: i64,
///
pub complete_at: i64,
///
pub code: i64,
///
pub message: Option<String>,
///
pub data: Option<String>,
///
pub created_at: i64,
}
///
#[derive(Insertable, Debug, Clone)]
#[table_name = "api_kgon_synchronization_history"]
pub struct NewSynchronizationHistory {
///
pub item: String,
///
pub start_at: i64,
///
pub complete_at: i64,
///
pub code: i64,
///
pub message: Option<String>,
///
pub data: Option<String>,
}
///
#[derive(Debug, Clone)]
pub struct FindAllSearch {
///
pub item: Option<String>,
///
pub code: Option<i64>,
}
///
#[derive(Debug, Clone)]
pub struct FindAll {
pub search: Option<FindAllSearch>,
///
pub pagination: Option<bcr::pagination::Pagination>,
///
pub sorts: Option<Vec<bcr::pagination::Sort>>,
}
impl QueryableByName<diesel::pg::Pg> for SynchronizationHistory {
fn build<R: diesel::row::NamedRow<diesel::pg::Pg>>(row: &R) -> diesel::deserialize::Result<Self> {
Ok(SynchronizationHistory {
id: row.get("id")?,
item: row.get("item")?,
start_at: row.get("start_at")?,
complete_at: row.get("complete_at")?,
code: row.get("code")?,
message: row.get("message")?,
data: row.get("data")?,
created_at: row.get("created_at")?,
})
}
}

View File

@ -0,0 +1,206 @@
//!
//!
use super::{models, schema::api_kgon_synchronization_history};
use beteran_common_rust as bcr;
use diesel::result::Error;
use diesel::{prelude::*, sql_query};
///
pub struct Repository {}
impl std::fmt::Debug for Repository {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Repository of api_kgon_synchronization_history")
.finish()
}
}
impl Default for Repository {
fn default() -> Self {
Self::new()
}
}
impl Repository {
///
pub fn new() -> Repository {
Repository {}
}
///
pub fn insert(
&self,
conn: &diesel::PgConnection,
new_member: &models::NewSynchronizationHistory,
) -> Result<models::SynchronizationHistory, Error> {
let inserted = diesel::insert_into(api_kgon_synchronization_history::table)
.values(new_member)
.get_result::<models::SynchronizationHistory>(conn)?;
Ok(inserted)
}
///
pub fn select(
&self,
conn: &diesel::PgConnection,
id: i64,
) -> Result<Option<models::SynchronizationHistory>, Error> {
match api_kgon_synchronization_history::table
.find(id)
.first::<models::SynchronizationHistory>(conn)
{
Ok(m) => Ok(Some(m)),
Err(e) => match e {
diesel::result::Error::NotFound => Ok(None),
_ => Err(e),
},
}
}
///
pub fn select_latest_by_item(
&self,
conn: &diesel::PgConnection,
item: String,
) -> Result<Option<models::SynchronizationHistory>, Error> {
let query = "
SELECT
id,
item,
start_at,
complete_at,
code,
message,
data,
created_at
FROM
(
SELECT
id,
item,
start_at,
complete_at,
code,
message,
data,
created_at,
row_number() OVER(PARTITION BY item ORDER BY created_at DESC) AS rn
FROM
api_kgon_synchronization_history
) t
WHERE t.rn = 1 AND item = $1
";
match sql_query(query)
.bind::<diesel::sql_types::Text, _>(item)
.get_result::<models::SynchronizationHistory>(conn)
{
Ok(m) => Ok(Some(m)),
Err(e) => match e {
diesel::result::Error::NotFound => Ok(None),
_ => Err(e),
},
}
}
///
pub fn select_all_count(
&self,
conn: &diesel::PgConnection,
find_all: &models::FindAll,
) -> Result<i64, Error> {
let mut q = api_kgon_synchronization_history::table.into_boxed();
if let Some(s) = &find_all.search {
if let Some(sp) = &s.item {
q = q.filter(api_kgon_synchronization_history::dsl::item.eq(sp));
}
if let Some(sp) = s.code {
q = q.filter(api_kgon_synchronization_history::dsl::code.eq(sp));
}
}
q.count().get_result(conn)
}
///
pub fn select_all(
&self,
conn: &diesel::PgConnection,
find_all: &models::FindAll,
) -> Result<Vec<models::SynchronizationHistory>, Error> {
let mut q = api_kgon_synchronization_history::table.into_boxed();
if let Some(s) = &find_all.search {
if let Some(sp) = &s.item {
q = q.filter(api_kgon_synchronization_history::dsl::item.eq(sp));
}
if let Some(sp) = s.code {
q = q.filter(api_kgon_synchronization_history::dsl::code.eq(sp));
}
}
if let Some(p) = &find_all.pagination {
let page = p.page.unwrap_or(1);
if let Some(page_size) = p.page_size {
q = q.offset(((page - 1) * page_size) as i64);
q = q.limit(page_size as i64);
}
}
if let Some(orderbys) = &find_all.sorts {
for s in orderbys {
match s {
bcr::pagination::Sort::ASC(property) => match property.as_str() {
"item" => {
q = q.order_by(api_kgon_synchronization_history::item.asc());
}
"start_at" => {
q = q.order_by(api_kgon_synchronization_history::start_at.asc());
}
"complete_at" => {
q = q.order_by(api_kgon_synchronization_history::complete_at.asc());
}
"code" => {
q = q.order_by(api_kgon_synchronization_history::code.asc());
}
"created_at" => {
q = q.order_by(api_kgon_synchronization_history::created_at.asc());
}
_ => {}
},
bcr::pagination::Sort::DESC(property) => match property.as_str() {
"item" => {
q = q.order_by(api_kgon_synchronization_history::item.desc());
}
"start_at" => {
q = q.order_by(api_kgon_synchronization_history::start_at.desc());
}
"complete_at" => {
q = q.order_by(api_kgon_synchronization_history::complete_at.desc());
}
"code" => {
q = q.order_by(api_kgon_synchronization_history::code.desc());
}
"created_at" => {
q = q.order_by(api_kgon_synchronization_history::created_at.desc());
}
_ => {}
},
};
}
}
q.load::<models::SynchronizationHistory>(conn)
}
///
pub fn delete(&self, conn: &diesel::PgConnection, id: i64) -> Result<u64, Error> {
use api_kgon_synchronization_history::dsl;
diesel::delete(api_kgon_synchronization_history::table.filter(dsl::id.eq(id)))
.execute(conn)
.map(|c| c as u64)
}
}

View File

@ -0,0 +1,24 @@
//!
//!
table! {
///
api_kgon_synchronization_history(id) {
///
id -> BigInt,
///
item -> Text,
///
start_at -> BigInt,
///
complete_at -> BigInt,
///
code -> BigInt,
///
message -> Nullable<Text>,
///
data -> Nullable<Text>,
///
created_at -> BigInt,
}
}

9
src/repositories/vendor/mod.rs vendored Normal file
View File

@ -0,0 +1,9 @@
//!
//!
///
pub mod models;
///
pub mod repository;
///
pub mod schema;

134
src/repositories/vendor/models.rs vendored Normal file
View File

@ -0,0 +1,134 @@
use super::schema::api_kgon_vendors;
use beteran_common_rust as bcr;
///
#[derive(Identifiable, Queryable, PartialEq, Debug, Clone)]
#[table_name = "api_kgon_vendors"]
pub struct Vendor {
///
pub id: i64,
///
pub company_id: i64,
///
pub vendor_id: i64,
///
pub key: String,
///
pub name: String,
///
pub category: String,
///
pub max_bet_casino: f64,
///
pub max_bet_slot: f64,
///
pub is_enable: String,
///
pub bet_count: i64,
///
pub created_at: i64,
///
pub updated_at: i64,
}
///
#[derive(Insertable, Debug, Clone)]
#[table_name = "api_kgon_vendors"]
pub struct NewVendor {
///
pub id: i64,
///
pub company_id: i64,
///
pub vendor_id: i64,
///
pub key: String,
///
pub name: String,
///
pub category: String,
///
pub max_bet_casino: f64,
///
pub max_bet_slot: f64,
///
pub is_enable: String,
///
pub bet_count: i64,
}
///
#[derive(AsChangeset, Debug, Clone)]
#[table_name = "api_kgon_vendors"]
pub struct ModifyVendor {
///
pub company_id: i64,
///
pub vendor_id: i64,
///
pub key: String,
///
pub name: String,
///
pub category: String,
///
pub max_bet_casino: f64,
///
pub max_bet_slot: f64,
///
pub is_enable: String,
///
pub bet_count: i64,
}
///
#[derive(Insertable, AsChangeset, Debug, Clone)]
#[table_name = "api_kgon_vendors"]
pub struct UpsertVendor {
///
pub id: i64,
///
pub company_id: i64,
///
pub vendor_id: i64,
///
pub key: String,
///
pub name: String,
///
pub category: String,
///
pub max_bet_casino: f64,
///
pub max_bet_slot: f64,
///
pub is_enable: String,
///
pub bet_count: i64,
}
///
#[derive(Debug, Clone)]
pub struct FindAllSearch {
///
pub company_id: Option<i64>,
///
pub vendor_id: Option<i64>,
///
pub key_like: Option<String>,
///
pub name_like: Option<String>,
///
pub category_like: Option<String>,
///
pub is_enable: Option<String>,
}
///
#[derive(Debug, Clone)]
pub struct FindAll {
pub search: Option<FindAllSearch>,
///
pub pagination: Option<bcr::pagination::Pagination>,
///
pub sorts: Option<Vec<bcr::pagination::Sort>>,
}

263
src/repositories/vendor/repository.rs vendored Normal file
View File

@ -0,0 +1,263 @@
//!
//!
use super::{models, schema::api_kgon_vendors};
use beteran_common_rust as bcr;
use diesel::prelude::*;
use diesel::result::Error;
///
pub struct Repository {}
impl std::fmt::Debug for Repository {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Repository of api_kgon_vendors").finish()
}
}
impl Default for Repository {
fn default() -> Self {
Self::new()
}
}
impl Repository {
///
pub fn new() -> Repository {
Repository {}
}
///
pub fn insert(
&self,
conn: &diesel::PgConnection,
new_member: &models::NewVendor,
) -> Result<models::Vendor, Error> {
let inserted = diesel::insert_into(api_kgon_vendors::table)
.values(new_member)
.get_result::<models::Vendor>(conn)?;
Ok(inserted)
}
///
pub fn upserts(
&self,
conn: &diesel::PgConnection,
upsert_vendors: Vec<models::UpsertVendor>,
) -> Result<usize, Error> {
use api_kgon_vendors::dsl;
use diesel::pg::upsert::excluded;
let affected = diesel::insert_into(api_kgon_vendors::table)
.values(upsert_vendors)
.on_conflict(dsl::id)
.do_update()
.set((
dsl::company_id.eq(excluded(dsl::company_id)),
dsl::vendor_id.eq(excluded(dsl::vendor_id)),
dsl::key.eq(excluded(dsl::key)),
dsl::name.eq(excluded(dsl::name)),
dsl::category.eq(excluded(dsl::category)),
dsl::max_bet_casino.eq(excluded(dsl::max_bet_casino)),
dsl::max_bet_slot.eq(excluded(dsl::max_bet_slot)),
dsl::is_enable.eq(excluded(dsl::is_enable)),
dsl::bet_count.eq(excluded(dsl::bet_count)),
))
.execute(conn)?;
Ok(affected)
}
///
pub fn select(
&self,
conn: &diesel::PgConnection,
id: i64,
) -> Result<Option<models::Vendor>, Error> {
match api_kgon_vendors::table
.find(id)
.first::<models::Vendor>(conn)
{
Ok(m) => Ok(Some(m)),
Err(e) => match e {
diesel::result::Error::NotFound => Ok(None),
_ => Err(e),
},
}
}
///
pub fn select_all_count(
&self,
conn: &diesel::PgConnection,
find_all: &models::FindAll,
) -> Result<i64, Error> {
let mut q = api_kgon_vendors::table.into_boxed();
if let Some(s) = &find_all.search {
if let Some(sp) = s.company_id {
q = q.filter(api_kgon_vendors::dsl::company_id.eq(sp));
}
if let Some(sp) = s.vendor_id {
q = q.filter(api_kgon_vendors::dsl::vendor_id.eq(sp));
}
if let Some(sp) = &s.key_like {
q = q.filter(api_kgon_vendors::dsl::key.like(sp));
}
if let Some(sp) = &s.name_like {
q = q.filter(api_kgon_vendors::dsl::name.like(sp));
}
if let Some(sp) = &s.category_like {
q = q.filter(api_kgon_vendors::dsl::category.like(sp));
}
if let Some(sp) = &s.is_enable {
q = q.filter(api_kgon_vendors::dsl::is_enable.eq(sp));
}
}
q.count().get_result(conn)
}
///
pub fn select_all(
&self,
conn: &diesel::PgConnection,
find_all: &models::FindAll,
) -> Result<Vec<models::Vendor>, Error> {
let mut q = api_kgon_vendors::table.into_boxed();
if let Some(s) = &find_all.search {
if let Some(sp) = s.company_id {
q = q.filter(api_kgon_vendors::dsl::company_id.eq(sp));
}
if let Some(sp) = s.vendor_id {
q = q.filter(api_kgon_vendors::dsl::vendor_id.eq(sp));
}
if let Some(sp) = &s.key_like {
q = q.filter(api_kgon_vendors::dsl::key.like(sp));
}
if let Some(sp) = &s.name_like {
q = q.filter(api_kgon_vendors::dsl::name.like(sp));
}
if let Some(sp) = &s.category_like {
q = q.filter(api_kgon_vendors::dsl::category.like(sp));
}
if let Some(sp) = &s.is_enable {
q = q.filter(api_kgon_vendors::dsl::is_enable.eq(sp));
}
}
if let Some(p) = &find_all.pagination {
let page = p.page.unwrap_or(1);
if let Some(page_size) = p.page_size {
q = q.offset(((page - 1) * page_size) as i64);
q = q.limit(page_size as i64);
}
}
if let Some(orderbys) = &find_all.sorts {
for s in orderbys {
match s {
bcr::pagination::Sort::ASC(property) => match property.as_str() {
"company_id" => {
q = q.order_by(api_kgon_vendors::company_id.asc());
}
"vendor_id" => {
q = q.order_by(api_kgon_vendors::vendor_id.asc());
}
"key" => {
q = q.order_by(api_kgon_vendors::key.asc());
}
"name" => {
q = q.order_by(api_kgon_vendors::name.asc());
}
"category" => {
q = q.order_by(api_kgon_vendors::category.asc());
}
"max_bet_casino" => {
q = q.order_by(api_kgon_vendors::max_bet_casino.asc());
}
"max_bet_slot" => {
q = q.order_by(api_kgon_vendors::max_bet_slot.asc());
}
"is_enable" => {
q = q.order_by(api_kgon_vendors::is_enable.asc());
}
"bet_count" => {
q = q.order_by(api_kgon_vendors::bet_count.asc());
}
"created_at" => {
q = q.order_by(api_kgon_vendors::created_at.asc());
}
"updated_at" => {
q = q.order_by(api_kgon_vendors::updated_at.asc());
}
_ => {}
},
bcr::pagination::Sort::DESC(property) => match property.as_str() {
"company_id" => {
q = q.order_by(api_kgon_vendors::company_id.desc());
}
"vendor_id" => {
q = q.order_by(api_kgon_vendors::vendor_id.desc());
}
"key" => {
q = q.order_by(api_kgon_vendors::key.desc());
}
"name" => {
q = q.order_by(api_kgon_vendors::name.desc());
}
"category" => {
q = q.order_by(api_kgon_vendors::category.desc());
}
"max_bet_casino" => {
q = q.order_by(api_kgon_vendors::max_bet_casino.desc());
}
"max_bet_slot" => {
q = q.order_by(api_kgon_vendors::max_bet_slot.desc());
}
"is_enable" => {
q = q.order_by(api_kgon_vendors::is_enable.desc());
}
"bet_count" => {
q = q.order_by(api_kgon_vendors::bet_count.desc());
}
"created_at" => {
q = q.order_by(api_kgon_vendors::created_at.desc());
}
"updated_at" => {
q = q.order_by(api_kgon_vendors::updated_at.desc());
}
_ => {}
},
};
}
}
q.load::<models::Vendor>(conn)
}
///
pub fn update(
&self,
conn: &diesel::PgConnection,
id: i64,
modify: &models::ModifyVendor,
) -> Result<u64, Error> {
use api_kgon_vendors::dsl;
diesel::update(dsl::api_kgon_vendors.filter(dsl::id.eq(id)))
.set(modify)
.execute(conn)
.map(|c| c as u64)
}
///
pub fn delete(&self, conn: &diesel::PgConnection, id: i64) -> Result<u64, Error> {
use api_kgon_vendors::dsl;
diesel::delete(api_kgon_vendors::table.filter(dsl::id.eq(id)))
.execute(conn)
.map(|c| c as u64)
}
}

32
src/repositories/vendor/schema.rs vendored Normal file
View File

@ -0,0 +1,32 @@
//!
//!
table! {
///
api_kgon_vendors(id) {
///
id -> BigInt,
///
company_id -> BigInt,
///
vendor_id -> BigInt,
///
key -> Text,
///
name -> Text,
///
category -> Text,
///
max_bet_casino -> Double,
///
max_bet_slot -> Double,
///
is_enable -> Text,
///
bet_count -> BigInt,
///
created_at -> BigInt,
///
updated_at -> BigInt,
}
}

View File

@ -0,0 +1 @@
pub mod scheduler;

View File

@ -0,0 +1,78 @@
use crate::synchronizations;
use once_cell::sync::OnceCell;
use std::sync::Arc;
use tokio_cron_scheduler::{Job, JobScheduler};
static G_INSTANCE: OnceCell<Arc<Scheduler>> = OnceCell::new();
///
pub struct Scheduler {
sched: JobScheduler,
member_account_synchronizer: synchronizations::member_account::synchronizer::Synchronizer,
}
impl std::fmt::Debug for Scheduler {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Scheduler of api.kgon.identity").finish()
}
}
impl Scheduler {
///
pub fn get_instance(
sched: JobScheduler,
member_account_synchronizer: synchronizations::member_account::synchronizer::Synchronizer,
) -> Result<&'static Arc<Scheduler>, Box<dyn std::error::Error>> {
let instance = G_INSTANCE
.get_or_try_init(|| -> Result<Arc<Scheduler>, Box<dyn std::error::Error>> {
let s = Scheduler {
sched,
member_account_synchronizer,
};
Ok(Arc::new(s))
})
.expect("");
Ok(instance)
}
pub async fn queue(&'static self) -> Result<(), std::boxed::Box<dyn std::error::Error>> {
self.balance_for_user().await?;
self.balance_for_partner().await?;
Ok(())
}
async fn balance_for_user(&'static self) -> Result<(), Box<dyn std::error::Error>> {
let j_synchronization = Job::new_async("0 0/3 * * * ?", move |_uuid, _l| {
Box::pin(async move {
self
.member_account_synchronizer
.balance_for_user_all()
.await
.expect("member_account_synchronizer.balance_for_user");
})
})?;
self.sched.add(j_synchronization).await?;
Ok(())
}
async fn balance_for_partner(&'static self) -> Result<(), Box<dyn std::error::Error>> {
let j_synchronization = Job::new_async("0 0/3 * * * ?", move |_uuid, _l| {
Box::pin(async move {
self
.member_account_synchronizer
.balance_for_partner()
.await
.expect("member_account_synchronizer.balance_for_partner");
})
})?;
self.sched.add(j_synchronization).await?;
Ok(())
}
}

View File

@ -0,0 +1 @@
pub mod scheduler;

View File

@ -0,0 +1,61 @@
use crate::synchronizations;
use once_cell::sync::OnceCell;
use std::sync::Arc;
use tokio_cron_scheduler::{Job, JobScheduler};
static G_INSTANCE: OnceCell<Arc<Scheduler>> = OnceCell::new();
///
pub struct Scheduler {
sched: JobScheduler,
betting_history_synchronizer: synchronizations::betting_history::synchronizer::Synchronizer,
}
impl std::fmt::Debug for Scheduler {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Scheduler of api.kgon.identity").finish()
}
}
impl Scheduler {
///
pub fn get_instance(
sched: JobScheduler,
betting_history_synchronizer: synchronizations::betting_history::synchronizer::Synchronizer,
) -> Result<&'static Arc<Scheduler>, Box<dyn std::error::Error>> {
let instance = G_INSTANCE
.get_or_try_init(|| -> Result<Arc<Scheduler>, Box<dyn std::error::Error>> {
let s = Scheduler {
sched,
betting_history_synchronizer,
};
Ok(Arc::new(s))
})
.expect("");
Ok(instance)
}
pub async fn queue(&'static self) -> Result<(), std::boxed::Box<dyn std::error::Error>> {
self.betting_history().await?;
Ok(())
}
async fn betting_history(&'static self) -> Result<(), Box<dyn std::error::Error>> {
let j_synchronization = Job::new_async("0 0/3 * * * ?", move |_uuid, _l| {
Box::pin(async move {
self
.betting_history_synchronizer
.betting_history()
.await
.expect("betting_history_synchronizer.betting_history");
})
})?;
self.sched.add(j_synchronization).await?;
Ok(())
}
}

View File

@ -0,0 +1 @@
pub mod scheduler;

View File

@ -0,0 +1,69 @@
use crate::synchronizations;
use once_cell::sync::OnceCell;
use std::sync::Arc;
use tokio_cron_scheduler::{Job, JobScheduler};
static G_INSTANCE: OnceCell<Arc<Scheduler>> = OnceCell::new();
///
pub struct Scheduler {
sched: JobScheduler,
vendor_synchronizer: synchronizations::vendor::synchronizer::Synchronizer,
game_synchronizer: synchronizations::game::synchronizer::Synchronizer,
}
impl std::fmt::Debug for Scheduler {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Scheduler of api.kgon.identity").finish()
}
}
impl Scheduler {
pub fn get_instance(
sched: JobScheduler,
vendor_synchronizer: synchronizations::vendor::synchronizer::Synchronizer,
game_synchronizer: synchronizations::game::synchronizer::Synchronizer,
) -> Result<&'static Arc<Scheduler>, Box<dyn std::error::Error>> {
let instance = G_INSTANCE
.get_or_try_init(|| -> Result<Arc<Scheduler>, Box<dyn std::error::Error>> {
let s = Scheduler {
sched,
vendor_synchronizer,
game_synchronizer,
};
Ok(Arc::new(s))
})
.expect("");
Ok(instance)
}
pub async fn queue(&'static self) -> Result<(), std::boxed::Box<dyn std::error::Error>> {
self.vendors_and_games().await?;
Ok(())
}
async fn vendors_and_games(&'static self) -> Result<(), Box<dyn std::error::Error>> {
let j_synchronization = Job::new_async("0 0/3 * * * ?", move |_uuid, _l| {
Box::pin(async move {
self
.vendor_synchronizer
.vendors()
.await
.expect("vendor_synchronizer.vendors");
self
.game_synchronizer
.games()
.await
.expect("game_synchronizer.games");
})
})?;
self.sched.add(j_synchronization).await?;
Ok(())
}
}

View File

@ -0,0 +1 @@
pub mod scheduler;

View File

@ -0,0 +1,61 @@
use crate::synchronizations;
use once_cell::sync::OnceCell;
use std::sync::Arc;
use tokio_cron_scheduler::{Job, JobScheduler};
static G_INSTANCE: OnceCell<Arc<Scheduler>> = OnceCell::new();
///
pub struct Scheduler {
sched: JobScheduler,
member_synchronizer: synchronizations::member::synchronizer::Synchronizer,
}
impl std::fmt::Debug for Scheduler {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Scheduler of api.kgon.identity").finish()
}
}
impl Scheduler {
///
pub fn get_instance(
sched: JobScheduler,
member_synchronizer: synchronizations::member::synchronizer::Synchronizer,
) -> Result<&'static Arc<Scheduler>, Box<dyn std::error::Error>> {
let instance = G_INSTANCE
.get_or_try_init(|| -> Result<Arc<Scheduler>, Box<dyn std::error::Error>> {
let s = Scheduler {
sched,
member_synchronizer,
};
Ok(Arc::new(s))
})
.expect("");
Ok(instance)
}
pub async fn queue(&'static self) -> Result<(), std::boxed::Box<dyn std::error::Error>> {
self.members().await?;
Ok(())
}
async fn members(&'static self) -> Result<(), Box<dyn std::error::Error>> {
let j_synchronization = Job::new_async("0 0/3 * * * ?", move |_uuid, _l| {
Box::pin(async move {
self
.member_synchronizer
.members()
.await
.expect("member_synchronizer.members");
})
})?;
self.sched.add(j_synchronization).await?;
Ok(())
}
}

4
src/schedulers/mod.rs Normal file
View File

@ -0,0 +1,4 @@
pub mod balance;
pub mod betting_history;
pub mod game;
pub mod member;

View File

@ -0,0 +1,2 @@
pub mod models;
pub mod service;

Some files were not shown because too many files have changed in this diff Show More