feat: add gacha service

This commit is contained in:
Maulana Sodiqin
2025-04-07 00:50:57 +07:00
parent 4f870ec4c9
commit eb05ea5994
30 changed files with 319 additions and 252 deletions
@@ -1,93 +0,0 @@
use serde::{Deserialize, Serialize};
use surrealdb::sql::Thing;
use utoipa::ToSchema;
use validator::Validate;
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)]
pub struct GachaItemRequestDto {
#[validate(length(min = 1, message = "Item name must not be empty"))]
pub name: String,
#[validate(length(min = 1, message = "Image URL must not be empty"))]
pub image_url: String,
}
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)]
pub struct GachaClaimRequestDto {
#[validate(length(min = 1, message = "User ID must not be empty"))]
pub user_id: String,
#[validate(length(min = 1, message = "Item ID must not be empty"))]
pub item_id: String,
}
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)]
pub struct GachaRollRequestDto {
#[validate(length(min = 1, message = "Item ID must not be empty"))]
pub item_id: String,
#[validate(range(min = 1, message = "Weight must be greater than zero"))]
pub weight: f32,
#[validate(range(min = 1, message = "Quantity must be at least 1"))]
pub quantity: i32,
}
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
pub struct GachaItemDto {
pub id: String,
pub name: String,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GachaItemDtoRaw {
pub id: Thing,
pub name: String,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
pub struct GachaClaimDto {
pub id: String,
pub user: String,
pub item: String,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GachaClaimDtoRaw {
pub id: Thing,
pub user: Thing,
pub item: Thing,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
pub struct GachaRollDto {
pub id: String,
pub item: String,
pub weight: String,
pub quantity: i32,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GachaRollDtoRaw {
pub id: Thing,
pub item: Thing,
pub weight: String,
pub quantity: i32,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
@@ -1,92 +0,0 @@
use crate::{make_thing, ResourceEnum};
use serde::{Deserialize, Serialize};
use surrealdb::{sql::Thing, Uuid};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GachaItemSchema {
pub id: Thing,
pub name: String,
pub image_url: String,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
impl Default for GachaItemSchema {
fn default() -> Self {
GachaItemSchema {
id: make_thing(
&ResourceEnum::GachaItems.to_string(),
&Uuid::new_v4().to_string(),
),
name: String::new(),
image_url: String::new(),
is_deleted: false,
created_at: None,
updated_at: None,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GachaClaimSchema {
pub id: Thing,
pub user: Thing,
pub item: Thing,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
impl Default for GachaClaimSchema {
fn default() -> Self {
GachaClaimSchema {
id: make_thing(
&ResourceEnum::GachaClaims.to_string(),
&Uuid::new_v4().to_string(),
),
user: make_thing(
&ResourceEnum::Users.to_string(),
&Uuid::new_v4().to_string(),
),
item: make_thing(
&ResourceEnum::GachaItems.to_string(),
&Uuid::new_v4().to_string(),
),
is_deleted: false,
created_at: None,
updated_at: None,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GachaRollSchema {
pub id: Thing,
pub item: Thing,
pub weight: f32,
pub quantity: i32,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
impl Default for GachaRollSchema {
fn default() -> Self {
GachaRollSchema {
id: make_thing(
&ResourceEnum::GachaRolls.to_string(),
&Uuid::new_v4().to_string(),
),
item: make_thing(
&ResourceEnum::GachaItems.to_string(),
&Uuid::new_v4().to_string(),
),
weight: 0.2,
quantity: 2,
is_deleted: false,
created_at: None,
updated_at: None,
}
}
}
@@ -1,6 +0,0 @@
pub mod gacha_dto;
pub mod gacha_repository;
pub mod gacha_schema;
pub use gacha_repository::*;
pub use gacha_schema::*;
@@ -0,0 +1,33 @@
use serde::{Deserialize, Serialize};
use surrealdb::sql::Thing;
use utoipa::ToSchema;
use validator::Validate;
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)]
pub struct GachaClaimRequestDto {
#[validate(length(min = 1, message = "User ID must not be empty"))]
pub user_id: String,
#[validate(length(min = 1, message = "Item ID must not be empty"))]
pub item_id: String,
}
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
pub struct GachaClaimDto {
pub id: String,
pub user: String,
pub item: String,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GachaClaimDtoRaw {
pub id: Thing,
pub user: Thing,
pub item: Thing,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
@@ -0,0 +1,42 @@
use super::GachaClaimSchema;
use crate::{AppState, ResourceEnum};
use anyhow::{Result, bail};
pub struct GachaClaimRepository<'a> {
state: &'a AppState,
}
impl<'a> GachaClaimRepository<'a> {
pub fn new(state: &'a AppState) -> Self {
Self { state }
}
pub async fn query_gacha_claim_by_id(
&self,
id: String,
) -> Result<GachaClaimSchema> {
let db = &self.state.surrealdb_ws;
let result: Option<GachaClaimSchema> = db
.select((ResourceEnum::GachaClaims.to_string(), id.clone()))
.await?;
match result {
Some(claim) if !claim.is_deleted => Ok(claim),
_ => bail!("Gacha Claim not found"),
}
}
pub async fn query_create_gacha_claim(
&self,
data: GachaClaimSchema,
) -> Result<String> {
let db = &self.state.surrealdb_ws;
let record: Option<GachaClaimSchema> = db
.create(ResourceEnum::GachaClaims.to_string())
.content(data)
.await?;
match record {
Some(_) => Ok("Success create Gacha Claim".into()),
None => bail!("Failed to create Gacha Claim"),
}
}
}
@@ -0,0 +1,35 @@
use crate::{ResourceEnum, make_thing};
use serde::{Deserialize, Serialize};
use surrealdb::{Uuid, sql::Thing};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GachaClaimSchema {
pub id: Thing,
pub user: Thing,
pub item: Thing,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
impl Default for GachaClaimSchema {
fn default() -> Self {
GachaClaimSchema {
id: make_thing(
&ResourceEnum::GachaClaims.to_string(),
&Uuid::new_v4().to_string(),
),
user: make_thing(
&ResourceEnum::Users.to_string(),
&Uuid::new_v4().to_string(),
),
item: make_thing(
&ResourceEnum::GachaItems.to_string(),
&Uuid::new_v4().to_string(),
),
is_deleted: false,
created_at: None,
updated_at: None,
}
}
}
@@ -0,0 +1,7 @@
pub mod gacha_claim_dto;
pub mod gacha_claim_repository;
pub mod gacha_claim_schema;
pub use gacha_claim_dto::*;
pub use gacha_claim_repository::*;
pub use gacha_claim_schema::*;
@@ -0,0 +1,30 @@
use serde::{Deserialize, Serialize};
use surrealdb::sql::Thing;
use utoipa::ToSchema;
use validator::Validate;
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)]
pub struct GachaItemRequestDto {
#[validate(length(min = 1, message = "Item name must not be empty"))]
pub name: String,
#[validate(length(min = 1, message = "Image URL must not be empty"))]
pub image_url: String,
}
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
pub struct GachaItemDto {
pub id: String,
pub name: String,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GachaItemDtoRaw {
pub id: Thing,
pub name: String,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
@@ -1,15 +1,15 @@
use super::{GachaClaimSchema, GachaItemSchema, GachaRollSchema};
use super::GachaItemSchema;
use crate::{
AppState, MetaRequestDto, ResourceEnum, ResponseListSuccessDto, get_id,
make_thing, query_list_with_meta,
};
use anyhow::{Result, bail};
pub struct GachaRepository<'a> {
pub struct GachaItemRepository<'a> {
state: &'a AppState,
}
impl<'a> GachaRepository<'a> {
impl<'a> GachaItemRepository<'a> {
pub fn new(state: &'a AppState) -> Self {
Self { state }
}
@@ -97,59 +97,4 @@ impl<'a> GachaRepository<'a> {
None => bail!("Failed to delete Gacha Item"),
}
}
pub async fn query_gacha_claim_by_id(
&self,
id: String,
) -> Result<GachaClaimSchema> {
let db = &self.state.surrealdb_ws;
let result: Option<GachaClaimSchema> = db
.select((ResourceEnum::GachaClaims.to_string(), id.clone()))
.await?;
match result {
Some(claim) if !claim.is_deleted => Ok(claim),
_ => bail!("Gacha Claim not found"),
}
}
pub async fn query_create_gacha_claim(
&self,
data: GachaClaimSchema,
) -> Result<String> {
let db = &self.state.surrealdb_ws;
let record: Option<GachaClaimSchema> = db
.create(ResourceEnum::GachaClaims.to_string())
.content(data)
.await?;
match record {
Some(_) => Ok("Success create Gacha Claim".into()),
None => bail!("Failed to create Gacha Claim"),
}
}
pub async fn query_gacha_roll_by_id(&self, id: String) -> Result<GachaRollSchema> {
let db = &self.state.surrealdb_ws;
let result: Option<GachaRollSchema> = db
.select((ResourceEnum::GachaRolls.to_string(), id.clone()))
.await?;
match result {
Some(roll) if !roll.is_deleted => Ok(roll),
_ => bail!("Gacha Roll not found"),
}
}
pub async fn query_create_gacha_roll(
&self,
data: GachaRollSchema,
) -> Result<String> {
let db = &self.state.surrealdb_ws;
let record: Option<GachaRollSchema> = db
.create(ResourceEnum::GachaRolls.to_string())
.content(data)
.await?;
match record {
Some(_) => Ok("Success create Gacha Roll".into()),
None => bail!("Failed to create Gacha Roll"),
}
}
}
@@ -0,0 +1,29 @@
use crate::{ResourceEnum, make_thing};
use serde::{Deserialize, Serialize};
use surrealdb::{Uuid, sql::Thing};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GachaItemSchema {
pub id: Thing,
pub name: String,
pub image_url: String,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
impl Default for GachaItemSchema {
fn default() -> Self {
GachaItemSchema {
id: make_thing(
&ResourceEnum::GachaItems.to_string(),
&Uuid::new_v4().to_string(),
),
name: String::new(),
image_url: String::new(),
is_deleted: false,
created_at: None,
updated_at: None,
}
}
}
@@ -0,0 +1,7 @@
pub mod gacha_item_dto;
pub mod gacha_item_repository;
pub mod gacha_item_schema;
pub use gacha_item_dto::*;
pub use gacha_item_repository::*;
pub use gacha_item_schema::*;
@@ -0,0 +1,38 @@
use serde::{Deserialize, Serialize};
use surrealdb::sql::Thing;
use utoipa::ToSchema;
use validator::Validate;
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)]
pub struct GachaRollRequestDto {
#[validate(length(min = 1, message = "Item ID must not be empty"))]
pub item_id: String,
#[validate(range(min = 1, message = "Weight must be greater than zero"))]
pub weight: f32,
#[validate(range(min = 1, message = "Quantity must be at least 1"))]
pub quantity: i32,
}
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
pub struct GachaRollDto {
pub id: String,
pub item: String,
pub weight: String,
pub quantity: i32,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GachaRollDtoRaw {
pub id: Thing,
pub item: Thing,
pub weight: String,
pub quantity: i32,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
@@ -0,0 +1,39 @@
use super::GachaRollSchema;
use crate::{AppState, ResourceEnum};
use anyhow::{Result, bail};
pub struct GachaRollRepository<'a> {
state: &'a AppState,
}
impl<'a> GachaRollRepository<'a> {
pub fn new(state: &'a AppState) -> Self {
Self { state }
}
pub async fn query_gacha_roll_by_id(&self, id: String) -> Result<GachaRollSchema> {
let db = &self.state.surrealdb_ws;
let result: Option<GachaRollSchema> = db
.select((ResourceEnum::GachaRolls.to_string(), id.clone()))
.await?;
match result {
Some(roll) if !roll.is_deleted => Ok(roll),
_ => bail!("Gacha Roll not found"),
}
}
pub async fn query_create_gacha_roll(
&self,
data: GachaRollSchema,
) -> Result<String> {
let db = &self.state.surrealdb_ws;
let record: Option<GachaRollSchema> = db
.create(ResourceEnum::GachaRolls.to_string())
.content(data)
.await?;
match record {
Some(_) => Ok("Success create Gacha Roll".into()),
None => bail!("Failed to create Gacha Roll"),
}
}
}
@@ -0,0 +1,34 @@
use crate::{ResourceEnum, make_thing};
use serde::{Deserialize, Serialize};
use surrealdb::{Uuid, sql::Thing};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GachaRollSchema {
pub id: Thing,
pub item: Thing,
pub weight: f32,
pub quantity: i32,
pub is_deleted: bool,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
impl Default for GachaRollSchema {
fn default() -> Self {
GachaRollSchema {
id: make_thing(
&ResourceEnum::GachaRolls.to_string(),
&Uuid::new_v4().to_string(),
),
item: make_thing(
&ResourceEnum::GachaItems.to_string(),
&Uuid::new_v4().to_string(),
),
weight: 0.2,
quantity: 2,
is_deleted: false,
created_at: None,
updated_at: None,
}
}
}
@@ -0,0 +1,7 @@
pub mod gacha_roll_dto;
pub mod gacha_roll_repository;
pub mod gacha_roll_schema;
pub use gacha_roll_dto::*;
pub use gacha_roll_repository::*;
pub use gacha_roll_schema::*;
+7 -2
View File
@@ -1,2 +1,7 @@
pub mod gacha;
pub use gacha::*;
pub mod gacha_claim;
pub mod gacha_item;
pub mod gacha_roll;
pub use gacha_claim::*;
pub use gacha_item::*;
pub use gacha_roll::*;
+6 -1
View File
@@ -52,12 +52,17 @@ pub fn cors_middleware() -> CorsLayer {
let cors_origins = match env.rust_env.as_str() {
"development" => vec!["http://localhost:3000"],
"production" => {
vec!["https://gacha.imphnen.dev", "https://imphnen.dev"]
vec![
"https://gacha.imphnen.dev",
"https://imphnen.dev",
"https://dimentorin.imphnen.dev",
]
}
_ => vec![
"http://localhost:3000",
"https://gacha.imphnen.dev",
"https://imphnen.dev",
"https://dimentorin.imphnen.dev",
],
};
let allowed_origins: Vec<HeaderValue> = cors_origins
@@ -4,6 +4,7 @@ use std::fmt;
pub enum RolesEnum {
Admin,
User,
Student,
Staf,
}
@@ -12,6 +13,7 @@ impl fmt::Display for RolesEnum {
let roles_str = match self {
RolesEnum::Admin => "Admin",
RolesEnum::User => "User",
RolesEnum::Student => "Student",
RolesEnum::Staf => "Staf",
};
write!(f, "{}", roles_str)
View File