diff --git a/lms/djangoapps/courseware/model_data.py b/lms/djangoapps/courseware/model_data.py index 681763e88f73cec23fc32406e61fe337c4a5ff4a..2a208c34f86748d171795539f411d6a05a01cf12 100644 --- a/lms/djangoapps/courseware/model_data.py +++ b/lms/djangoapps/courseware/model_data.py @@ -27,7 +27,7 @@ from abc import ABCMeta, abstractmethod from collections import defaultdict, namedtuple from contracts import contract, new_contract -from django.db import DatabaseError +from django.db import DatabaseError, IntegrityError, transaction from opaque_keys.edx.asides import AsideUsageKeyV1, AsideUsageKeyV2 from opaque_keys.edx.block_types import BlockTypeKeyV1 from opaque_keys.edx.keys import CourseKey @@ -994,15 +994,27 @@ def set_score(user_id, usage_key, score, max_score): """ Set the score and max_score for the specified user and xblock usage. """ - student_module, created = StudentModule.objects.get_or_create( - student_id=user_id, - module_state_key=usage_key, - course_id=usage_key.course_key, - defaults={ - 'grade': score, - 'max_grade': max_score, - } - ) + created = False + kwargs = {"student_id": user_id, "module_state_key": usage_key, "course_id": usage_key.course_key} + try: + with transaction.atomic(): + student_module, created = StudentModule.objects.get_or_create( + defaults={ + 'grade': score, + 'max_grade': max_score, + }, + **kwargs + ) + except IntegrityError: + # log information for duplicate entry and get the record as above command failed. + student_module = StudentModule.objects.get(**kwargs) + log.warning( + 'set_score: IntegrityError for student %d - course_id %s - usage_key %s having ' + 'score %d and max_score %d same as request score %d and max_score %d', + user_id, usage_key.course_key, usage_key, student_module.grade, student_module.max_grade, + score, max_score + ) + if not created: student_module.grade = score student_module.max_grade = max_score