From e3a06f1ba975ba43698994142ea9bb97e6490535 Mon Sep 17 00:00:00 2001 From: Ly Tuan Kiet Date: Mon, 9 Dec 2024 18:35:01 +0700 Subject: [PATCH] feat: add scheduled quiz notification task and enhance Quiz schema with scheduleId - Introduced a new cron job in CronService to check for schedules with status WAITING_QUIZ and notify customers to complete their quizzes. - Enhanced the Quiz schema by adding an optional 'scheduleId' argument to facilitate quiz retrieval based on specific schedules, improving user experience and data association. - Updated role-based access control logic to ensure proper handling of quiz queries for customers and center mentors. --- src/Cron/cron.service.ts | 24 +++++++++++++++++++ src/Quiz/quiz.schema.ts | 52 +++++++++++++++++++++++++++++----------- 2 files changed, 62 insertions(+), 14 deletions(-) diff --git a/src/Cron/cron.service.ts b/src/Cron/cron.service.ts index 96a8adc..067a264 100644 --- a/src/Cron/cron.service.ts +++ b/src/Cron/cron.service.ts @@ -219,4 +219,28 @@ export class CronService { Logger.log(`Service ${service.id} has been disabled`, 'CronService') } } + + @Cron(CronExpression.EVERY_4_HOURS) + async taskCheckQuiz() { + // check all schedule have status WAITING_QUIZ and notify customer to do quiz + Logger.log('Checking quiz', 'CronService') + const schedules = await this.prisma.schedule.findMany({ + where: { + status: ScheduleStatus.WAITING_QUIZ, + }, + }) + for (const schedule of schedules) { + if (!schedule.customerId) { + continue + } + await this.notificationService.sendNotification( + schedule.customerId, + 'Bạn có lịch hướng dẫn cần hoàn thành bài kiểm tra', + `Lịch hướng dẫn với ngày bắt đầu: ${DateTimeUtils.format( + DateTimeUtils.fromDate(schedule.scheduleStart), + 'D', + )}, slot: ${schedule.slots.map((s) => s).join(', ')} của bạn đã được đăng ký, vui lòng hoàn thành bài kiểm tra để tiếp tục`, + ) + } + } } diff --git a/src/Quiz/quiz.schema.ts b/src/Quiz/quiz.schema.ts index 62f8576..1f2d902 100644 --- a/src/Quiz/quiz.schema.ts +++ b/src/Quiz/quiz.schema.ts @@ -151,6 +151,10 @@ export class QuizSchema extends PothosSchema { type: 'String', required: true, }), + scheduleId: t.arg({ + type: 'String', + required: false, + }), }, resolve: async (query, _root, args, ctx, _info) => { if (ctx.isSubscription) { @@ -159,22 +163,42 @@ export class QuizSchema extends PothosSchema { if (!ctx.http.me) { throw new Error('Unauthorized') } - if (ctx.http.me.role !== Role.CENTER_MENTOR && ctx.http.me.role !== Role.CENTER_OWNER) { - throw new Error('Unauthorized') + // use case 1: center mentor or center owner + if (ctx.http.me.role === Role.CENTER_MENTOR || ctx.http.me.role === Role.CENTER_OWNER) { + const centerMentor = await this.prisma.centerMentor.findUnique({ + where: { mentorId: ctx.http.me.id }, + }) + if (!centerMentor) { + throw new Error('Center mentor not found') + } + return await this.prisma.quiz.findMany({ + ...query, + where: { + serviceId: args.serviceId, + centerMentorId: centerMentor.mentorId, + }, + }) } - const centerMentor = await this.prisma.centerMentor.findUnique({ - where: { mentorId: ctx.http.me.id }, - }) - if (!centerMentor) { - throw new Error('Center mentor not found') + + // use case 2: Customer + if (ctx.http.me.role === Role.CUSTOMER) { + // if scheduleId is provided, return quizzes for the schedule + if (args.scheduleId) { + const schedule = await this.prisma.schedule.findUnique({ + where: { id: args.scheduleId }, + }) + if (!schedule) { + throw new Error('Schedule not found') + } + return await this.prisma.quiz.findMany({ + ...query, + where: { + serviceId: args.serviceId, + }, + }) + } + throw new Error('Schedule ID is required') } - return await this.prisma.quiz.findMany({ - ...query, - where: { - serviceId: args.serviceId, - centerMentorId: centerMentor.mentorId, - }, - }) }, }), }))