betting is added

This commit is contained in:
병준 박 2022-08-31 08:56:37 +00:00
parent 6edcc2d615
commit 62b501d6bb
11 changed files with 970 additions and 9 deletions

View File

@ -36,7 +36,7 @@ tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
tokio-cron-scheduler = { version = "0" } tokio-cron-scheduler = { version = "0" }
uuid = { version = "0", features = ["serde", "v4", "v5"] } uuid = { version = "0", features = ["serde", "v4", "v5"] }
beteran-protobuf-rust = { git = "https://gitlab.loafle.net/bet/beteran-protobuf-rust.git", tag = "v0.1.85-snapshot" } beteran-protobuf-rust = { git = "https://gitlab.loafle.net/bet/beteran-protobuf-rust.git", tag = "v0.1.86-snapshot" }
beteran-common-rust = { git = "https://gitlab.loafle.net/bet/beteran-common-rust.git", tag = "v0.1.71-snapshot" } beteran-common-rust = { git = "https://gitlab.loafle.net/bet/beteran-common-rust.git", tag = "v0.1.72-snapshot" }
[build-dependencies] [build-dependencies]

View File

@ -2,4 +2,5 @@ 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_game_id;
DROP INDEX idx_api_kgon_betting_history_created_at; 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_utc_created_at;
DROP INDEX idx_api_kgon_betting_history_site_username;
DROP TABLE api_kgon_betting_history; DROP TABLE api_kgon_betting_history;

View File

@ -29,3 +29,4 @@ CREATE INDEX idx_api_kgon_betting_history_vendor_id ON api_kgon_betting_history
CREATE INDEX idx_api_kgon_betting_history_game_id ON api_kgon_betting_history (game_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_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_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);

View File

