<commit_before>"""
Management command to check users progress and sends notifications
./manage.py lms send_progress_leaderboard_notifications  --settings=production --time-range=30
"""

import logging
import sys

from completion_aggregator.models import Aggregator
from django.conf import settings
from django.core.management.base import BaseCommand
from django.utils import timezone
from edx_notifications.data import NotificationMessage
from edx_notifications.lib.publisher import (
    publish_notification_to_user,
    get_notification_type
)

from ...models import LeaderBoard
from edx_solutions_api_integration.models import APIUser as User


log = logging.getLogger(__name__)


class Command(BaseCommand):
    """
    Command to check users progress and sends notifications
    """
    help = "Time range in minute for which we need to check progress updates in past",

    def add_arguments(self, parser):
        parser.add_argument(
            "--time-range",
            dest="time_range",
            type=int,
            default=60,
            help="Time range in minute for which we need to check progress updates in past",
        )

    def handle(self, *args, **options):
        if not settings.FEATURES['ENABLE_NOTIFICATIONS']:
            return

        # Increase time range so that users don't miss notification in case cron job is skipped or delayed.
        time_range = timezone.now() - timezone.timedelta(minutes=options['time_range'] * 2)
        leaderboard_size = getattr(settings, 'LEADERBOARD_SIZE', 3)
        courses = Aggregator.objects.filter(
            aggregation_name='course',
            last_modified__gte=time_range
        ).distinct().values_list('course_key', flat=True)
        for course_key in courses:
            all_progress = Aggregator.objects.filter(
                aggregation_name='course', course_key=course_key, percent__gt=0
            ).exclude(user__in=User.objects.filter(courseaccessrole__course_id=course_key,
                      courseaccessrole__role__in=['staff', 'observer', 'assistant'])
            ).order_by('-percent', 'last_modified')[:leaderboard_size]

            all_leaders = LeaderBoard.objects.filter(course_key=course_key).all()
            leaders = {l.position: l for l in all_leaders}
            positions = {l.user_id: l.position for l in all_leaders}
            for idx, progress in enumerate(all_progress):
                position = idx + 1
                leader = leaders.get(position)
                if not leader:
                    leader = LeaderBoard(course_key=course_key, position=position)

                old_leader = leader.user_id
                old_position = positions.get(progress.user_id, sys.maxint)
                leader.user_id = progress.user_id
                leader.save()
                is_new = progress.modified >= time_range<commit_msg>MCKIN-20811 Notification - TA/staff are receiving notifications<commit_after>"""
Management command to check users progress and sends notifications
./manage.py lms send_progress_leaderboard_notifications  --settings=production --time-range=30
"""

import logging
import sys

from completion_aggregator.models import Aggregator
from django.conf import settings
from django.core.management.base import BaseCommand
from django.utils import timezone
from edx_notifications.data import NotificationMessage
from edx_notifications.lib.publisher import (
    publish_notification_to_user,
    get_notification_type
)

from ...models import LeaderBoard
from edx_solutions_api_integration.models import APIUser as User


log = logging.getLogger(__name__)


class Command(BaseCommand):
    """
    Command to check users progress and sends notifications
    """
    help = "Time range in minute for which we need to check progress updates in past",

    def add_arguments(self, parser):
        parser.add_argument(
            "--time-range",
            dest="time_range",
            type=int,
            default=60,
            help="Time range in minute for which we need to check progress updates in past",
        )

    def handle(self, *args, **options):
        if not settings.FEATURES['ENABLE_NOTIFICATIONS']:
            return

        # Increase time range so that users don't miss notification in case cron job is skipped or delayed.
        time_range = timezone.now() - timezone.timedelta(minutes=options['time_range'] * 2)
        leaderboard_size = getattr(settings, 'LEADERBOARD_SIZE', 3)
        courses = Aggregator.objects.filter(
            aggregation_name='course',
            last_modified__gte=time_range
        ).distinct().values_list('course_key', flat=True)
        for course_key in courses:
            all_progress = Aggregator.objects.filter(
                aggregation_name='course', course_key=course_key, percent__gt=0
            ).exclude(user__in=User.objects.filter(courseaccessrole__course_id=course_key,
                      courseaccessrole__role__in=['staff', 'observer', 'assistant', 'instructor'])
            ).order_by('-percent', 'last_modified')[:leaderboard_size]

            all_leaders = LeaderBoard.objects.filter(course_key=course_key).all()
            leaders = {l.position: l for l in all_leaders}
            positions = {l.user_id: l.position for l in all_leaders}
            for idx, progress in enumerate(all_progress):
                position = idx + 1
                leader = leaders.get(position)
                if not leader:
                    leader = LeaderBoard(course_key=course_key, position=position)

                old_leader = leader.user_id
                old_position = positions.get(progress.user_id, sys.maxint)
                leader.user_id = progress.user_id
                leader.save()
                is_new = progress.modified >= time_range
{'fraction_non_alphanumeric': 0.0826730967964175, 'fraction_numerical': 0.0036169479848432657, 'mean_word_length': 2.763447828904731, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '987808', 'n_tokens_mistral': 1590, 'n_tokens_neox': 1511, 'n_words': 405}