from django.db import models from django.conf import settings from django.utils import timezone class WorkLog(models.Model): date = models.DateField('Дата', default=timezone.localdate, db_index=True) technician = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.PROTECT, related_name='work_logs', verbose_name='Исполнитель', ) location = models.ForeignKey( 'locations.Location', on_delete=models.SET_NULL, null=True, blank=True, related_name='work_logs', verbose_name='Локация', ) # Устаревший грубый вид (~7 типов); для новых записей не заполняется. work_type = models.ForeignKey( 'core.Directory', on_delete=models.PROTECT, limit_choices_to={'directory_type__code': 'worklog_type', 'is_active': True}, related_name='worklogs_by_type', verbose_name='Вид работ', null=True, blank=True, ) catalog_work = models.ForeignKey( 'core.Directory', on_delete=models.PROTECT, limit_choices_to={'directory_type__code': 'it_work', 'is_active': True}, related_name='worklogs_by_catalog', verbose_name='Типовая работа', null=True, blank=True, ) details = models.JSONField('Уточнения', default=dict, blank=True) description = models.TextField('Комментарий', blank=True) result = models.TextField('Результат', blank=True) hours_spent = models.DecimalField('Затрачено часов', max_digits=5, decimal_places=1, null=True, blank=True) equipment = models.ForeignKey( 'it_manager.Equipment', on_delete=models.SET_NULL, null=True, blank=True, related_name='work_logs', verbose_name='Оборудование', ) ticket = models.ForeignKey( 'it_manager.Ticket', on_delete=models.SET_NULL, null=True, blank=True, related_name='work_logs', verbose_name='Заявка', ) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: verbose_name = 'Выполненная работа' verbose_name_plural = 'Журнал выполненных работ' ordering = ['-date', '-created_at'] indexes = [ models.Index(fields=['date', 'technician']), ] def __str__(self): if self.catalog_work_id: title = self.catalog_work.name elif self.work_type_id: title = self.work_type.name else: title = (self.description or '—')[:40] return f'{title} — {self.technician} — {self.date:%d.%m.%Y}' @property def display_title(self) -> str: from apps.it_manager.work_directory import worklog_display_title return worklog_display_title(self) class ServiceCall(models.Model): date_time = models.DateTimeField('Дата и время', default=timezone.now, db_index=True) caller = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.PROTECT, related_name='service_calls_made', verbose_name='Кто обратился', ) handler = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, related_name='service_calls_handled', verbose_name='Принял обращение', ) channel = models.ForeignKey( 'core.Directory', on_delete=models.PROTECT, limit_choices_to={'directory_type__code': 'servicecall_channel', 'is_active': True}, related_name='servicecalls_by_channel', verbose_name='Канал', ) location = models.ForeignKey( 'locations.Location', on_delete=models.SET_NULL, null=True, blank=True, related_name='service_calls', verbose_name='Локация', ) description = models.TextField('Описание обращения') resolution = models.TextField('Решение', blank=True) minutes_spent = models.PositiveSmallIntegerField('Затрачено минут', null=True, blank=True) ticket = models.ForeignKey( 'it_manager.Ticket', on_delete=models.SET_NULL, null=True, blank=True, related_name='service_calls', verbose_name='Связанная заявка', help_text='Если обращение переросло в тикет', ) created_at = models.DateTimeField(auto_now_add=True) class Meta: verbose_name = 'Обращение' verbose_name_plural = 'Обращения' ordering = ['-date_time'] indexes = [ models.Index(fields=['date_time', 'handler']), ] def __str__(self): return (f'{self.channel.name} — {self.caller} — ' f'{self.date_time:%d.%m.%Y %H:%M}') @property def duration_display(self): if not self.minutes_spent: return '—' if self.minutes_spent < 60: return f'{self.minutes_spent} мин.' h, m = divmod(self.minutes_spent, 60) return f'{h}ч {m}м' if m else f'{h}ч'