Skip to content

Commit ec43ee0

Browse files
authored
Feat/leaderboard (#64)
- Leaderboard Service - Get Male M4 Top 20 - Get Male M5 Top 20 - Get Female M4 Top 20 - Get Female M5 Top 20 - Get Reserve Male M4 Top 5 (after top 20) - Get Reserve Male M5 Top 5 (after top 20) - Get Reserve Female M4 Top 5 (after top 20) - Get Reserve Female M5 Top 5 (after top 20) - Status Result and Allow confirm Service
2 parents 3301ef1 + 99f7912 commit ec43ee0

17 files changed

Lines changed: 769 additions & 6 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-- CreateTable
2+
CREATE TABLE "ApplicationTotalScore" (
3+
"std_application_id" TEXT NOT NULL,
4+
"std_total_score" DOUBLE PRECISION NOT NULL,
5+
"std_regis_score" DOUBLE PRECISION NOT NULL,
6+
"std_academic_score" DOUBLE PRECISION NOT NULL,
7+
"std_academic_chaos_score" DOUBLE PRECISION NOT NULL,
8+
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
9+
"updated_at" TIMESTAMP(3) NOT NULL,
10+
11+
CONSTRAINT "ApplicationTotalScore_pkey" PRIMARY KEY ("std_application_id")
12+
);
13+
14+
-- AddForeignKey
15+
ALTER TABLE "ApplicationTotalScore" ADD CONSTRAINT "ApplicationTotalScore_std_application_id_fkey" FOREIGN KEY ("std_application_id") REFERENCES "StudentApplication"("std_application_id") ON DELETE RESTRICT ON UPDATE CASCADE;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- AlterTable
2+
ALTER TABLE "ApplicationTotalScore" ALTER COLUMN "std_academic_score" DROP NOT NULL;

prisma/schema.prisma

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,19 @@ datasource db {
99
provider = "postgresql"
1010
}
1111

12+
model ApplicationTotalScore {
13+
std_application_id String @id
14+
std_application StudentApplication @relation(fields: [std_application_id], references: [std_application_id])
15+
16+
std_total_score Float
17+
std_regis_score Float
18+
std_academic_score Float?
19+
std_academic_chaos_score Float
20+
21+
created_at DateTime @default(now())
22+
updated_at DateTime @updatedAt
23+
}
24+
1225
model StaffEmailHistory {
1326
email_id String @default(uuid()) @id
1427
@@ -285,6 +298,8 @@ model StudentApplication {
285298
std_regis_question ApplicationRegisQuestionAnswer[]
286299
std_academic_question ApplicationAcademicQuestionAnswer[]
287300
std_academic_chaos_question ApplicationAcademicChaosQuestionAnswer[]
301+
302+
std_total_score ApplicationTotalScore?
288303
289304
std_status ApplicationStatus?
290305

src/app.module.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ import { StaffAccountModule } from "./modules/staff-account/staff-account.module
3232
import { StaffApplicationModule } from "./modules/staff-application/staff-application.module";
3333
import { StaffEmailModule } from "./modules/staff-email/staff-email.module";
3434
import { StaffFileModule } from "./modules/staff-file/staff-file.module";
35+
import { StaffLeaderboardModule } from "./modules/staff-leaderboard/staff-leaderboard.module";
3536
import { StaffRegisGradingModule } from "./modules/staff-regis-grading/staff-regis-grading.module";
3637
import { StaffRegisQuestionModule } from "./modules/staff-regis-question/staff-regis-question.module";
3738
import { StaffStatisticModule } from "./modules/staff-statistic/staff-statistic.module";
3839
import { StaffStatusModule } from "./modules/staff-status/staff-status.module";
3940
import { StaffStatusUpdaterModule } from "./modules/staff-status-updater/staff-status-updater.module";
41+
import { StaffTotalScoreModule } from "./modules/staff-total-score/staff-total-score.module";
4042
import { StatusUpdaterModule } from "./modules/status-updater/status-updater.module";
4143
import { StudentApplicationModule } from "./modules/student-application/student-application.module";
4244
import { TicketModule } from "./modules/ticket/ticket.module";
@@ -85,6 +87,8 @@ import { UtilModule } from "./modules/util/util.module";
8587
StaffAcademicChaosGradingModule,
8688
TicketModule,
8789
StaffEmailModule,
90+
StaffTotalScoreModule,
91+
StaffLeaderboardModule,
8892
],
8993

9094
controllers: [AppController],

src/core/logger/logger.service.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ export class LoggerService {
1616
this.logger.info(ctx.join(" "));
1717
}
1818

19+
success(...ctx: any[]) {
20+
this.logger.success(ctx.join(" "));
21+
}
22+
1923
error(...ctx: any[]) {
2024
this.logger.error(ctx.join(" "));
2125
this.discordWebhook.send(this.discordWebhook.errorEmbed(ctx.join(" ")));
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Controller, Get, Param, ParseEnumPipe, UseGuards } from "@nestjs/common";
2+
import { AppInfoGender } from "generated/prisma/enums";
3+
import { AnnouncePeriodGuard } from "src/common/guards/announce-period.guard";
4+
import { RegisGuard } from "src/common/guards/regis.guard";
5+
import { StaffLeaderboardService } from "./staff-leaderboard.service";
6+
7+
export enum EducationLevel {
8+
M4 = "m4",
9+
M5 = "m5",
10+
}
11+
12+
@Controller("/api/staff/leaderboard")
13+
export class StaffLeaderboardController {
14+
constructor(private readonly staffLeaderboardService: StaffLeaderboardService) {}
15+
16+
@Get("/pass/:gender/:level")
17+
@UseGuards(RegisGuard)
18+
getPassApplication(@Param("gender", new ParseEnumPipe(AppInfoGender)) gender: AppInfoGender, @Param("level", new ParseEnumPipe(EducationLevel)) level: EducationLevel) {
19+
console.log(level);
20+
return this.staffLeaderboardService.getPassApplication(gender, level);
21+
}
22+
23+
@Get("/reserve/:gender/:level")
24+
@UseGuards(RegisGuard)
25+
getReserveApplication(@Param("gender", new ParseEnumPipe(AppInfoGender)) gender: AppInfoGender, @Param("level", new ParseEnumPipe(EducationLevel)) level: EducationLevel) {
26+
return this.staffLeaderboardService.getReserveApplication(gender, level);
27+
}
28+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Module } from "@nestjs/common";
2+
import { StaffLeaderboardController } from "./staff-leaderboard.controller";
3+
import { StaffLeaderboardService } from "./staff-leaderboard.service";
4+
5+
@Module({
6+
controllers: [StaffLeaderboardController],
7+
providers: [StaffLeaderboardService],
8+
})
9+
export class StaffLeaderboardModule {}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { HttpException, Injectable, InternalServerErrorException } from "@nestjs/common";
2+
import { AppInfoGender } from "generated/prisma/enums";
3+
import { LoggerService } from "src/core/logger/logger.service";
4+
import { PrismaService } from "src/core/prisma/prisma.service";
5+
import { EducationLevel } from "./staff-leaderboard.controller";
6+
7+
const educationLevelKey = {
8+
m4: "มัธยมศึกษาปีที่ 4",
9+
m5: "มัธยมศึกษาปีที่ 5",
10+
v1: "ปวช. 1",
11+
v2: "ปวช. 2",
12+
};
13+
14+
@Injectable()
15+
export class StaffLeaderboardService {
16+
constructor(
17+
private readonly prisma: PrismaService,
18+
private readonly logger: LoggerService,
19+
) {}
20+
21+
async getPassApplication(gender: AppInfoGender, level: EducationLevel) {
22+
try {
23+
const getTopScore = await this.prisma.studentApplication.findMany({
24+
where: {
25+
std_total_score: {
26+
isNot: null,
27+
},
28+
std_info: {
29+
std_info_gender: gender,
30+
OR: [
31+
{
32+
std_info_education_level: encodeURI(level === EducationLevel.M4 ? educationLevelKey.m4 : educationLevelKey.m5),
33+
},
34+
{
35+
std_info_education_level: encodeURI(level === EducationLevel.M4 ? educationLevelKey.v1 : educationLevelKey.v2),
36+
},
37+
],
38+
},
39+
},
40+
orderBy: {
41+
std_total_score: {
42+
std_total_score: "desc",
43+
},
44+
},
45+
include: {
46+
std_total_score: true,
47+
std_status: true,
48+
std_info: true,
49+
},
50+
skip: 0,
51+
take: 20,
52+
});
53+
54+
return getTopScore;
55+
} catch (e) {
56+
this.logger.error(e);
57+
if (e instanceof HttpException) {
58+
throw e;
59+
}
60+
61+
throw new InternalServerErrorException(e);
62+
}
63+
}
64+
65+
async getReserveApplication(gender: AppInfoGender, level: EducationLevel) {
66+
try {
67+
const getTopScore = await this.prisma.studentApplication.findMany({
68+
where: {
69+
std_total_score: {
70+
isNot: null,
71+
},
72+
std_info: {
73+
std_info_gender: gender,
74+
OR: [
75+
{
76+
std_info_education_level: encodeURI(level === EducationLevel.M4 ? educationLevelKey.m4 : educationLevelKey.m5),
77+
},
78+
{
79+
std_info_education_level: encodeURI(level === EducationLevel.M4 ? educationLevelKey.v1 : educationLevelKey.v2),
80+
},
81+
],
82+
},
83+
},
84+
orderBy: {
85+
std_total_score: {
86+
std_total_score: "desc",
87+
},
88+
},
89+
include: {
90+
std_total_score: true,
91+
std_status: true,
92+
std_info: true,
93+
},
94+
take: 5,
95+
skip: 20,
96+
});
97+
98+
return getTopScore;
99+
} catch (e) {
100+
this.logger.error(e);
101+
if (e instanceof HttpException) {
102+
throw e;
103+
}
104+
105+
throw new InternalServerErrorException(e);
106+
}
107+
}
108+
}

src/modules/staff-status/dto/staff-status.dto.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ApiProperty } from "@nestjs/swagger";
2-
import { IsBoolean, IsEnum, IsString } from "class-validator";
3-
import { AppInfoStatus } from "../../../../generated/prisma/enums";
2+
import { IsBoolean, IsEnum, IsString, IsUUID } from "class-validator";
3+
import { AppInfoGender, AppInfoStatus, ApplicationResult } from "../../../../generated/prisma/enums";
44

55
export class AppStatusInfoCheckDto {
66
@ApiProperty({
@@ -34,3 +34,21 @@ export class AppStatusCommentDto {
3434
@IsString()
3535
readonly comment: string;
3636
}
37+
38+
export class AllowToConfirmDto {
39+
@IsString()
40+
@IsUUID()
41+
readonly application_id: string;
42+
43+
@IsBoolean()
44+
readonly confirm: boolean;
45+
}
46+
47+
export class ChangeResultDto {
48+
@IsString()
49+
@IsUUID()
50+
readonly application_id: string;
51+
52+
@IsEnum(ApplicationResult)
53+
readonly result: ApplicationResult;
54+
}

src/modules/staff-status/staff-status.controller.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Body, Controller, Get, Param, Post, UseGuards } from "@nestjs/common";
22
import { ApiBody, ApiOperation, ApiParam, ApiResponse, ApiTags } from "@nestjs/swagger";
33
import { Session, type UserSession } from "@thallesp/nestjs-better-auth";
44
import { RegisGuard } from "src/common/guards/regis.guard";
5-
import { AppStatusCommentDto, AppStatusInfoCheckDto } from "./dto/staff-status.dto";
5+
import { AllowToConfirmDto, AppStatusCommentDto, AppStatusInfoCheckDto, ChangeResultDto } from "./dto/staff-status.dto";
66
import { StaffInfoCheckResponseDto, StaffStatusResponseDto } from "./dto/staff-status-response.dto";
77
import { StaffStatusService } from "./staff-status.service";
88

@@ -98,4 +98,14 @@ export class StaffStatusController {
9898
infoComment(@Body() appStatusInfoCommentDto: AppStatusCommentDto) {
9999
return;
100100
}
101+
102+
@Post("/allow-to-confirm")
103+
@UseGuards(RegisGuard)
104+
allowToConfirm(@Body() allowToConfirmDto: AllowToConfirmDto) {
105+
return this.staffStatusService.allowToConfirm(allowToConfirmDto);
106+
}
107+
108+
@Post("/change-result")
109+
@UseGuards(RegisGuard)
110+
changeResult(@Body() changeResultDto: ChangeResultDto) {}
101111
}

0 commit comments

Comments
 (0)