Skip to content

Commit

Permalink
Merge pull request #2201 from openedx/ahtisham/INF-1304
Browse files Browse the repository at this point in the history
  • Loading branch information
AhtishamShahid authored Apr 22, 2024
2 parents 43ae22a + c8fc9c2 commit b42e68d
Show file tree
Hide file tree
Showing 12 changed files with 137 additions and 34 deletions.
2 changes: 1 addition & 1 deletion openassessment/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
Initialization Information for Open Assessment Module
"""

__version__ = '6.6.2'
__version__ = '6.7.0'
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
create_submission_dict,
)


logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -129,6 +128,7 @@ def self_assess(
config_data.publish_assessment_event("openassessmentblock.self_assess", assessment)
# After we've created the self-assessment, we need to update the workflow.
workflow_data.update_workflow_status()

except (
SelfAssessmentRequestError,
AssessmentWorkflowRequestError,
Expand Down
42 changes: 29 additions & 13 deletions openassessment/xblock/apis/submissions/submissions_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import json
import logging
import os

from opaque_keys.edx.keys import CourseKey
from submissions.api import Submission, SubmissionError, SubmissionRequestError

from openassessment.fileupload.exceptions import FileUploadError
Expand All @@ -22,12 +24,14 @@
SubmitInternalError,
UnsupportedFileTypeException
)
from openassessment.xblock.utils.notifications import send_staff_notification

from openassessment.xblock.utils.validation import validate_submission
from openassessment.xblock.utils.data_conversion import (
format_files_for_submission,
prepare_submission_for_serialization,
)

logger = logging.getLogger(__name__) # pylint: disable=invalid-name


Expand Down Expand Up @@ -115,9 +119,9 @@ def submit(text_responses, block_config_data, block_submission_data, block_workf
logger.exception(msg)
raise
except (
SubmissionError,
AssessmentWorkflowError,
NoTeamToCreateSubmissionForError,
SubmissionError,
AssessmentWorkflowError,
NoTeamToCreateSubmissionForError,
) as e:
msg = (
"An unknown error occurred while submitting "
Expand All @@ -130,11 +134,11 @@ def submit(text_responses, block_config_data, block_submission_data, block_workf


def create_submission(
student_item_dict,
submission_data,
block_config_data,
block_submission_data,
block_workflow_data
student_item_dict,
submission_data,
block_config_data,
block_submission_data,
block_workflow_data
):
"""Creates submission for the submitted assessment response or a list for a team assessment."""
# Import is placed here to avoid model import at project startup.
Expand All @@ -157,6 +161,18 @@ def create_submission(

# Set student submission_uuid
block_config_data._block.submission_uuid = submission["uuid"] # pylint: disable=protected-access
has_staff_step = block_workflow_data.workflow_requirements.get('staff', {}).get('required', False)

if has_staff_step:
if block_config_data.course:
course_id = block_config_data.course.id
else:
course_id = CourseKey.from_string(student_item_dict.get("course_id"))
send_staff_notification(
course_id,
student_item_dict.get("item_id"),
block_config_data._block.display_name # pylint: disable=protected-access
)

# Emit analytics event...
block_config_data.publish_event(
Expand All @@ -174,11 +190,11 @@ def create_submission(


def create_team_submission(
student_item_dict,
submission_data,
block_config_data,
block_submission_data,
block_workflow_data
student_item_dict,
submission_data,
block_config_data,
block_submission_data,
block_workflow_data
):
"""A student submitting for a team should generate matching submissions for every member of the team."""

Expand Down
5 changes: 4 additions & 1 deletion openassessment/xblock/test/test_grade_explanation.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ def test_render_grade_explanation_self_only(self, xblock, assessment_score_prior
self.assertIn(self.second_sentences_options["self"], resp.decode('utf-8'))

@scenario('data/grade_scenario_staff_only.xml', user_id='Bernard')
@patch('openassessment.xblock.apis.submissions.submissions_actions.send_staff_notification')
@data(*assessment_score_priority)
def test_render_explanation_grade_staff_only(self, xblock, assessment_score_priority):
def test_render_explanation_grade_staff_only(self, xblock, assessment_score_priority, mock_send_staff_notification):
with patch(
'openassessment.workflow.models.AssessmentWorkflow.ASSESSMENT_SCORE_PRIORITY',
assessment_score_priority
Expand All @@ -64,6 +65,8 @@ def test_render_explanation_grade_staff_only(self, xblock, assessment_score_prio

self.assertIn(self.second_sentences_options["staff"], resp.decode('utf-8'))

mock_send_staff_notification.assert_called_once()

@scenario('data/grade_scenario_peer_only.xml', user_id='Bernard')
@data(*assessment_score_priority)
def test_render_grade_explanation_peer_only(self, xblock, assessment_score_priority):
Expand Down
60 changes: 60 additions & 0 deletions openassessment/xblock/test/test_notifications.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""
Unit test for notification util
"""
import unittest
from unittest.mock import patch

from openassessment.xblock.utils.notifications import send_staff_notification


