production-taskbar / backend / informing / models.py
models.py
Raw
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}'