From 974f67aefee327c2a3c29219a3f9d4c5b04554c9 Mon Sep 17 00:00:00 2001 From: Fahid Latheef Alungal Date: Sun, 16 Feb 2025 19:29:03 +0530 Subject: [PATCH] fix: validate if submission exceeds the allowed limit in backend --- frontend/src/components/Quiz.vue | 12 ++++++++++- .../lms_quiz_submission.py | 21 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Quiz.vue b/frontend/src/components/Quiz.vue index c0de8ff5..165e666f 100644 --- a/frontend/src/components/Quiz.vue +++ b/frontend/src/components/Quiz.vue @@ -290,7 +290,7 @@ import { FormControl, } from 'frappe-ui' import { ref, watch, reactive, inject, computed } from 'vue' -import { createToast } from '@/utils/' +import { createToast, showToast } from '@/utils/' import { CheckCircle, XCircle, MinusCircle } from 'lucide-vue-next' import { timeAgo } from '@/utils' import { useRouter } from 'vue-router' @@ -582,6 +582,16 @@ const createSubmission = () => { if (quiz.data && quiz.data.max_attempts) attempts.reload() if (quiz.data.duration) clearInterval(timerInterval) }, + onError(err) { + const errorTitle = err?.message || '' + if (errorTitle.includes('MaximumAttemptsExceededError')) { + const errorMessage = err.messages?.[0] || err + showToast(__('Error'), __(errorMessage), 'x') + setTimeout(() => { + window.location.reload() + }, 3000) + } + }, } ) } diff --git a/lms/lms/doctype/lms_quiz_submission/lms_quiz_submission.py b/lms/lms/doctype/lms_quiz_submission/lms_quiz_submission.py index 0618eb2b..b643ea54 100644 --- a/lms/lms/doctype/lms_quiz_submission/lms_quiz_submission.py +++ b/lms/lms/doctype/lms_quiz_submission/lms_quiz_submission.py @@ -10,12 +10,29 @@ from frappe.desk.doctype.notification_log.notification_log import make_notificat class LMSQuizSubmission(Document): def validate(self): + self.validate_if_max_attempts_exceeded() self.validate_marks() self.set_percentage() def on_update(self): self.notify_member() + def validate_if_max_attempts_exceeded(self): + max_attempts = frappe.db.get_value("LMS Quiz", self.quiz, ["max_attempts"]) + if max_attempts == 0: + return + + current_user_submission_count = frappe.db.count( + self.doctype, filters={"quiz": self.quiz, "member": frappe.session.user} + ) + if current_user_submission_count >= max_attempts: + frappe.throw( + _("You have exceeded the maximum number of attempts ({0}) for this quiz").format( + max_attempts + ), + MaximumAttemptsExceededError, + ) + def validate_marks(self): self.score = 0 for row in self.result: @@ -52,3 +69,7 @@ class LMSQuizSubmission(Document): ) make_notification_logs(notification, [self.member]) + + +class MaximumAttemptsExceededError(frappe.DuplicateEntryError): + pass