@ -0,0 +1,517 @@
use super::models;
use beteran_common_rust as bcr;
use diesel::{result::Error, sql_query, RunQueryDsl};
use std::fmt::Write;
static MEMBER_COUNT_QUERY: &str = "
SELECT
COUNT(akbh.id)
FROM api_kgon_betting_history as akbh
INNER JOIN members _m
ON _m.username = akbh.site_username
";
static MEMBER_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.key as akbh_key ,
akbh.ref_id as akbh_ref_id ,
akbh.o_ref_id as akbh_o_ref_id ,
akbh.group_key as akbh_group_key ,
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.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
FROM api_kgon_betting_history as akbh
INNER JOIN members _m
ON _m.username = akbh.site_username
";
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
",
MEMBER_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
",
MEMBER_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_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_find_all(&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 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 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, "{}", MEMBER_COUNT_QUERY)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
let query_where = self.get_find_all(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, "{}", MEMBER_QUERY)
.map_err(|e| diesel::result::Error::QueryBuilderError(e.to_string().into()))?;
let query_where = self.get_find_all(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()))?;
}
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,193 @@
use beteran_common_rust as bcr;
use beteran_protobuf_rust as bpr;
use diesel::deserialize::QueryableByName;
///
#[derive(PartialEq, Debug, Clone)]
pub struct BettingHistoryModel {
///
pub id: String,
///
pub member: bpr::models::member::Member,
///
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 key: String,
///
pub ref_id: String,
///
pub o_ref_id: String,
///
pub group_key: Option<String>,
///
pub is_bonus: bool,
///
pub is_promo: bool,
///
pub is_jackpot: bool,
///
pub site_username: 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> {
let member = bpr::models::member::Member {
id: row.get("_m_id")?,
site_id: row.get("_m_site_id")?,
member_class_id: row.get("_m_member_class_id")?,
member_level_id: row.get("_m_member_level_id")?,
username: row.get("_m_username")?,
nickname: row.get("_m_nickname")?,
mobile_phone_number: row.get("_m_mobile_phone_number")?,
state: row.get("_m_state")?,
state_changed_at: row
.get::<diesel::sql_types::Nullable<diesel::sql_types::BigInt>, Option<i64>>(
"_m_state_changed_at",
)?
.map(|v| v as u64),
parent_member_id: row.get("_m_parent_member_id")?,
child_member_count: row.get::<diesel::sql_types::BigInt, i64>("_m_child_member_count")?
as u64,
last_signined_ip: row.get("_m_last_signined_ip")?,
last_signined_at: row
.get::<diesel::sql_types::Nullable<diesel::sql_types::BigInt>, Option<i64>>(
"_m_last_signined_at",
)?
.map(|v| v as u64),
created_at: row.get::<diesel::sql_types::BigInt, i64>("_m_created_at")? as u64,
updated_at: row.get::<diesel::sql_types::BigInt, i64>("_m_updated_at")? as u64,
deleted_at: row
.get::<diesel::sql_types::Nullable<diesel::sql_types::BigInt>, Option<i64>>(
"_m_deleted_at",
)?
.map(|v| v as u64),
};
Ok(BettingHistoryModel {
id: row.get("akbh_id")?,
member,
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")?,
key: row.get("akbh_key")?,
ref_id: row.get("akbh_ref_id")?,
o_ref_id: row.get("akbh_o_ref_id")?,
group_key: row.get("akbh_group_key")?,
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")?,
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_name: Option<String>,
///
pub vendor_name_like: Option<String>,
///
pub game_id: Option<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>>,
}

View File

@ -108,7 +108,7 @@ impl Composition {
member: mm, member: mm,
created_at: m.created_at, created_at: m.created_at,
updated_at: m.updated_at, updated_at: m.updated_at,
})) }));
} }
None => { None => {
return Ok(None); return Ok(None);

View File

@ -106,8 +106,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
connection_broker.clone(), connection_broker.clone(),
queue_broker.clone(), queue_broker.clone(),
); );
let betting_service = let betting_service = services::betting::service::Service::new(
services::betting::service::Service::new(connection_broker.clone(), queue_broker.clone()); connection_broker.clone(),
queue_broker.clone(),
pool.clone(),
);
let member_event_handler = events::member::event::EventHandler::new( let member_event_handler = events::member::event::EventHandler::new(
connection_broker.clone(), connection_broker.clone(),
@ -164,6 +167,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
futures::try_join!( futures::try_join!(
vendor_service.subscribe(), vendor_service.subscribe(),
game_service.subscribe(), game_service.subscribe(),
betting_service.subscribe(),
// member_service.subscribe(), // member_service.subscribe(),
// member_account_service.subscribe(), // member_account_service.subscribe(),
// betting_service.subscribe(), // betting_service.subscribe(),

View File

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

View File

@ -0,0 +1,54 @@
use crate::compositions;
use beteran_protobuf_rust as bpr;
impl From<&compositions::betting::models::BettingHistoryModel>
for bpr::models::api::betting::BettingHistoryModel
{
fn from(d: &compositions::betting::models::BettingHistoryModel) -> Self {
let member = Some(bpr::models::member::Member {
id: d.member.id.to_string(),
site_id: d.member.site_id.to_string(),
member_class_id: d.member.member_class_id.to_string(),
member_level_id: d.member.member_level_id.to_string(),
parent_member_id: d.member.parent_member_id.as_ref().map(|d| d.to_string()),
child_member_count: d.member.child_member_count as u64,
username: d.member.username.clone(),
nickname: d.member.nickname.clone(),
mobile_phone_number: d.member.mobile_phone_number.clone(),
state: d.member.state as i32,
state_changed_at: d.member.state_changed_at.map(|d| d as u64),
last_signined_ip: d.member.last_signined_ip.clone(),
last_signined_at: d.member.last_signined_at.map(|d| d as u64),
created_at: d.member.created_at as u64,
updated_at: d.member.updated_at as u64,
deleted_at: d.member.deleted_at.map(|d| d as u64),
});
bpr::models::api::betting::BettingHistoryModel {
id: d.id.clone(),
member,
vendor_id: d.vendor_id as u64,
vendor_name: d.vendor_name.clone(),
game_id: d.game_id as u64,
game_name: d.game_name.clone(),
game_category: d.game_category.clone(),
game_type: d.game_type.clone(),
currency: d.currency.clone(),
cash: d.cash,
before_cash: d.before_cash,
after_cash: d.after_cash,
key: d.key.clone(),
ref_id: d.ref_id.clone(),
o_ref_id: d.o_ref_id.clone(),
group_key: d.group_key.clone(),
is_bonus: d.is_bonus,
is_promo: d.is_promo,
is_jackpot: d.is_jackpot,
site_username: d.site_username.clone(),
betting_type: d.betting_type.clone(),
category: d.category.clone(),
created_at: d.created_at as u64,
utc_created_at: d.utc_created_at as u64,
}
}
}

View File

@ -1,7 +1,18 @@
use crate::compositions;
use beteran_common_rust as bcr;
use beteran_protobuf_rust as bpr;
use diesel::{
r2d2::{ConnectionManager, Pool},
PgConnection,
};
use prost::Message;
/// ///
pub struct Service { pub struct Service {
connection_broker: nats::asynk::Connection, connection_broker: nats::asynk::Connection,
queue_broker: String, queue_broker: String,
pool: Pool<ConnectionManager<PgConnection>>,
betting_composition: compositions::betting::composition::Composition,
} }
impl std::fmt::Debug for Service { impl std::fmt::Debug for Service {
@ -12,16 +23,22 @@ impl std::fmt::Debug for Service {
impl Service { impl Service {
/// ///
pub fn new(connection_broker: nats::asynk::Connection, queue_broker: String) -> Service { pub fn new(
connection_broker: nats::asynk::Connection,
queue_broker: String,
pool: Pool<ConnectionManager<PgConnection>>,
) -> Service {
Service { Service {
connection_broker, connection_broker: connection_broker.clone(),
queue_broker, queue_broker,
pool,
betting_composition: compositions::betting::composition::Composition::new(),
} }
} }
pub async fn subscribe(&self) -> std::result::Result<(), std::boxed::Box<dyn std::error::Error>> { pub async fn subscribe(&self) -> std::result::Result<(), std::boxed::Box<dyn std::error::Error>> {
futures::try_join!( futures::try_join!(
self.list_history(), self.list_betting_history(),
self.list_history_for_pragmatic(), self.list_history_for_pragmatic(),
self.list_history_for_evolution(), self.list_history_for_evolution(),
self.statistics(), self.statistics(),
@ -29,7 +46,178 @@ impl Service {
.map(|_| ()) .map(|_| ())
} }
async fn list_history(&self) -> Result<(), Box<dyn std::error::Error>> { async fn list_betting_history(&self) -> Result<(), Box<dyn std::error::Error>> {
let s = self
.connection_broker
.queue_subscribe(
bpr::ss::api::betting::SUBJECT_LIST_BETTING_HISTORY,
self.queue_broker.as_str(),
)
.await?;
while let Some(message) = s.next().await {
if let Err(e) = async {
let req = bpr::ss::api::betting::ListBettingHistoryRequest::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 req.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 request = match req.request {
Some(r) => r,
None => {
return Err(bcr::error::rpc::Error::InvalidParams(
bcr::error::rpc::InvalidParams {
message: "invalid request information".to_string(),
detail: bcr::error::rpc::InvalidParamsDetail {
location: "request".to_string(),
param: "request".to_string(),
value: "".to_string(),
error_type: bcr::error::rpc::InvalidParamsType::Required,
message: "".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,
})
})?;
let find_all = compositions::betting::models::FindAll {
search: match request.search {
Some(s) => Some(compositions::betting::models::FindAllSearch {
member_id: s.member_id,
vendor_id: s.vendor_id.map(|v| v as i64),
vendor_name: s.vendor_name,
vendor_name_like: s.vendor_name_like,
game_id: s.game_id.map(|v| v as i64),
game_name: s.game_name,
game_name_like: s.game_name_like,
game_category: s.game_category,
game_category_like: s.game_category_like,
game_type: s.game_type,
game_type_like: s.game_type_like,
currency: s.currency,
currency_like: s.currency_like,
key: s.key,
key_like: s.key_like,
ref_id: s.ref_id,
ref_id_like: s.ref_id_like,
o_ref_id: s.o_ref_id,
o_ref_id_like: s.o_ref_id_like,
group_key: s.group_key,
group_key_like: s.group_key_like,
is_bonus: s.is_bonus,
is_promo: s.is_promo,
is_jackpot: s.is_jackpot,
site_username: s.site_username,
site_username_like: s.site_username_like,
betting_type: s.betting_type,
betting_type_like: s.betting_type_like,
category: s.category,
category_like: s.category_like,
}),
None => None,
},
pagination: request
.pagination
.as_ref()
.map(bcr::pagination::Pagination::from),
sorts: Some(
request
.sorts
.iter()
.map(bcr::pagination::Sort::from)
.collect(),
),
};
let count = self
.betting_composition
.select_all_count(&conn, &find_all)
.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 list = self
.betting_composition
.select_all(&conn, &find_all)
.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,
})
})?;
message
.respond(
bpr::ss::api::betting::ListBettingHistoryResponse {
error: None,
result: Some(
bpr::ss::api::betting::list_betting_history_response::Result {
betting_history: list
.iter()
.map(bpr::models::api::betting::BettingHistoryModel::from)
.collect(),
},
),
}
.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,
})
})?;
Ok::<(), bcr::error::rpc::Error>(())
}
.await
{
message
.respond(
bpr::ss::api::betting::ListBettingHistoryResponse {
error: Some(bpr::protobuf::rpc::Error::from(e)),
result: None,
}
.encode_to_vec(),
)
.await?;
}
}
Ok(()) Ok(())
} }
async fn list_history_for_pragmatic(&self) -> Result<(), Box<dyn std::error::Error>> { async fn list_history_for_pragmatic(&self) -> Result<(), Box<dyn std::error::Error>> {