Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion backend/src/handlers/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
39 changes: 37 additions & 2 deletions backend/src/handlers/rewards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<RewardResponse>,
Expand Down Expand Up @@ -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;
Expand All @@ -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,
Expand Down
25 changes: 24 additions & 1 deletion backend/src/services/transaction.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -18,6 +18,29 @@ impl TransactionService {
Self { db }
}

pub async fn get_ccup_total_purchased(&self, user_dorm: &str) -> Result<i32, sea_orm::DbErr> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can probably be done with one database call. I haven't read into this code thoroughly, but something like this may work:

let total: Option<i32> = Transaction::find()
    .inner_join(User)
    .filter(transaction::Column::RewardName.eq("Carnegie Cup Contribution"))
    .filter(user::Column::Dorm.eq(user_dorm))
    .select_only()
    .column_as(transaction::Column::Count.sum(), "total")
    .into_tuple::<i32>()
    .one(&self.db)
    .await?;
    
Ok(total.unwrap_or(0))

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::<Vec<_>>();

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,
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/trade/prize-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export function PrizeCard({ prize }: PrizeCardProps) {
<div className="flex justify-center items-center gap-2.5">
<div className="justify-start">
<span className="text-gray-500 text-xs font-bold font-['Open_Sans'] leading-none tracking-tight">
Stock: {!isCarnegieCup ? stock : "∞"}
Stock: {stock >= 0 ? stock : "∞"}
</span>
</div>
</div>
Expand All @@ -81,7 +81,7 @@ export function PrizeCard({ prize }: PrizeCardProps) {
}}
/>
<span className="absolute inset-0 flex items-center justify-center text-white text-xs font-bold">
{claimed}/{!isCarnegieCup ? prize.trade_limit : "∞"}
{claimed}/{stock >= 0 ? prize.trade_limit : "∞"}
</span>
</div>
</div>
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/lib/data/dorms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/routes/dorm-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,13 @@ const MascotData: Record<DormName, { mascotName: string; chant: string }> = {
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!!"',
},
};

Expand Down
Loading