From 8a09e535e4f35629ab62ca80673f8a2f667abdea Mon Sep 17 00:00:00 2001 From: evermake Date: Sun, 24 Mar 2024 21:46:59 +0300 Subject: [PATCH] feat: implement `getSemestersSummary` method --- backend/src/domain/index.ts | 47 +++++++++++++++++++++++++++ backend/src/domain/types.ts | 8 +++++ backend/src/services/sport/client.ts | 16 ++------- backend/src/services/sport/schemas.ts | 2 +- 4 files changed, 58 insertions(+), 15 deletions(-) create mode 100644 backend/src/domain/types.ts diff --git a/backend/src/domain/index.ts b/backend/src/domain/index.ts index 52bb0f4..816115e 100644 --- a/backend/src/domain/index.ts +++ b/backend/src/domain/index.ts @@ -1,4 +1,5 @@ import { User } from './schemas/user' +import type { SemesterSummary } from './types' import type { Logger } from '~/utils/logging' import type { Database } from '~/services/database' import type { SportClient } from '~/services/sport' @@ -150,4 +151,50 @@ export class Domain { trainingId: trainingId, }) } + + public async getSemestersSummary({ + telegramId, + }: { + telegramId: number + }): Promise { + const user = await this.db.user.findFirstOrThrow({ + where: { + telegramId: telegramId, + sportId: { not: null }, + }, + select: { sportId: true }, + }) + + const [semesters, sportHours, allFitnessTests] = await Promise.all([ + this.sport.getAllSemesters(), + this.sport.getSportHoursInfo({ studentId: user.sportId! }), + this.sport.getAllFitnessTestResults({ studentId: user.sportId! }), + ]) + + const allSportHours = [ + sportHours.ongoing_semester, + ...sportHours.last_semesters_hours, + ] + + return semesters.map(({ id, name }) => { + const semesterSportHours = allSportHours.find(h => h.id_sem === id) + const semesterFitnessTest = allFitnessTests.find(t => t.semester === name) + + return { + title: name, + hoursTotal: semesterSportHours + ? (semesterSportHours.hours_not_self + semesterSportHours.hours_self_not_debt) + : 0, + fitnessTest: semesterFitnessTest + ? { + passed: semesterFitnessTest.grade, + pointsTotal: semesterFitnessTest.total_score, + } + : { + passed: false, + pointsTotal: 0, + }, + } + }) + } } diff --git a/backend/src/domain/types.ts b/backend/src/domain/types.ts new file mode 100644 index 0000000..e6bb03b --- /dev/null +++ b/backend/src/domain/types.ts @@ -0,0 +1,8 @@ +export type SemesterSummary = { + title: string + hoursTotal: number + fitnessTest: { + passed: boolean + pointsTotal: number + } +} diff --git a/backend/src/services/sport/client.ts b/backend/src/services/sport/client.ts index 1410c66..479291e 100644 --- a/backend/src/services/sport/client.ts +++ b/backend/src/services/sport/client.ts @@ -2,7 +2,7 @@ import axios from 'axios' import { z } from 'zod' import type { AxiosInstance } from 'axios' import type { TrainingDetailed, TrainingInfo } from './types' -import { CalendarTraining, Training } from './schemas' +import { CalendarTraining, FitnessTestResult, Training } from './schemas' import type { Logger } from '~/utils/logging' /** @@ -224,19 +224,7 @@ export class SportClient { return this.request({ method: 'GET', path: '/fitnesstest/result', - responseSchema: z.array(z.object({ - semester: z.string(), - retake: z.boolean(), - grade: z.number(), - total_score: z.number(), - details: z.array(z.object({ - exercise: z.string(), - unit: z.string(), - value: z.union([z.string(), z.number()]), - score: z.number(), - max_score: z.number(), - })), - })), + responseSchema: z.array(FitnessTestResult), }) } diff --git a/backend/src/services/sport/schemas.ts b/backend/src/services/sport/schemas.ts index d904fba..3d9e2cf 100644 --- a/backend/src/services/sport/schemas.ts +++ b/backend/src/services/sport/schemas.ts @@ -27,7 +27,7 @@ export const Group = z.object({ export const FitnessTestExerciseResult = z.object({ exercise: z.string(), - unit: z.string(), + unit: z.string().nullable(), value: z.union([z.number(), z.string()]), score: z.number(), max_score: z.number(),