Kaynağa Gözat

Necessary changes for the functionality of document uploading for partners

TonyKurts 3 ay önce
ebeveyn
işleme
b46aa69be7
4 değiştirilmiş dosya ile 65 ekleme ve 32 silme
  1. 12 3
      admin/documents.py
  2. 1 1
      models/__init__.py
  3. 14 14
      models/company.py
  4. 38 14
      models/documents.py

+ 12 - 3
admin/documents.py

@@ -1,5 +1,13 @@
 from django.contrib import admin
-from dbsynce.models import Documents
+from dbsynce.models import Documents, DocumentFile
+
+
+class DocumentFileInline(admin.TabularInline):
+    model = DocumentFile
+    extra = 1
+    fields = ('file',)
+    can_delete = True
+
 
 @admin.register(Documents)
 class DocumentsAdmin(admin.ModelAdmin):
@@ -12,7 +20,6 @@ class DocumentsAdmin(admin.ModelAdmin):
         'requirements',
         'status',
         'ticket_status',
-        'datalink',
         'doc_type',
         'user_id',
         'company_id',
@@ -27,4 +34,6 @@ class DocumentsAdmin(admin.ModelAdmin):
         'user_id',
         'company_id',
         'checked_by',
-    )
+    )
+
+    inlines = [DocumentFileInline]

+ 1 - 1
models/__init__.py

@@ -1,6 +1,6 @@
 from .client import Client
 from .company import Company
-from .documents import Documents
+from .documents import Documents, DocumentFile
 from .orders import Orders
 from .permissions import Permissions
 from .provider import Provider

+ 14 - 14
models/company.py

@@ -7,25 +7,25 @@ from tickets.models import Ticket
 
 
 class Company(models.Model):
-    legal_name = models.CharField(max_length=150, help_text="Настоящее имя юридического лица")
+    legal_name = models.CharField("Название организации", max_length=150, help_text="Настоящее имя юридического лица")
 
     # FIXME: Нет уверенности, что после удаления пользователя следует оставлять `models.DO_NOTHING`
-    repr_id =models.ForeignKey(get_user_model(), blank=True, on_delete=models.DO_NOTHING, help_text="Уникальный идентификатор представителя компании")
+    repr_id =models.ForeignKey(get_user_model(), blank=True, verbose_name="Представитель организации", on_delete=models.DO_NOTHING, help_text="Уникальный идентификатор представителя компании")
     
-    requirements = models.CharField(max_length=150, default="DS01y04y05y06y07yMPUCS13MPUB", help_text="Код необходимый для того, чтобы ресурс мог стать активным")
-    status = models.CharField(max_length=150, default="deactivated", help_text="Cтатус обработки заявки")
+    requirements = models.CharField("Ограничения", max_length=150, default="DS01y04y05y06y07yMPUCS13MPUB", help_text="Код необходимый для того, чтобы ресурс мог стать активным")
+    status = models.CharField("Статус", max_length=150, default="deactivated", help_text="Cтатус обработки заявки")
 
     # FIXME: Нет уверенности, что после удаления заявки следует оставлять `models.DO_NOTHING`
