Skip to content

Commit

Permalink
fix: Fixed course date handling
Browse files Browse the repository at this point in the history
  • Loading branch information
rijuma committed Feb 19, 2025
1 parent 0345aa5 commit c44e293
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 26 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ In your ``lms/envs/private.py`` settings file in edx-platform (create file if ne
LEARNING_ASSISTANT_AVAILABLE = True
In devstack, run ``make lms-shell`` and run the following command: ``paver install_prereqs;exit``. This will install anything included in your ``private.txt`` requirements file.
In devstack, run ``make lms-shell`` and run the following command: ``make requirements;exit``. This will install anything included in your ``private.txt`` requirements file.

In django admin, add the following waffle flag ``learning_assistant.enable_course_content`` and make sure it is turned on for Everyone. The flag should be checked on for: Superusers, Staff, and Authenticated.

Expand Down
2 changes: 2 additions & 0 deletions learning_assistant/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@
}

AUDIT_TRIAL_MAX_DAYS = 14

LMS_DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%SZ'
20 changes: 20 additions & 0 deletions learning_assistant/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
import json
import logging

from datetime import datetime
import requests
from django.conf import settings
from optimizely import optimizely
from requests.exceptions import ConnectTimeout
from rest_framework import status as http_status

from learning_assistant.constants import LMS_DATETIME_FORMAT
from learning_assistant.toggles import v2_endpoint_enabled

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -185,3 +187,21 @@ def get_audit_trial_length_days(user_id, enrollment_mode):
trial_length_days = 0

return trial_length_days


def parse_lms_datetime(datetime_string):
"""
Parse an LMS datetime into a timezone-aware, Python datetime object.
Arguments:
datetime_string: A string to be parsed.
"""
if datetime_string is None:
return None

try:
parsed_datetime = datetime.strptime(datetime_string, LMS_DATETIME_FORMAT)
except ValueError:
return None

return parsed_datetime
24 changes: 15 additions & 9 deletions learning_assistant/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@
from learning_assistant.platform_imports import get_cache_course_run_data
from learning_assistant.serializers import MessageSerializer
from learning_assistant.toggles import chat_history_enabled
from learning_assistant.utils import get_audit_trial_length_days, get_chat_response, user_role_is_staff
from learning_assistant.utils import (
get_audit_trial_length_days,
get_chat_response,
parse_lms_datetime,
user_role_is_staff,
)

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -135,12 +140,13 @@ def post(self, request, course_run_id):

course_data = get_cache_course_run_data(course_run_id, ['start', 'end'])
today = datetime.now()
start = course_data.get('start', None)
end = course_data.get('end', None)

course_start = parse_lms_datetime(course_data.get('start', None))
course_end = parse_lms_datetime(course_data.get('end', None))

valid_dates = (
(start <= today if start else True)
and (end >= today if end else True)
(course_start <= today if course_start else True)
and (course_end >= today if course_end else True)
)

if (
Expand Down Expand Up @@ -259,11 +265,11 @@ def get(self, request, course_run_id):

course_data = get_cache_course_run_data(course_run_id, ['start', 'end'])
today = datetime.now()
start = course_data.get('start', None)
end = course_data.get('end', None)
course_start = parse_lms_datetime(course_data.get('start', None))
course_end = parse_lms_datetime(course_data.get('end', None))
valid_dates = (
(start <= today if start else True)
and (end >= today if end else True)
(course_start <= today if course_start else True)
and (course_end >= today if course_end else True)
)

# Get whether the Learning Assistant is enabled.
Expand Down
24 changes: 24 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@
import json
from unittest.mock import MagicMock, patch

from datetime import datetime
import ddt
import responses
from django.conf import settings
from django.test import TestCase, override_settings
from requests.exceptions import ConnectTimeout

from learning_assistant.constants import LMS_DATETIME_FORMAT
from learning_assistant.utils import (
get_audit_trial_length_days,
get_chat_response,
get_optimizely_variation,
get_reduced_message_list,
parse_lms_datetime,
user_role_is_staff,
)

Expand Down Expand Up @@ -229,3 +232,24 @@ def test_return_variation(self, mock_optimizely):
with patch.object(settings, 'OPTIMIZELY_FULLSTACK_SDK_KEY', 'sdk_key'):
expected_value = {'enabled': True, 'variation_key': 'variation'}
self.assertEqual(get_optimizely_variation(1, 'verified'), expected_value)


class ParseLMSDatetimeTests(TestCase):
"""
Tests for the parse_lms_datetime helper function.
"""

def test_correct_date(self):
expected_value = datetime(1982, 12, 7, 14, 00, 00)
stringified = expected_value.strftime(LMS_DATETIME_FORMAT)

response = parse_lms_datetime(stringified)

self.assertEqual(response, expected_value)

def test_wrong_date(self):
expected_value = None

response = parse_lms_datetime('when I get my homework done')

self.assertEqual(response, expected_value)
32 changes: 16 additions & 16 deletions tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,24 +147,24 @@ def test_invalid_messages(self, mock_mode, mock_enrollment, mock_get_user_role,
self.assertEqual(response.status_code, 400)

@ddt.data({
'start': datetime(2023, 1, 1), # past date
'end': datetime(2023, 1, 30), # past date
'start': '2023-01-01T01:00:00Z', # past date
'end': '2023-01-30T01:00:00Z', # past date
'expects_fail': True,
}, {
'start': datetime(2026, 1, 1), # future date
'end': datetime(2026, 1, 30), # future date
'start': '2026-01-01T01:00:00Z', # future date
'end': '2026-01-30T01:00:00Z', # future date
'expects_fail': True,
}, {
'start': datetime(2024, 6, 1), # past date
'end': datetime(2024, 6, 30), # future date
'start': '2024-06-01T01:00:00Z', # past date
'end': '2024-06-01T30:00:00Z', # future date
'expects_fail': False,
}, {
'start': datetime(2024, 6, 1), # past date
'start': '2024-06-01T01:00:00Z', # past date
'end': None,
'expects_fail': False,
}, {
'start': None,
'end': datetime(2024, 6, 30), # future date
'end': '2024-06-01T30:00:00Z', # future date
'expects_fail': False,
})
@patch('learning_assistant.views.get_cache_course_run_data')
Expand Down Expand Up @@ -748,24 +748,24 @@ def test_chat_summary_with_trial_access_student(
self.assertEqual(response.data['audit_trial_length_days'], audit_trial_length_days_mock_value)

@ddt.data({
'start': datetime(2023, 1, 1), # past date
'end': datetime(2023, 1, 30), # past date
'start': '2023-01-01T01:00:00Z', # past date
'end': '2023-01-30T01:00:00Z', # past date
'expects_fail': True,
}, {
'start': datetime(2026, 1, 1), # future date
'end': datetime(2026, 1, 30), # future date
'start': '2026-01-01T01:00:00Z', # future date
'end': '2026-01-30T01:00:00Z', # future date
'expects_fail': True,
}, {
'start': datetime(2024, 6, 1), # past date
'end': datetime(2024, 6, 30), # future date
'start': '2024-06-01T01:00:00Z', # past date
'end': '2024-06-01T30:00:00Z', # future date
'expects_fail': False,
}, {
'start': datetime(2024, 6, 1), # past date
'start': '2024-06-01T01:00:00Z', # past date
'end': None,
'expects_fail': False,
}, {
'start': None,
'end': datetime(2024, 6, 30), # future date
'end': '2024-06-01T30:00:00Z', # future date
'expects_fail': False,
})
@patch('learning_assistant.views.get_cache_course_run_data')
Expand Down

0 comments on commit c44e293

Please sign in to comment.