Phase 9: division/season tracking, club customization, pack history, notifications
CI / Build, lint & test (push) Failing after 1m42s
CI / Build, lint & test (push) Failing after 1m42s
- GET /division returns live season stats (points, record, promotion threshold) - PUT /club allows updating club name and manager_name - GET /packs/history returns opened packs with full card definitions - GET /notifications dynamically surfaces completed objectives, expiring loans, season end - Club model gains manager_name column (migration 0006 already added it) - Pack model gains opened_cards and opened_at; pack SELECT queries updated - 9 new integration tests — all 45 pass, clippy clean Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+46
-8
@@ -5,19 +5,30 @@ use crate::{
|
||||
};
|
||||
use chrono::Utc;
|
||||
|
||||
const CLUB_SELECT: &str =
|
||||
"SELECT id, profile_id, name, coins, level, created_at, updated_at, manager_name \
|
||||
FROM clubs";
|
||||
|
||||
pub async fn get_club_by_profile(pool: &Pool, profile_id: &str) -> AppResult<Club> {
|
||||
sqlx::query_as::<_, Club>(
|
||||
"SELECT id, profile_id, name, coins, level, created_at, updated_at FROM clubs WHERE profile_id = ? LIMIT 1"
|
||||
)
|
||||
.bind(profile_id)
|
||||
.fetch_optional(pool)
|
||||
.await?
|
||||
.ok_or_else(|| AppError::NotFound("club not found".into()))
|
||||
sqlx::query_as::<_, Club>(&format!("{CLUB_SELECT} WHERE profile_id = ? LIMIT 1"))
|
||||
.bind(profile_id)
|
||||
.fetch_optional(pool)
|
||||
.await?
|
||||
.ok_or_else(|| AppError::NotFound("club not found".into()))
|
||||
}
|
||||
|
||||
pub async fn get_club_by_id(pool: &Pool, club_id: &str) -> AppResult<Club> {
|
||||
sqlx::query_as::<_, Club>(&format!("{CLUB_SELECT} WHERE id = ? LIMIT 1"))
|
||||
.bind(club_id)
|
||||
.fetch_optional(pool)
|
||||
.await?
|
||||
.ok_or_else(|| AppError::NotFound("club not found".into()))
|
||||
}
|
||||
|
||||
pub async fn create_club(pool: &Pool, club: &Club) -> AppResult<()> {
|
||||
sqlx::query(
|
||||
"INSERT INTO clubs (id, profile_id, name, coins, level, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)"
|
||||
"INSERT INTO clubs (id, profile_id, name, coins, level, created_at, updated_at, manager_name) \
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
)
|
||||
.bind(&club.id)
|
||||
.bind(&club.profile_id)
|
||||
@@ -26,11 +37,38 @@ pub async fn create_club(pool: &Pool, club: &Club) -> AppResult<()> {
|
||||
.bind(club.level)
|
||||
.bind(club.created_at)
|
||||
.bind(club.updated_at)
|
||||
.bind(&club.manager_name)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn update_club(
|
||||
pool: &Pool,
|
||||
club_id: &str,
|
||||
name: Option<&str>,
|
||||
manager_name: Option<&str>,
|
||||
) -> AppResult<Club> {
|
||||
let now = Utc::now();
|
||||
if let Some(n) = name {
|
||||
sqlx::query("UPDATE clubs SET name = ?, updated_at = ? WHERE id = ?")
|
||||
.bind(n)
|
||||
.bind(now)
|
||||
.bind(club_id)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
}
|
||||
if let Some(m) = manager_name {
|
||||
sqlx::query("UPDATE clubs SET manager_name = ?, updated_at = ? WHERE id = ?")
|
||||
.bind(m)
|
||||
.bind(now)
|
||||
.bind(club_id)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
}
|
||||
get_club_by_id(pool, club_id).await
|
||||
}
|
||||
|
||||
pub async fn add_coins(pool: &Pool, club_id: &str, amount: i64) -> AppResult<i64> {
|
||||
let now = Utc::now();
|
||||
sqlx::query("UPDATE clubs SET coins = coins + ?, updated_at = ? WHERE id = ?")
|
||||
|
||||
Reference in New Issue
Block a user