from __future__ import annotations from datetime import datetime from ckeditor_uploader.fields import RichTextUploadingField from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from django.utils.translation import gettext_lazy as _ from django_celery_beat.models import CrontabSchedule from simple_history.models import HistoricalRecords from taskbar.models import Location, Workplace class Weekday(models.Model): name = models.CharField(max_length=15, verbose_name=_('name')) number = models.PositiveSmallIntegerField(verbose_name=_('Weekday number')) class Meta: verbose_name = _('Weekday') verbose_name_plural = _('Weekdays') ordering = ['id'] unique_together = ( 'name', 'number', ) def __str__(self) -> str: return f'{self.name}' class CronSchedule(models.Model): name = models.CharField( max_length=80, unique=True, verbose_name=_('name'), ) crontab = models.ForeignKey( CrontabSchedule, on_delete=models.CASCADE, verbose_name=_('Crontab Schedule'), ) crontab.help_text = _('crontab helptext') history = HistoricalRecords(cascade_delete_history=True) class Meta: verbose_name = _('crontab schedule') verbose_name_plural = _('crontab schedules') ordering = ['id'] def __str__(self) -> str: return f'{self.name}' class Shift(models.Model): name = models.CharField(max_length=40) location = models.ForeignKey(Location, on_delete=models.CASCADE, null=False) start_time = models.TimeField(null=True, blank=False) end_time = models.TimeField(null=True, blank=False) weekdays = models.ManyToManyField(Weekday) is_active = models.BooleanField(default=True, ) history = HistoricalRecords(cascade_delete_history=True) class Meta: verbose_name = _('Shift') verbose_name_plural = _('Shifts') ordering = ['-id'] unique_together = ( 'name', 'location', ) def __str__(self) -> str: return f'{self.location_id}: {self.name} ({self.start_time}-{self.end_time})' # type: ignore class OrganizationalUnit(models.Model): name = models.CharField(max_length=40, verbose_name=_('name')) description = models.CharField( max_length=200, default='', blank=True, verbose_name=_('OrganizationalUnit description')) location = models.ForeignKey(Location, on_delete=models.CASCADE, null=False, verbose_name=_('OrganizationalUnit location')) workplaces = models.ManyToManyField( Workplace, blank=True, verbose_name=_('OrganizationalUnit workplaces')) parent = models.ForeignKey('self', blank=True, null=True, on_delete=models.SET_NULL, verbose_name=_('OrganizationalUnit parent')) history = HistoricalRecords(cascade_delete_history=True) class Meta: verbose_name = _('Organizational Unit') verbose_name_plural = _('Organizational Units') ordering = ['-id'] unique_together = ( 'name', 'location', ) def __str__(self) -> str: return f'{self.location_id}: {self.name}' # type: ignore class Notification(models.Model): name = models.CharField(max_length=40, verbose_name=_('name')) description = models.CharField(max_length=200, default='', blank=True, verbose_name=_('Notification description')) location = models.ForeignKey(Location, on_delete=models.CASCADE, null=False, verbose_name=_('Notification location')) recipients = models.ManyToManyField( OrganizationalUnit, related_name='recipients_notification', verbose_name=_('Notification recipients'), blank=True) recipients.help_text = _('Notification recipients help text') is_active = models.BooleanField(default=True, verbose_name=_('Notification is active')) need_confirmation = models.BooleanField( default=False, verbose_name=_('Notification need confirmation')) is_overlay = models.BooleanField( default=False, verbose_name=_('Notification is overlay'), ) is_overlay.help_text = _('Notification overlay help text') interval = models.IntegerField( blank=True, null=True, validators=[MaxValueValidator(500), MinValueValidator(10)], verbose_name=_('Notification interval'), ) interval.help_text = _('Notification interval help text') cron_schedules = models.ManyToManyField( CronSchedule, related_name='cron_schedules', verbose_name=_('Crontab Schedule'), blank=True, ) cron_schedules.help_text = _('Schedule in cron format') shifts = models.ManyToManyField( Shift, blank=True, verbose_name=_('Notification shifts'), ) shifts.help_text = _('Notification shifts help text') show_on_shift_start = models.IntegerField( blank=True, null=True, validators=[MaxValueValidator(30), MinValueValidator(0)], verbose_name=_('Notification show on shift start'), ) show_on_shift_start.help_text = _( 'Notification show on shift start help text') show_on_shift_end = models.IntegerField( blank=True, null=True, validators=[MaxValueValidator(30), MinValueValidator(0)], verbose_name=_('Notification show on shift end'), ) show_on_shift_end.help_text = _('Notification show on shift end help text') close_delay = models.IntegerField( default=45, validators=[MaxValueValidator(180), MinValueValidator(1)], verbose_name=_('Notification close delay'), ) close_delay.help_text = _('Notification close delay help text') start_datetime = models.DateTimeField( null=True, default=datetime.now, verbose_name=_('Notification start datetime'), ) expires_datetime = models.DateTimeField( null=True, blank=True, verbose_name=_('Notification expires datetime'), ) one_off = models.BooleanField( default=False, verbose_name=_('Notification one-off'), help_text=_('Notification one-off help text'), ) last_run_at = models.DateTimeField( auto_now=False, auto_now_add=False, editable=False, blank=True, null=True, verbose_name=_('Notification last run'), ) content = RichTextUploadingField( blank=True, config_name='informing-content', verbose_name=_('Notification content'), ) history = HistoricalRecords(cascade_delete_history=True, excluded_fields=['last_run_at']) class Meta: verbose_name = _('Notification') verbose_name_plural = _('Notifications') ordering = ['-id'] unique_together = ('name', ) def __str__(self) -> str: return f'{self.name}' class NotificationConfirmation(models.Model): user_id = models.PositiveIntegerField( verbose_name=_('NotificationConfirmation userId')) notification = models.ForeignKey( Notification, on_delete=models.CASCADE, verbose_name=_('NotificationConfirmation notification')) datetime = models.DateTimeField( auto_now_add=True, verbose_name=_('NotificationConfirmation datetime')) class Meta: verbose_name = _('Notification confirmation') verbose_name_plural = _('Notification confirmations') ordering = ['-id'] unique_together = () def __str__(self) -> str: return f'{self.user_id}: {self.notification}'