diff --git a/document_management/models.py b/document_management/models.py index f823889e1c..43a070b68c 100644 --- a/document_management/models.py +++ b/document_management/models.py @@ -1,62 +1,260 @@ +import os +import uuid + +from django.contrib.postgres.fields import ArrayField from django.db import models +from hospitals.models import Hospitals +from podrazdeleniya.models import Podrazdeleniya +from users.models import DoctorProfile + class GroupDocuments(models.Model): title = models.CharField(max_length=128, blank=True, null=True) class Meta: - verbose_name = 'Группа Документов' - verbose_name_plural = 'Группы документов' + verbose_name = "Группа Документов" + verbose_name_plural = "Группы документов" def __str__(self): - return f'{self.title}' + return f"{self.title}" @property def json(self): return { - 'id': self.id, - 'title': self.title, + "id": self.id, + "title": self.title, } -class Attributes(models.Model): +class TypeDocuments(models.Model): title = models.CharField(max_length=128, blank=True, null=True) + group_document = models.ForeignKey(GroupDocuments, default=None, blank=True, null=True, help_text="Группа документов", on_delete=models.SET_NULL) + code = models.CharField(max_length=55, blank=True, null=True) class Meta: - verbose_name = 'Группа Документов' - verbose_name_plural = 'Группы документов' + verbose_name = "Вид документа" + verbose_name_plural = "Виды документов" def __str__(self): - return f'{self.title}' + return f"{self.title}" + + @property + def json(self): + return { + "id": self.id, + "title": self.title, + } -class TypeDocuments(models.Model): +class Nomenclature(models.Model): title = models.CharField(max_length=128, blank=True, null=True) - group_document = models.ForeignKey(GroupDocuments, default=None, blank=True, null=True, help_text='Группа документов', on_delete=models.SET_NULL) - code = models.CharField(max_length=55, blank=True, null=True) + type_document = models.ForeignKey(TypeDocuments, default=None, blank=True, null=True, db_index=True, help_text="Тип документа", on_delete=models.SET_NULL) + department = models.ForeignKey( + Podrazdeleniya, related_name="department_nomenclature", help_text="Подразделение", db_index=True, null=True, blank=True, default=None, on_delete=models.SET_NULL + ) class Meta: - verbose_name = 'Группа Документов' - verbose_name_plural = 'Группы документов' + verbose_name = "Номенклатура" + verbose_name_plural = "Носенклатуры" def __str__(self): - return f'{self.title}' + return f"{self.title}" + + +class Generators(models.Model): + title = models.CharField(max_length=400, help_text="Название генератора номера") + hospital = models.ForeignKey(Hospitals, on_delete=models.CASCADE, db_index=True, verbose_name="Больница") + year = models.IntegerField(verbose_name="Год", db_index=True) + is_active = models.BooleanField(verbose_name="Активность диапазона", db_index=True) + start = models.PositiveBigIntegerField(verbose_name="Начало диапазона") + end = models.PositiveBigIntegerField(verbose_name="Конец диапазона", null=True, blank=True, default=None) + last = models.PositiveBigIntegerField(verbose_name="Последнее значение диапазона", null=True, blank=True) + free_numbers = ArrayField(models.PositiveBigIntegerField(verbose_name="Свободные номера"), default=list, blank=True) + prepend_length = models.PositiveSmallIntegerField(verbose_name="Длина номера", help_text='Если номер короче, впереди будет добавлено недостающее кол-во "0"') + department = models.ForeignKey( + Podrazdeleniya, related_name="department_for_generator", help_text="Подразделение", db_index=True, null=True, blank=True, default=None, on_delete=models.SET_NULL + ) + + def __str__(self): + return f"{self.hospital} {self.year} {self.is_active} {self.start} — {self.end} ({self.last})" + + class Meta: + verbose_name = "Генератор номеров" + verbose_name_plural = "Генераторы номеров" + + +class MetaFieldsForAllTypeDocuments(models.Model): + TYPES = ( + (0, "Text"), + (1, "Date"), + (2, "Calc"), + (3, "List"), + (4, "Dict"), + (5, "Radio"), + (6, "Number"), + (7, "Number range"), + (8, "Time HH:MM"), + (9, "Table"), + (10, "Исполнитель"), + ) + title = models.CharField(max_length=400, help_text="Название поля ввода") + short_title = models.CharField(max_length=400, default="", blank=True, help_text="Синоним-короткое название поля ввода") + order = models.IntegerField() + default_value = models.TextField(blank=True, default="") + input_templates = models.TextField() + hide = models.BooleanField() + lines = models.IntegerField(default=3) + field_type = models.SmallIntegerField(default=0, choices=TYPES, blank=True) + required = models.BooleanField(default=False, blank=True) + + class Meta: + verbose_name = "Мета реквизит для всех документов" + verbose_name_plural = "Мета реквизиты для всех документов" + + def __str__(self): + return f"{self.title}" + + +class DocumentFields(models.Model): + TYPES = ( + (0, "Text"), + (1, "Date"), + (2, "Calc"), + (3, "List"), + (4, "Dict"), + (5, "Radio"), + (6, "Number"), + (7, "Number range"), + (8, "Time HH:MM"), + (9, "Table"), + (10, "Исполнитель"), + ) + type_document = models.ForeignKey(TypeDocuments, default=None, db_index=True, blank=True, null=True, help_text="Тип документа", on_delete=models.SET_NULL) + title = models.CharField(max_length=400, help_text="Название поля ввода") + short_title = models.CharField(max_length=400, default="", blank=True, help_text="Синоним-короткое название поля ввода") + order = models.IntegerField() + default_value = models.TextField(blank=True, default="") + input_templates = models.TextField() + hide = models.BooleanField() + lines = models.IntegerField(default=3) + field_type = models.SmallIntegerField(default=0, choices=TYPES, blank=True) + required = models.BooleanField(default=False, blank=True) + is_meta_attributes = models.BooleanField(default=False, blank=True) + is_content_attributes = models.BooleanField(default=False, blank=True) + + class Meta: + verbose_name = "Реквизит для документа" + verbose_name_plural = "Реквизит для документов" + + def __str__(self): + return f"{self.type_document}" + + +class Documents(models.Model): + type_document = models.ForeignKey(TypeDocuments, db_index=True, default=None, blank=True, null=True, help_text="Тип документа", on_delete=models.SET_NULL) + who_create = models.ForeignKey(DoctorProfile, db_index=True, default=None, blank=True, null=True, help_text="Создатель документа", on_delete=models.SET_NULL) + create_at = models.DateTimeField(auto_now_add=True, help_text="Дата создания документа", db_index=True) + time_registration = models.DateTimeField(null=True, blank=True, db_index=True, help_text="Время регистрации") + number_registration = models.CharField(max_length=20, blank=True, help_text="Регистрационный номер документа", db_index=True) + is_registered = models.BooleanField(default=False, blank=True, help_text="Прошел регистрацию", db_index=True) + need_approve = models.BooleanField(default=False, blank=True, help_text="Находится на согласовании", db_index=True) + need_control = models.BooleanField(default=False, blank=True, help_text="Находится на контроле", db_index=True) + total_approved = models.BooleanField(default=False, blank=True, help_text="Полностью согласован", db_index=True) + total_completed = models.BooleanField(default=False, blank=True, help_text="Полностью завершен/снят с контроля", db_index=True) + parent_document = models.ForeignKey("self", db_index=True, related_name="document_p", help_text="Документ основание", blank=True, null=True, default=None, on_delete=models.SET_NULL) + + class Meta: + verbose_name = "Документ-экземпляр" + verbose_name_plural = "Документы экземляров" + + def __str__(self): + return f"{self.type_document}" - @property - def json(self): - return { - 'id': self.id, - 'title': self.title, - } +class DocumentEmployeeApprove(models.Model): + document = models.ForeignKey(Documents, db_index=True, on_delete=models.CASCADE) + employee = models.ForeignKey(DoctorProfile, related_name="employee_approve", db_index=True, default=None, blank=True, null=True, help_text="Согласующий", on_delete=models.SET_NULL) + time_approve = models.DateTimeField(null=True, blank=True, db_index=True, help_text="Время согласования исполнителем") + create_at_approve = models.DateTimeField(null=True, blank=True, db_index=True, help_text="Время запроса согласования") + who_create = models.ForeignKey( + DoctorProfile, related_name="who_create_to_approve", db_index=True, default=None, blank=True, null=True, help_text="кто запросил согласование", on_delete=models.SET_NULL + ) + is_cancel = models.BooleanField(default=True, blank=True, db_index=True) + note_cancel = models.CharField(max_length=130, blank=True, help_text="Причина отмены") + + class Meta: + verbose_name = "Согласование документа" + verbose_name_plural = "Согласования документов" + + def __str__(self): + return f"{self.document} {self.employee} {self.time_approve} {self.is_cancel}" -class TypeDocumentsAttributes(models.Model): - type_document = models.ForeignKey(TypeDocuments, default=None, blank=True, null=True, help_text='Тип документа', on_delete=models.SET_NULL) - attribute = models.ForeignKey(Attributes, default=None, blank=True, null=True, help_text='Тип реквизита', on_delete=models.SET_NULL) + +class DocumentResolution(models.Model): + document = models.ForeignKey(Documents, db_index=True, on_delete=models.CASCADE) + employee = models.ForeignKey(DoctorProfile, related_name="employee_resolution", db_index=True, default=None, blank=True, null=True, help_text="Исполнитель", on_delete=models.SET_NULL) + time_resolution = models.DateTimeField(null=True, blank=True, db_index=True, help_text="Время создания резолюции") + who_create = models.ForeignKey( + DoctorProfile, related_name="who_create_resolution", db_index=True, default=None, blank=True, null=True, help_text="Кто создал резолюцию", on_delete=models.SET_NULL + ) + is_cancel = models.BooleanField(default=True, blank=True, db_index=True) + note_cancel = models.CharField(max_length=128, blank=True, help_text="Причина отмены") + note_resolution = models.CharField(max_length=255, blank=True, help_text="Содержание резолюции") + parent_resolution = models.ForeignKey("self", db_index=True, related_name="resolution_p", help_text="Резолюция основание", blank=True, null=True, default=None, on_delete=models.SET_NULL) class Meta: - verbose_name = 'Реквизит для документа' - verbose_name_plural = 'Реквизит для документов' + verbose_name = "Резолюция документа" + verbose_name_plural = "Резолюции документов" def __str__(self): - return f'{self.type_document} {self.attribute}' + return f"{self.document} {self.employee} {self.time_resolution} {self.is_cancel}" + + +class DocumentControl(models.Model): + document = models.ForeignKey(Documents, db_index=True, on_delete=models.CASCADE) + time_control = models.DateTimeField(null=True, blank=True, db_index=True, help_text="Дата контроля") + resolution = models.ForeignKey(DocumentResolution, db_index=True, on_delete=models.CASCADE, help_text="Резолюция") + is_completed = models.BooleanField(default=False, blank=True, db_index=True, help_text="Выполнена резолюция") + + class Meta: + verbose_name = "Контроль документа" + verbose_name_plural = "Контроли документов" + + def __str__(self): + return f"{self.document} {self.document} {self.time_control}" + + +class DocumentResult(models.Model): + document = models.ForeignKey(Documents, db_index=True, default=None, blank=True, null=True, help_text="Тип документа", on_delete=models.SET_NULL) + create_at = models.DateTimeField(auto_now_add=True, help_text="Дата создания/изменения", db_index=True) + who_create = models.ForeignKey(DoctorProfile, default=None, blank=True, null=True, help_text="Создатель", on_delete=models.SET_NULL) + value = models.TextField(null=True, blank=True, help_text="Значение") + document_field = models.ForeignKey(DocumentFields, db_index=True, default=None, blank=True, null=True, help_text="поле документа", on_delete=models.SET_NULL) + field_type = models.SmallIntegerField(default=None, blank=True, choices=DocumentFields.TYPES, null=True) + meta_document_field = models.ForeignKey(MetaFieldsForAllTypeDocuments, db_index=True, default=None, blank=True, null=True, help_text="поле документа", on_delete=models.SET_NULL) + meta_field_type = models.SmallIntegerField(default=None, blank=True, choices=MetaFieldsForAllTypeDocuments.TYPES, null=True) + + class Meta: + verbose_name = "Реквизит для документа" + verbose_name_plural = "Реквизит для документов" + + def __str__(self): + return f"{self.document}" + + +def get_file_path(instance: "DocumentFiles", filename): + return os.path.join("document_files", str(instance.document.pk), str(uuid.uuid4()), filename) + + +class DocumentFiles(models.Model): + document = models.ForeignKey(Documents, db_index=True, on_delete=models.CASCADE) + uploaded_file = models.FileField(upload_to=get_file_path, blank=True, null=True, default=None) + created_at = models.DateTimeField(auto_now_add=True) + type_file = models.CharField(max_length=16, blank=True, help_text="Тип документа") + who_add_files = models.ForeignKey(DoctorProfile, default=None, blank=True, null=True, related_name="document_who_add_files", help_text="Создатель направления", on_delete=models.SET_NULL) + comment = models.CharField(max_length=130, blank=True, help_text="Комментарий") + + class Meta: + verbose_name = "Файл на документ" + verbose_name_plural = "Файлы на документы"