from django.db import models from django.contrib.auth import get_user_model User = get_user_model() class IssueType(models.Model): """Тип ошибки или неисправности""" CATEGORY_CHOICES = [ ('error', 'Ошибка'), ('malfunction', 'Неисправность'), ] PLACES = [ ("kr", "КР"), ("dv", "ДВ") ] location_place = models.CharField( max_length=30, choices=PLACES, null=True, default="kr", verbose_name="Комплекс", help_text="К какому комплексу принадлежит журнал", ) name = models.CharField(max_length=255, verbose_name="Название") category = models.CharField( max_length=20, choices=CATEGORY_CHOICES, default='error', verbose_name='Категория' ) def __str__(self): return f"{self.name} ({self.get_category_display()})" class Meta: verbose_name = "Тип ошибки/неисправности" verbose_name_plural = "Типы ошибок/неисправностей" ordering = ["category", "name"] class DailyReport(models.Model): """Ежедневный отчёт""" PLACES = [ ("kr", "КР"), ("dv", "ДВ") ] date = models.DateField( verbose_name="Дата", db_index=True, help_text="Дата отчёта" ) daily_work_hours = models.DecimalField( max_digits=5, decimal_places=2, default=0, verbose_name="Время работы за день (ч)" ) weekly_work_hours = models.DecimalField( max_digits=6, decimal_places=2, default=0, verbose_name="Время работы за неделю (ч)" ) explanation = models.TextField(blank=True, null=True, verbose_name='Пояснение') comment = models.TextField(blank=True, null=True, verbose_name='Комментарий') location_place = models.CharField( max_length=30, choices=PLACES, null=True, default="kr", verbose_name="Комплекс", help_text="К какому комплексу принадлежит журнал", ) created_at = models.DateTimeField(auto_now_add=True, verbose_name="Создано") updated_at = models.DateTimeField(auto_now=True, verbose_name="Обновлено") created_by = models.ForeignKey( User, on_delete=models.SET_NULL, null=True, blank=True, related_name='daily_reports_created', verbose_name="Создал" ) def __str__(self): return f"Отчёт за {self.date}" class Meta: verbose_name = "Ежедневный отчёт" verbose_name_plural = "Ежедневные отчёты" ordering = ["-date"] constraints = [ models.UniqueConstraint( fields=['date', 'location_place'], name='unique_daily_report_date_location' ) ] class DowntimePeriod(models.Model): """Период простоя""" report = models.ForeignKey( DailyReport, on_delete=models.CASCADE, related_name='downtime_periods', verbose_name="Отчёт" ) start_time = models.TimeField(verbose_name="Время начала") end_time = models.TimeField(verbose_name="Время окончания") reason = models.TextField(verbose_name="Причина простоя") def __str__(self): return f"{self.start_time.strftime('%H:%M')}-{self.end_time.strftime('%H:%M')}: {self.reason[:30]}" @property def duration_hours(self): """Длительность простоя в часах""" from datetime import datetime, timedelta start = datetime.combine(datetime.today(), self.start_time) end = datetime.combine(datetime.today(), self.end_time) if end < start: end += timedelta(days=1) delta = end - start return delta.total_seconds() / 3600 class Meta: verbose_name = "Период простоя" verbose_name_plural = "Периоды простоя" ordering = ["start_time"] class IssueMark(models.Model): """Отметка об ошибке/неисправности в отчёте""" report = models.ForeignKey( DailyReport, on_delete=models.CASCADE, related_name='issue_marks', verbose_name="Отчёт" ) issue_type = models.ForeignKey( IssueType, on_delete=models.CASCADE, related_name='marks', verbose_name="Тип ошибки/неисправности" ) is_present = models.BooleanField(default=False, verbose_name="Наличие") def __str__(self): mark = "+" if self.is_present else "-" return f"{self.report.date} - {self.issue_type.name}: {mark}" class Meta: verbose_name = "Отметка об ошибке" verbose_name_plural = "Отметки об ошибках" unique_together = ['report', 'issue_type'] ordering = ["issue_type__category", "issue_type__name"]