-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added management command to delete notifications (#34447)
* feat: added management command to delete notifications
- Loading branch information
1 parent
03a490f
commit fe13884
Showing
6 changed files
with
274 additions
and
2 deletions.
There are no files selected for viewing
76 changes: 76 additions & 0 deletions
76
openedx/core/djangoapps/notifications/management/commands/delete_notifications.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
""" | ||
Management command for deleting notifications with parameters | ||
""" | ||
import datetime | ||
import logging | ||
|
||
from django.core.management.base import BaseCommand | ||
|
||
from openedx.core.djangoapps.notifications.base_notification import ( | ||
COURSE_NOTIFICATION_APPS, | ||
COURSE_NOTIFICATION_TYPES | ||
) | ||
from openedx.core.djangoapps.notifications.tasks import delete_notifications | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class Command(BaseCommand): | ||
""" | ||
Invoke with: | ||
python manage.py lms delete_notifications | ||
""" | ||
help = ( | ||
"Delete notifications that meets a criteria. Requires app_name, notification_type and created (duration)" | ||
) | ||
|
||
def add_arguments(self, parser): | ||
""" | ||
Add command line arguments to management command | ||
""" | ||
parser.add_argument('--app_name', choices=list(COURSE_NOTIFICATION_APPS.keys()), required=True) | ||
parser.add_argument('--notification_type', choices=list(COURSE_NOTIFICATION_TYPES.keys()), | ||
required=True) | ||
parser.add_argument('--created', type=argparse_date, required=True, | ||
help="Allowed date formats YYYY-MM-DD. YYYY Year. MM Month. DD Date." | ||
"Duration can be specified with ~. Maximum 15 days duration is allowed") | ||
parser.add_argument('--course_id', required=False) | ||
|
||
def handle(self, *args, **kwargs): | ||
""" | ||
Calls delete notifications task | ||
""" | ||
delete_notifications.delay(kwargs) | ||
logger.info('Deletion task is in progress please check logs to verify') | ||
|
||
|
||
def argparse_date(string: str): | ||
""" | ||
Argparse Type to return datetime dictionary from string | ||
Returns { | ||
'created__gte': datetime, | ||
'created__lte': datetime, | ||
} | ||
""" | ||
ret_dict = {} | ||
if '~' in string: | ||
start_date, end_date = string.split('~') | ||
start_date = parse_date(start_date) | ||
end_date = parse_date(end_date) | ||
if (end_date - start_date).days > 15: | ||
raise ValueError('More than 15 days duration is not allowed') | ||
else: | ||
start_date = parse_date(string) | ||
end_date = start_date | ||
ret_dict['created__gte'] = datetime.datetime.combine(start_date, datetime.time.min) | ||
ret_dict['created__lte'] = datetime.datetime.combine(end_date, datetime.time.max) | ||
return ret_dict | ||
|
||
|
||
def parse_date(string): | ||
""" | ||
Converts string date to datetime object | ||
""" | ||
return datetime.datetime.strptime(string.strip(), "%Y-%m-%d") |
56 changes: 56 additions & 0 deletions
56
openedx/core/djangoapps/notifications/management/tests/test_delete_notifications.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
""" | ||
Tests delete_notifications management command | ||
""" | ||
import ddt | ||
|
||
from unittest import mock | ||
|
||
from django.core.management import call_command | ||
|
||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase | ||
|
||
|
||
@ddt.ddt | ||
class TestDeleteNotifications(ModuleStoreTestCase): | ||
""" | ||
Tests delete notifications management command | ||
""" | ||
|
||
@ddt.data('app_name', 'notification_type', 'created') | ||
def test_management_command_fails_if_required_param_is_missing(self, param): | ||
""" | ||
Tests if all required params are available when running management command | ||
""" | ||
default_dict = { | ||
'app_name': 'discussion', | ||
'notification_type': 'new_comment', | ||
'created': '2024-02-01' | ||
} | ||
default_dict.pop(param) | ||
try: | ||
call_command('delete_notifications', **default_dict) | ||
assert False | ||
except Exception: # pylint: disable=broad-except | ||
pass | ||
|
||
@ddt.data('course_id', None) | ||
@mock.patch( | ||
'openedx.core.djangoapps.notifications.tasks.delete_notifications.delay' | ||
) | ||
def test_management_command_runs_for_valid_params(self, key_to_remove, mock_func): | ||
""" | ||
Tests management command runs with valid params optional | ||
""" | ||
default_dict = { | ||
'app_name': 'discussion', | ||
'notification_type': 'new_comment', | ||
'created': '2024-02-01', | ||
'course_id': 'test-course' | ||
} | ||
if key_to_remove is not None: | ||
default_dict.pop(key_to_remove) | ||
call_command('delete_notifications', **default_dict) | ||
assert mock_func.called | ||
args = mock_func.call_args[0][0] | ||
for key, value in default_dict.items(): | ||
assert args[key] == value |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
""" | ||
Utils for tests | ||
""" | ||
from openedx.core.djangoapps.notifications.models import Notification | ||
|
||
|
||
def create_notification(user, course_key, **kwargs): | ||
""" | ||
Create a notification | ||
""" | ||
params = { | ||
'user': user, | ||
'course_id': course_key, | ||
'app_name': 'discussion', | ||
'notification_type': 'new_comment', | ||
'content_url': '', | ||
'content_context': { | ||
"replier_name": "replier", | ||
"username": "username", | ||
"author_name": "author_name", | ||
"post_title": "post_title", | ||
"course_update_content": "Course update content", | ||
"content_type": 'post', | ||
"content": "post_title" | ||
} | ||
} | ||
params.update(kwargs) | ||
notification = Notification.objects.create(**params) | ||
return notification |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters