aircox-radiocampus/aircox/management/commands/diffusions_monitor.py
2016-10-10 15:04:15 +02:00

185 lines
6.4 KiB
Python

"""
Manage diffusions using schedules, to update, clean up or check diffusions.
A generated diffusion can be unconfirmed, that means that the user must confirm
it by changing its type to "normal". The behaviour is controlled using
--approval.
Different actions are available:
- "update" is the process that is used to generated them using programs
schedules for the (given) month.
- "clean" will remove all diffusions that are still unconfirmed and have been
planified before the (given) month.
- "check" will remove all diffusions that are unconfirmed and have been planified
from the (given) month and later.
"""
import logging
from argparse import RawTextHelpFormatter
from django.core.management.base import BaseCommand, CommandError
from django.utils import timezone as tz
from aircox.models import *
logger = logging.getLogger('aircox.tools')
class Actions:
@staticmethod
def __check_conflicts (item, saved_items):
"""
Check for conflicts, and update conflictual
items if they have been generated during this
update.
It set an attribute 'do_not_save' if the item should not
be saved. FIXME: find proper way
Return the number of conflicts
"""
conflicts = list(item.get_conflicts())
for i, conflict in enumerate(conflicts):
if conflict.program == item.program:
item.do_not_save = True
del conflicts[i]
continue
if conflict.pk in saved_items and \
conflict.type != Diffusion.Type.unconfirmed:
conflict.type = Diffusion.Type.unconfirmed
conflict.save()
if not conflicts:
item.type = Diffusion.Type.normal
return 0
item.type = Diffusion.Type.unconfirmed
return len(conflicts)
@classmethod
def update (cl, date, mode):
manual = (mode == 'manual')
if not manual:
saved_items = set()
count = [0, 0]
for schedule in Schedule.objects.filter(program__active = True) \
.order_by('initial'):
# in order to allow rerun links between diffusions, we save items
# by schedule;
items = schedule.diffusions_of_month(date, exclude_saved = True)
count[0] += len(items)
if manual:
Diffusion.objects.bulk_create(items)
else:
for item in items:
count[1] += cl.__check_conflicts(item, saved_items)
if hasattr(item, 'do_not_save'):
count[0] -= 1
continue
item.save()
saved_items.add(item)
logger.info('[update] schedule %s: %d new diffusions',
str(schedule), len(items),
)
logger.info('[update] %d diffusions have been created, %s', count[0],
'do not forget manual approval' if manual else
'{} conflicts found'.format(count[1]))
@staticmethod
def clean (date):
qs = Diffusion.objects.filter(type = Diffusion.Type.unconfirmed,
start__lt = date)
logger.info('[clean] %d diffusions will be removed', qs.count())
qs.delete()
@staticmethod
def check (date):
qs = Diffusion.objects.filter(type = Diffusion.Type.unconfirmed,
start__gt = date)
items = []
for diffusion in qs:
schedules = Schedule.objects.filter(program = diffusion.program)
for schedule in schedules:
if schedule.match(diffusion.start):
break
else:
items.append(diffusion.id)
logger.info('[check] %d diffusions will be removed', len(items))
if len(items):
Diffusion.objects.filter(id__in = items).delete()
class Command (BaseCommand):
help= __doc__
def add_arguments (self, parser):
parser.formatter_class=RawTextHelpFormatter
now = tz.datetime.today()
group = parser.add_argument_group('action')
group.add_argument(
'--update', action='store_true',
help='generate (unconfirmed) diffusions for the given month. '
'These diffusions must be confirmed manually by changing '
'their type to "normal"')
group.add_argument(
'--clean', action='store_true',
help='remove unconfirmed diffusions older than the given month')
group.add_argument(
'--check', action='store_true',
help='check future unconfirmed diffusions from the given date '
'agains\'t schedules and remove it if that do not match any '
'schedule')
group = parser.add_argument_group('date')
group.add_argument(
'--year', type=int, default=now.year,
help='used by update, default is today\'s year')
group.add_argument(
'--month', type=int, default=now.month,
help='used by update, default is today\'s month')
group.add_argument(
'--next-month', action='store_true',
help='set the date to the next month of given date'
' (if next month from today'
)
group = parser.add_argument_group('options')
group.add_argument(
'--mode', type=str, choices=['manual', 'auto'],
default='auto',
help='manual means that all generated diffusions are unconfirmed, '
'thus must be approved manually; auto confirmes all '
'diffusions except those that conflicts with others'
)
def handle (self, *args, **options):
date = tz.datetime(year = options.get('year'),
month = options.get('month'),
day = 1)
date = tz.make_aware(date)
if options.get('next_month'):
month = options.get('month')
date += tz.timedelta(days = 28)
if date.month == month:
date += tz.timedelta(days = 28)
date = date.replace(day = 1)
if options.get('update'):
Actions.update(date, mode = options.get('mode'))
if options.get('clean'):
Actions.clean(date)
if options.get('check'):
Actions.check(date)