-    ticket_status = models.ForeignKey(Ticket, on_delete=models.SET_NULL, blank=True, null=True, help_text="ID заявки, привязанной к текущей записи")
-
-    inn = models.CharField(max_length=10, unique=True, help_text="ИНН компании")
-    kpp = models.CharField(max_length=9, help_text="КПП компании")
-    ogrn = models.CharField(max_length=13, help_text="ОГРН компании")
-    bank_name = models.CharField(max_length=150, help_text="Название банка с расчетным счетом")
-    bik = models.CharField(max_length=9, help_text="БИК компании")
-    rs = models.CharField(max_length=50, help_text="Расчетный счет")
-    ks = models.CharField(max_length=50, help_text="Корреспондентский счет (счет, открываемый банковской организацией в подразделении самого банка)")
-    address = models.CharField(max_length=150, help_text="Юридический адрес")
+    ticket_status = models.ForeignKey(Ticket, on_delete=models.SET_NULL, blank=True, null=True, help_text="ID заявки, привязанной к текущей записи", verbose_name="Связанный тикет")
+
+    inn = models.CharField("ИНН компании", max_length=10, unique=True)
+    kpp = models.CharField("КПП компании", max_length=9)
+    ogrn = models.CharField("ОГРН компании", max_length=13)
+    bank_name = models.CharField("Название банка", max_length=150, help_text="Название банка с расчетным счетом")
+    bik = models.CharField("БИК компании", max_length=9)
+    rs = models.CharField("Расчетный счет", max_length=50)
+    ks = models.CharField("Корреспондентский счет", max_length=50, help_text="Корреспондентский счет (счет, открываемый банковской организацией в подразделении самого банка)")
+    address = models.CharField("Юридический адрес", max_length=150)
     is_global = models.CharField(max_length=1, default="f", help_text="Доступно ли для хранения в глобальном сервисе / Нужна синхронизация данных")
     is_visible = models.CharField(max_length=1, default="f", help_text="Доступно ли для планирования в цепочке с другими услугами в глобальном сервисе")
     

+ 38 - 14
models/documents.py

@@ -1,7 +1,10 @@
 import re
+import os
 
 from django.db import models
+from django.urls import reverse
 from django.contrib.auth import get_user_model
+from django.contrib.contenttypes.models import ContentType
 
 from dbsynce.models.company import Company
 from tickets.models import Ticket
@@ -20,8 +23,8 @@ class Documents(models.Model):
         ("03", "СНИЛС"),
         ("04", "Cвидетельство о регистрации компании"),
         ("05", "Cистема налогообложения"),
-        ("06", "Документ, подтверждающий полномочия представлять компанию (доверенность, приказ)"),
-        ("07", "Документ, подтверждающий право совершать действия (права, лицензия)"),
+        ("06", "Доверенность / Приказ"),
+        ("07", "Права / Лицензия"),
         ("08", "Документ, подтверждающий собственность"),
         ("09", "Документ об образовании"),
         ("10", "Медицинская книжка"),
@@ -30,30 +33,51 @@ class Documents(models.Model):
         ("13", "Фотография"),
         ("99", "Иное"),
     ]