class TestSendStaffNotification(unittest.TestCase):
"""
Test for send_staff_notification function
"""
@patch('openassessment.xblock.utils.notifications.COURSE_NOTIFICATION_REQUESTED.send_event')
def test_send_staff_notification(self, mock_send_event):
"""
Test send_staff_notification function
"""
# Mocked data
course_id = 'course_id'
problem_id = 'problem_id'
ora_name = 'ora_name'

# Call the function
send_staff_notification(course_id, problem_id, ora_name)

# Assertions
mock_send_event.assert_called_once()
args, kwargs = mock_send_event.call_args
notification_data = kwargs['course_notification_data']

# Check if CourseNotificationData is properly initialized
self.assertEqual(notification_data.course_key, course_id)
self.assertEqual(notification_data.content_context['ora_name'], ora_name)
self.assertEqual(notification_data.notification_type, 'ora_staff_notification')
self.assertEqual(notification_data.content_url, f"/{problem_id}")
self.assertEqual(notification_data.app_name, "ora")
self.assertEqual(notification_data.audience_filters['course_roles'], ['staff', 'instructor'])

@patch('openassessment.xblock.utils.notifications.logger.error')
@patch('openassessment.xblock.utils.notifications.COURSE_NOTIFICATION_REQUESTED.send_event')
def test_send_staff_notification_error_logging(self, mock_send_event, mock_logger_error):
"""
Test send_staff_notification function when an exception is raised
"""
# Mocked data
course_id = 'course_id'
problem_id = 'problem_id'
ora_name = 'ora_name'

# Mock exception
mock_exception = Exception('Test exception')

mock_send_event.side_effect = mock_exception

# Call the function
send_staff_notification(course_id, problem_id, ora_name)

# Assertions
mock_logger_error.assert_called_once_with(f"Error while sending ora staff notification: {mock_exception}")
33 changes: 33 additions & 0 deletions openassessment/xblock/utils/notifications.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""
This module contains utility functions for sending notifications.
"""
import logging

from django.conf import settings
from openedx_events.learning.signals import COURSE_NOTIFICATION_REQUESTED
from openedx_events.learning.data import CourseNotificationData

logger = logging.getLogger(__name__)


def send_staff_notification(course_id, problem_id, ora_name):
"""
Send a staff notification for a course
"""
try:
audience_filters = {
'course_roles': ['staff', 'instructor']
}
notification_data = CourseNotificationData(
course_key=course_id,
content_context={
'ora_name': ora_name
},
notification_type='ora_staff_notification',
content_url=f"{getattr(settings, 'ORA_GRADING_MICROFRONTEND_URL', '')}/{problem_id}",
app_name="ora",
audience_filters=audience_filters,
)
COURSE_NOTIFICATION_REQUESTED.send_event(course_notification_data=notification_data)
except Exception as e:
logger.error(f"Error while sending ora staff notification: {e}")
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "edx-ora2",
"version": "6.6.2",
"version": "6.7.0",
"repository": "https://github.com/openedx/edx-ora2.git",
"dependencies": {
"@edx/frontend-build": "8.0.6",
Expand Down
1 change: 1 addition & 0 deletions requirements/base.in
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jsonfield
lazy
loremipsum
lxml
openedx-events
path.py
python-dateutil
pytz
Expand Down
10 changes: 4 additions & 6 deletions requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#
# This file is autogenerated by pip-compile with Python 3.8
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# make upgrade
# pip-compile requirements/base.in
#
appdirs==1.4.4
# via fs
Expand Down Expand Up @@ -197,10 +197,8 @@ stevedore==5.2.0
# edx-opaque-keys
text-unidecode==1.3
# via python-slugify
typing-extensions==4.11.0
# via
# asgiref
# edx-opaque-keys
typing-extensions==4.10.0
# via edx-opaque-keys
urllib3==1.26.18
# via
# botocore
Expand Down
1 change: 1 addition & 0 deletions requirements/common_constraints.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@


# A central location for most common version constraints
# (across edx repos) for pip-installation.
#
Expand Down
11 changes: 1 addition & 10 deletions requirements/pip-tools.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# This file is autogenerated by pip-compile with Python 3.8
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# make upgrade
Expand All @@ -8,8 +8,6 @@ build==1.2.1
# via pip-tools
click==8.1.7
# via pip-tools
importlib-metadata==7.1.0
# via build
packaging==24.0
# via build
pip-tools==7.4.1
Expand All @@ -18,15 +16,8 @@ pyproject-hooks==1.0.0
# via
# build
# pip-tools
tomli==2.0.1
# via
# build
# pip-tools
# pyproject-hooks
wheel==0.43.0
# via pip-tools
zipp==3.18.1
# via importlib-metadata

# The following packages are considered to be unsafe in a requirements file:
# pip
Expand Down
2 changes: 1 addition & 1 deletion requirements/pip.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# This file is autogenerated by pip-compile with Python 3.8
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# make upgrade
Expand Down

0 comments on commit b42e68d

Please sign in to comment.