From 3480a4d5e44cdbcbf9fd51ef77fd5a8403ea92ec Mon Sep 17 00:00:00 2001 From: Theodor Urban Date: Tue, 19 Aug 2025 21:59:16 -0400 Subject: [PATCH 1/2] feat: for carnegie cup, display community progress instead of infinity --- backend/src/handlers/completion.rs | 1 - backend/src/handlers/rewards.rs | 39 +++++++++++++++++++- backend/src/services/transaction.rs | 25 ++++++++++++- frontend/src/components/trade/prize-card.tsx | 4 +- frontend/src/lib/data/dorms.ts | 5 +++ frontend/src/routes/dorm-select.tsx | 6 ++- 6 files changed, 73 insertions(+), 7 deletions(-) diff --git a/backend/src/handlers/completion.rs b/backend/src/handlers/completion.rs index 57082bd..1217e01 100644 --- a/backend/src/handlers/completion.rs +++ b/backend/src/handlers/completion.rs @@ -2,7 +2,6 @@ use crate::services::traits::{ChallengeServiceTrait, CompletionServiceTrait}; use crate::{AppState, AuthClaims}; use axum::{Extension, Json, extract::State, http::StatusCode}; use chrono::{NaiveDateTime, Utc}; -use minio::s3; use rust_decimal::prelude::ToPrimitive; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; diff --git a/backend/src/handlers/rewards.rs b/backend/src/handlers/rewards.rs index f5723c2..b7a9ef8 100644 --- a/backend/src/handlers/rewards.rs +++ b/backend/src/handlers/rewards.rs @@ -5,6 +5,21 @@ use chrono::NaiveDateTime; use serde::Serialize; use utoipa::ToSchema; +const CCUP_LIMIT_BY_DORM: fn(&str) -> i32 = |dorm| match dorm { + "Res on Fifth" => 4350, + "McGill and Boss" => 4350, + "The Hill" => 4350, + "Hammerschlag" => 4350, + "Mudge" => 8670, + "Stever" => 8670, + "Morewood E-Tower" => 6090, + "Morewood Gardens" => 4170, + "Donner" => 6960, + "Margaret Morrison" => 8010, + "Whesco" => 8010, + _ => -1, +}; + #[derive(Serialize, ToSchema)] pub struct RewardsListResponse { pub rewards: Vec, @@ -69,6 +84,8 @@ pub async fn get_rewards( let mut incomplete_count = 0; let mut complete_count = 0; let mut transaction_details = Vec::new(); + let mut stock = reward.stock; + let mut trade_limit = reward.trade_limit; for transaction in transactions { total_purchased += transaction.count; @@ -89,12 +106,30 @@ pub async fn get_rewards( // Sort transactions by timestamp, most recent first transaction_details.sort_by(|a, b| b.timestamp.cmp(&a.timestamp)); + if reward.name.eq("Carnegie Cup Contribution") { + let user_dorm = state + .user_service + .get_or_create_user(&claims.sub, &claims.name) + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? + .dorm; + + let user_dorm = user_dorm.as_deref().unwrap_or("Unknown"); + + stock = CCUP_LIMIT_BY_DORM(user_dorm); + trade_limit = stock; + total_purchased = state + .transaction_service + .get_ccup_total_purchased(user_dorm) + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + } reward_responses.push(RewardResponse { name: reward.name.clone(), cost: reward.cost, - stock: reward.stock, - trade_limit: reward.trade_limit, + stock: stock, + trade_limit: trade_limit, transaction_info: RewardTransactionInfo { total_purchased, incomplete_count, diff --git a/backend/src/services/transaction.rs b/backend/src/services/transaction.rs index 5980088..b700997 100644 --- a/backend/src/services/transaction.rs +++ b/backend/src/services/transaction.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use crate::entities::{prelude::*, reward, transaction}; +use crate::entities::{prelude::*, reward, transaction, user}; use chrono::Utc; use sea_orm::{ ActiveModelTrait, ActiveValue::Set, ColumnTrait, DatabaseConnection, EntityTrait, JoinType, @@ -18,6 +18,29 @@ impl TransactionService { Self { db } } + pub async fn get_ccup_total_purchased(&self, user_dorm: &str) -> Result { + let all_ccup_transactions = Transaction::find() + .filter(transaction::Column::RewardName.eq("Carnegie Cup Contribution")) + .all(&self.db) + .await?; + + let all_dorm_userids = User::find() + .filter(user::Column::Dorm.eq(user_dorm)) + .all(&self.db) + .await? + .iter() + .map(|user| user.user_id.clone()) + .collect::>(); + + let total = all_ccup_transactions + .iter() + .filter(|tx| all_dorm_userids.contains(&tx.user_id)) + .map(|tx| tx.count) + .sum(); + + Ok(total) + } + pub async fn create_transaction( &self, user_id: &str, diff --git a/frontend/src/components/trade/prize-card.tsx b/frontend/src/components/trade/prize-card.tsx index 9e79117..a238d2b 100644 --- a/frontend/src/components/trade/prize-card.tsx +++ b/frontend/src/components/trade/prize-card.tsx @@ -63,7 +63,7 @@ export function PrizeCard({ prize }: PrizeCardProps) {
- Stock: {!isCarnegieCup ? stock : "∞"} + Stock: {stock >= 0 ? stock : "∞"}
@@ -81,7 +81,7 @@ export function PrizeCard({ prize }: PrizeCardProps) { }} /> - {claimed}/{!isCarnegieCup ? prize.trade_limit : "∞"} + {claimed}/{stock >= 0 ? prize.trade_limit : "∞"} diff --git a/frontend/src/lib/data/dorms.ts b/frontend/src/lib/data/dorms.ts index d56c49a..a73178d 100644 --- a/frontend/src/lib/data/dorms.ts +++ b/frontend/src/lib/data/dorms.ts @@ -44,6 +44,11 @@ export const dorms = [ image_path: "/images/dorm-mascots/redpanda.png", group: "HamBaM", }, + { + name: "The Hill", + image_path: "/images/dorm-mascots/redpanda.png", + group: "HamBaM", + }, { name: "Margaret Morrison", image_path: "/images/dorm-mascots/aimagpie.png", diff --git a/frontend/src/routes/dorm-select.tsx b/frontend/src/routes/dorm-select.tsx index dbb83c8..3699e12 100644 --- a/frontend/src/routes/dorm-select.tsx +++ b/frontend/src/routes/dorm-select.tsx @@ -59,9 +59,13 @@ const MascotData: Record = { mascotName: "Randal the Red Panda", chant: '"Can I get a Hill Yeah?! Hill Yeah!!"\n~McGill and Boss', }, + "The Hill": { + mascotName: "Randal the Red Panda", + chant: '"Can I get a Hill Yeah?! Hill Yeah!!"\n~The Hill', + }, "Margaret Morrison": { mascotName: "Aimee the Magpie", - chant: '"What do we need?! Morisson!!"', + chant: '"What do we need?! Morrison!!"', }, }; From 2f9fb4ba4539e69d8fd093afc6369bd108e6d9ba Mon Sep 17 00:00:00 2001 From: Theodor Urban Date: Wed, 20 Aug 2025 10:48:38 -0400 Subject: [PATCH 2/2] more efficient db call --- backend/src/handlers/rewards.rs | 4 +++- backend/src/services/transaction.rs | 35 +++++++++++++---------------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/backend/src/handlers/rewards.rs b/backend/src/handlers/rewards.rs index b7a9ef8..5cf9bba 100644 --- a/backend/src/handlers/rewards.rs +++ b/backend/src/handlers/rewards.rs @@ -122,7 +122,9 @@ pub async fn get_rewards( .transaction_service .get_ccup_total_purchased(user_dorm) .await - .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? + .try_into() + .unwrap(); } reward_responses.push(RewardResponse { diff --git a/backend/src/services/transaction.rs b/backend/src/services/transaction.rs index b700997..e1525ce 100644 --- a/backend/src/services/transaction.rs +++ b/backend/src/services/transaction.rs @@ -18,27 +18,24 @@ impl TransactionService { Self { db } } - pub async fn get_ccup_total_purchased(&self, user_dorm: &str) -> Result { - let all_ccup_transactions = Transaction::find() + pub async fn get_ccup_total_purchased(&self, user_dorm: &str) -> Result { + let total: Option = Transaction::find() + .inner_join(User) .filter(transaction::Column::RewardName.eq("Carnegie Cup Contribution")) - .all(&self.db) - .await?; - - let all_dorm_userids = User::find() .filter(user::Column::Dorm.eq(user_dorm)) - .all(&self.db) - .await? - .iter() - .map(|user| user.user_id.clone()) - .collect::>(); - - let total = all_ccup_transactions - .iter() - .filter(|tx| all_dorm_userids.contains(&tx.user_id)) - .map(|tx| tx.count) - .sum(); - - Ok(total) + .select_only() + .column_as(transaction::Column::Count.sum(), "total") + .into_tuple::() + .one(&self.db) + .await + .inspect_err(|f| { + eprintln!( + "Failed to get total purchased for Carnegie Cup Contribution: {}", + f + ); + })?; + + Ok(total.unwrap_or(0)) } pub async fn create_transaction(