-
-    check_date = models.DateTimeField(help_text="timestamp проверки")
-    check_level = models.IntegerField(help_text="информация об уровне проверки. Документ может быть проверен как платформой, так и мета-сервисом, так и партнером мета-сервиса, а может быть и никем (просто загружен). Указывается, так как достоверность проверки разная. Документ, проверенный только на низком уровне, не принимается во внимание как имеющийся до прохождения более высокоуровневой проверки. Информацию об уровнях проверки можно посмотреть по словарю Requirements. В данной таблице хранится информация о наиболее высоком уровне проверки.")
-    expire_date = models.DateTimeField(null=True, help_text="срок окончания действия документа.")
-    id_metaservice = models.BigIntegerField(null=True, help_text="уникальный идентификатор мета-сервиса, необходимый для синхронизации данных. Если при синхронизации возникает конфликт (несовместимость) с другим сервисом, предлагается или форсировать изменения везде (если возможно), либо is_global выставляется как false.")
-    requirements = models.CharField(max_length=150)
-    status = models.CharField(max_length=150, help_text="активность на основе системы заявок")
-    ticket_status = models.ForeignKey(Ticket, on_delete=models.DO_NOTHING, help_text="id последнего актуального тикета, касающийся статуса. Если он меняет статус на закрытый - вызывается проверка, которая смотрит, нет ли другого открытого по пользователю.")
-    datalink = models.TextField(blank=True, help_text="адрес фактического размещения на физическом носителе, если информация настолько велика, что не может храниться внутри БД.")
+    DOC_TYPES_DICT = dict(DOC_TYPES)
+    
+    # FIXME: id_metaservice должно принимать текущий идентификатор метасервиса, на котором происходит создание записи
+    id_metaservice = models.BigIntegerField(default=1, help_text="уникальный идентификатор мета-сервиса, необходимый для синхронизации данных. Если при синхронизации возникает конфликт (несовместимость) с другим сервисом, предлагается или форсировать изменения везде (если возможно), либо is_global выставляется как false.")
+    check_date = models.DateTimeField(auto_now_add=True, help_text="timestamp проверки")
+    check_level = models.IntegerField(null=True, blank=True, help_text="информация об уровне проверки. Документ может быть проверен как платформой, так и мета-сервисом, так и партнером мета-сервиса, а может быть и никем (просто загружен). Указывается, так как достоверность проверки разная. Документ, проверенный только на низком уровне, не принимается во внимание как имеющийся до прохождения более высокоуровневой проверки. Информацию об уровнях проверки можно посмотреть по словарю Requirements. В данной таблице хранится информация о наиболее высоком уровне проверки.")
+    expire_date = models.DateField(null=True, blank=True, help_text="срок окончания действия документа.")
+    # FIXME: requirements должно иметь другое значение поумолчанию
+    requirements = models.CharField(max_length=150, default="fixme")
+    # FIXME: status должен иметь другое значение поумолчанию
+    status = models.CharField(max_length=150, default="deactivated", help_text="активность на основе системы заявок")
+    ticket_status = models.ForeignKey(Ticket, null=True, blank=True, on_delete=models.SET_NULL, help_text="id последнего актуального тикета, касающийся статуса. Если он меняет статус на закрытый - вызывается проверка, которая смотрит, нет ли другого открытого по пользователю.")
     doc_type = models.CharField(max_length=2, choices=DOC_TYPES, help_text="тип документа (паспорт/паспорт 1 страница и т д) в соответствии с классификатором типов документов (см описание в Requirements)")
     user_id = models.ForeignKey(get_user_model(), related_name="user_id_doc", on_delete=models.DO_NOTHING, help_text="уникальный идентификатор пользователя (конкретного клиентского аккаунта) являющегося владельцем данного документа")
     company_id = models.ForeignKey(Company, on_delete=models.DO_NOTHING, null=True, help_text="идентификатор компании, к которой относится документ, если таковая есть (может не быть)")
     is_global = models.BooleanField(default=False, help_text="доступны ли документы для хранения в глобальном сервисе/нужна синхронизация")
     is_visible = models.BooleanField(default=False, help_text="доступна ли информация о наличии документов для планирования в цепочке с другими услугами в глобальном сервисе")
-    checked_by = models.ForeignKey(get_user_model(), related_name="checked_by_doc", on_delete=models.DO_NOTHING, null=True, help_text="userid проверившего")
+    checked_by = models.ForeignKey(get_user_model(), null=True, blank=True, related_name="checked_by_doc", on_delete=models.DO_NOTHING, help_text="userid проверившего")
 
     @staticmethod
     def parse_requirements(requirements: str):
         """
         Метод позволяет разобрать строку requirements в удобочитаемый вид.
         """
-        return re.findall(r'\d{2}', requirements)
+        return sorted(set(re.findall(r'\d{2}', requirements)))
+
+    def get_admin_url(self):
+        """
+        Возвращает URL-адрес текущего объекта в административной панели Django.
+
+        Returns:
+            str: URL-адрес текущего объекта в административной панели Django
+        """
+        content_type = ContentType.objects.get_for_model(self.__class__)
+        return reverse("admin:%s_%s_change" % (content_type.app_label, content_type.model), args=(self.id,))
 
     class Meta:
         db_table = "documents"
         verbose_name = "Документ"
-        verbose_name_plural = "Документы"
+        verbose_name_plural = "Документы"
+
+
+class DocumentFile(models.Model):
+    document = models.ForeignKey(Documents, related_name='files', on_delete=models.CASCADE)
+    file = models.FileField(upload_to=f'uploads/partners_docs/')
+
+    def __str__(self):
+        return os.path.basename(self.file.name)