Ver Fonte

activation for testing added

ShariX Developer há 5 dias atrás
pai
commit
583deffe2a

+ 8 - 0
.env.example

@@ -71,3 +71,11 @@ METASERVICE_ID=1
 
 LOGIN_REDIRECT_URL = "webservice_running:main_local"
 
+MIN_SERVICE_CATEGORY_REQUIREMENTS="DSMPU"
+MIN_SERVICE_REQUIREMENTS="DSMPU"
+MIN_RESOURCE_REQUIREMENTS="S01y04y05y06y07yMPUCS13MPUB"
+MIN_PROVIDER_REQUIREMENTS="DSMPU"
+MIN_RELTATIONSHIP_REQUIREMENTS="DSMPU"
+MIN_COMPANY_REQUIREMENTS="DSMPU"
+MIN_CLIENT_REQUIREMENTS="DSMPU"
+

+ 7 - 0
core/settings_vars.py

@@ -77,3 +77,10 @@ METASERVICE_ID = os.getenv("METASERVICE_ID")
 
 LOGIN_REDIRECT_URL = os.getenv("LOGIN_REDIRECT_URL")
 
+MIN_SERVICE_CATEGORY_REQUIREMENTS=os.getenv("MIN_SERVICE_CATEGORY_REQUIREMENTS")
+MIN_SERVICE_REQUIREMENTS=os.getenv("MIN_SERVICE_REQUIREMENTS")
+MIN_RESOURCE_REQUIREMENTS=os.getenv("MIN_RESOURCE_REQUIREMENTS")
+MIN_PROVIDER_REQUIREMENTS=os.getenv("MIN_PROVIDER_REQUIREMENTS")
+MIN_RELATIONSHIP_REQUIREMENTS=os.getenv("MIN_RELTATIONSHIP_REQUIREMENTS")
+MIN_COMPANY_REQUIREMENTS=os.getenv("MIN_COMPANY_REQUIREMENTS")
+MIN_CLIENT_REQUIREMENTS=os.getenv("MIN_CLIENT_REQUIREMENTS")

BIN
sharix_admin/static/sharix_admin/img/logo-old.png


BIN
sharix_admin/static/sharix_admin/img/logo.png


+ 81 - 76
sharix_admin/tables.py

@@ -147,7 +147,7 @@ class PartnersTable(tables.Table):
         )
 
     def render_check(self, value, record):
-        if record.status == 'active':
+        if record.status == '0':
             return format_html(
                 '<input class="form-check-input status-toggle" checked type="checkbox" id="flexCheckDefault" data-partners-id="{}">',
                 record.id
@@ -292,9 +292,9 @@ class ResourcesTable(tables.Table):
         )
 
     def render_check(self, value, record):
-        if record.status == 'active':
+        if record.status == '0':
             return format_html(
-                '<input class="form-check-input status-toggle" checked type="checkbox" id="flexCheckDefault" data-resource-id="{}">',
+                '<input class="form-check-input status-toggle" checked type="checkbox" id="flexCheckDefault"  data-resource-id="{}">',
                 record.id
             )
         else:
@@ -389,7 +389,7 @@ class ProvidersTable(tables.Table):
         )
 
     def render_check(self, value, record):
-        if record.status == 'active':
+        if record.status == '0':
             return format_html(
                 '<input class="form-check-input status-toggle" checked type="checkbox" id="flexCheckDefault" data-provider-id="{}">',
                 record.id
@@ -489,11 +489,16 @@ class ServiceTariffsTable(tables.Table):
         )
 
     def render_check(self, value, record):
-        if record.status == 'active':
-            return format_html('<input class="form-check-input status-toggle" disabled  checked type="checkbox"')
+        if record.status == '0':
+            return format_html(
+                '<input class="form-check-input status-toggle" checked type="checkbox" id="flexCheckDefault" data-service-id="{}">',
+                record.id
+            )
         else:
-            return format_html('<input class="form-check-input status-toggle" disabled  type="checkbox"')
-
+            return format_html(
+                '<input class="form-check-input status-toggle" type="checkbox" id="flexCheckDefault" data-service-id="{}">',
+                record.id
+            )
 
 class ServiceCategoriesTable(tables.Table):
     id = tables.LinkColumn(
@@ -619,72 +624,72 @@ class ServiceCategoriesTable(tables.Table):
     #     return format_html("<a href='{}'>{}</a>", record.get_absolute_url(), value)
 
 
-class ServiceTable(tables.Table):
-    id = tables.Column(
-        verbose_name=_('ID'),
-        attrs={
-            "td": {"width": "5%"}
-        }
-    )
-    service_category = tables.Column(
-        verbose_name=_('Description of the service'),
-        accessor='service_category.caption',
-        attrs={
-            'th': {'scope': 'col'},
-            "td": {"width": "20%"}}
-    )
+#class ServiceTable(tables.Table):
+#    id = tables.Column(
+#        verbose_name=_('ID'),
+#        attrs={
+#            "td": {"width": "5%"}
+#        }
+#    )
+#    service_category = tables.Column(
+#        verbose_name=_('Description of the service'),
+#        accessor='service_category.caption',
+#       attrs={
+#           'th': {'scope': 'col'},
+#           "td": {"width": "20%"}}
+#    )
 
     # description = tables.Column(verbose_name='Название тарифа', attrs={'th':{'scope':'col'}, "td":{"width":"20%"}})
     # description = tables.Column(verbose_name='Описание строки тарифов', attrs={'th':{'scope':'col'}, "td":{"width":"20%"}})
     # price_type = tables.Column(verbose_name='Тип тарифа', attrs={'th':{'scope':'col'}, "td":{"width":"20%"}})
 
-    price_km = tables.Column(
-        verbose_name=_('Cost km.'),
-        attrs={
-            'th': {'scope': 'col'},
-            "td": {"width": "20%"}
-        }
-    )
-    price_min = tables.Column(
-        verbose_name=_('Cost min.'),
-        attrs={
-            'th': {'scope': 'col'},
-            "td": {"width": "20%"}}
-    )
-    price_amount = tables.Column(
-        verbose_name=_('Cost of service'),
-        attrs={
-            'th': {'scope': 'col'},
-            "td": {"width": "20%"}
-        }
-    )
-
-    class Meta:
-        model = Service
-        attrs = {
-            "class": "table table-layout-fixed"
-        }
-        exclude = (
-            'resource',
-            'requirements',
-            'id_metaservice',
-            'price_type',
-            'ticket_status',
-            'is_global',
-            'is_visible'
-        )
-
-    def render_check(self, value, record):
-        if record.status == 'active':
-            return format_html(
-                '<input class="form-check-input status-toggle" checked type="checkbox" id="flexCheckDefault" data-service-id="{}">',
-                record.id
-            )
-        else:
-            return format_html(
-                '<input class="form-check-input status-toggle" type="checkbox" id="flexCheckDefault" data-service-id="{}">',
-                record.id
-            )
+ #   price_km = tables.Column(
+#        verbose_name=_('Cost km.'),
+#        attrs={
+#            'th': {'scope': 'col'},
+#            "td": {"width": "20%"}
+#        }
+#    )
+#    price_min = tables.Column(
+#        verbose_name=_('Cost min.'),
+#       attrs={
+#            'th': {'scope': 'col'},
+#           "td": {"width": "20%"}}
+#   )
+#    price_amount = tables.Column(
+#        verbose_name=_('Cost of service'),
+#        attrs={
+#            'th': {'scope': 'col'},
+#            "td": {"width": "20%"}
+ #       }
+ #   )
+#
+ #   class Meta:
+#        model = Service
+#        attrs = {
+#            "class": "table table-layout-fixed"
+#        }
+#        exclude = (
+#            'resource',
+#            'requirements',
+#            'id_metaservice',
+#            'price_type',
+#            'ticket_status',
+#            'is_global',
+#            'is_visible'
+#        )
+
+#    def render_check(self, value, record):
+#        if record.status == '0':
+#            return format_html(
+#                '<input class="form-check-input status-toggle" checked type="checkbox" id="flexCheckDefault" data-service-id="{}">',
+#                record.id
+#            )
+#        else:
+#            return format_html(
+#                '<input class="form-check-input status-toggle" type="checkbox" id="flexCheckDefault" data-service-id="{}">',
+#                record.id
+#            )
 
 
 class UserInfoTable(tables.Table):
@@ -763,14 +768,14 @@ class PermissionsTable(tables.Table):
         )
 
     def render_check(self, value, record):
-        if record.status == 'active':
+        if record.status == '0':
             return format_html(
-                '<input class="form-check-input status-toggle" checked type="checkbox" id="flexCheckDefault" data-resource-id="{}">',
+                '<input class="form-check-input status-toggle" checked type="checkbox" id="flexCheckDefault" data-permissions-id="{}">',
                 record.id
             )
         else:
             return format_html(
-                '<input class="form-check-input status-toggle" type="checkbox" id="flexCheckDefault" data-resource-id="{}">',
+                '<input class="form-check-input status-toggle" type="checkbox" id="flexCheckDefault" data-permissions-id="{}">',
                 record.id
             )
 
@@ -831,13 +836,13 @@ class RelationshipTable(tables.Table):
         )
 
     def render_check(self, value, record):
-        if record.status == 'active':
+        if record.status == '0':
             return format_html(
-                '<input class="form-check-input status-toggle" checked type="checkbox" id="flexCheckDefault" data-provider-id="{}">',
+                '<input class="form-check-input status-toggle" checked type="checkbox" id="flexCheckDefault" data-relationship-id="{}">',
                 record.id
             )
         else:
             return format_html(
-                '<input class="form-check-input status-toggle" type="checkbox" id="flexCheckDefault" data-provider-id="{}">',
+                '<input class="form-check-input status-toggle" type="checkbox" id="flexCheckDefault" data-relationship-id="{}">',
                 record.id
-            )
+            )

+ 62 - 0
sharix_admin/templates/sharix_admin/detail.html

@@ -0,0 +1,62 @@
+{% extends 'sharix_admin/base_admin.html' %}
+{% load static %}
+
+{% block view %}
+<p class="description_service">
+Тут представлена информация о Партнере Сервиса {{ company.legal_name }}. Редактировать информацию может только представитель Партнера Сервиса с ролью PartnerAdmin.
+</p>
+
+<div class="card w-100 mb-4">
+    <div class="card-body position-relative">
+        <h5 class="card-title fw-bold mb-4">{{ company.legal_name }}</h5>
+
+        <ul class="list-style-none">
+            <li><b>Представитель</b> {{ company.repr.get_full_name }}</li>
+            <li><b>Юр. адрес</b> {{ company.address }}</li>
+            
+	    {% comment %}
+            <!-- FIXME: Не настроено -->
+            <li><b>НДС</b> Не платит</li>
+	    {% endcomment %}
+            
+            <li><b>ИНН</b> {{ company.inn }}</li>
+            <li><b>ОГРН</b> {{ company.ogrn }}</li>
+            <li><b>Р/c</b> {{ company.rs }}</li>
+            <li><b>К/c</b> {{ company.ks }}</li>
+            <li><b>БИК</b> {{ company.bik }}</li>
+            <li><b>Банк</b> {{ company.bank_name }}</li>
+        </ul>
+    </div>
+    {% comment %}    <a class="btn btn-primary btn-edit" href="{% url "sharix_admin:partner/edit" %}">
+	    <img src="{% static 'sharix_admin/img/pencil.svg' %}">
+    </a>
+    {% endcomment %}
+</div>
+
+{% comment %}
+<h6 class="mb-4">Документы</h6>
+    <ul class="list-style-none">
+        {% for doc in docs %}
+            <li class="d-flex justify-content-between">
+                <div class="d-flex align-items-center">
+                    {% if doc.ticket_status and doc.status == "deactivated" %}
+                        <i class="fa-solid fa-clock-rotate-left me-2 no-user-select fs-4 text-warning"></i>
+                    {% elif doc.status == "activated" %}
+                        <i class="fa-solid fa-check me-2 no-user-select fs-4 text-success"></i>
+                    {% else %}
+                        <i class="fa-regular fa-file me-2 no-user-select fs-4 text-primary"></i>
+                    {% endif %}
+
+                    {{ doc.get_doc_type_display }}
+                </div>
+                
+                {% if doc.ticket_status %}
+                    <a class="btn btn-sm btn-outline-primary" href="{% url "sharix_admin:partner_doc" doc.doc_type %}">Посмотреть</a>
+                {% else %}
+                    <a class="btn btn-sm btn-primary" href="{% url "sharix_admin:partner_doc_upload" doc.doc_type %}">Загрузить</a>
+                {% endif %}
+            </li>
+        {% endfor %}
+    </ul>
+{% endcomment %}
+{% endblock %}

+ 24 - 0
sharix_admin/templates/sharix_admin/include/doc.html

@@ -0,0 +1,24 @@
+{% extends 'sharix_admin/base_admin.html' %}
+{% load static %}
+
+{% block view %}
+
+<h5 class="my-3">Общая информация о документе</h6>
+
+<ul>
+    <li><b>Статус:</b> {{ doc.status }}</li>
+    <li><b>Дата проверки:</b> {{ doc.check_date }}</li>
+    <li><b>Срок окончания действия документа:</b> {{ doc.expire_date }}</li>
+    <li><b>Компания:</b> {{ doc.company.legal_name }}</li>
+    <li><b>Ресурс:</b> {{ doc.resource.id }}</li>
+</ul>
+
+<h5 class="my-3">Файлы</h6>
+<ul>
+    {% for doc_file in doc_files %}
+        <li><a href='{{ doc_file.file.url }}' target='_blank'>{{ doc_file }}</a></li>
+    {% endfor %}
+</ul>  
+
+<a class="btn btn-primary" href="{% url "sharix_admin:partner_doc_upload" doc.doc_type %}">Загрузить новые файлы</a>
+{% endblock %}

+ 87 - 0
sharix_admin/templates/sharix_admin/include/doc_upload.html

@@ -0,0 +1,87 @@
+{% extends 'sharix_admin/base_admin.html' %}
+{% load static %}
+
+
+{% block view %}
+
+<p class="description_service">
+    Универсальная Страница для загрузки документов.
+</p>
+
+<form class="d-flex flex-column align-items-end" enctype="multipart/form-data" method="POST">
+    {% csrf_token %}
+    <div class="w-100">
+        <label for="{{ form.doc_expire_date.id_for_label }}" class="form-label">{{ form.doc_expire_date.label }}</label>
+        {{ form.doc_expire_date }}
+        
+        {% if form.doc_expire_date.errors %}
+            <ul class="alert alert-danger list-style-none mt-2 p-3">
+                {% for error in form.doc_expire_date.errors %}
+                    <li>{{ error }}</li>
+                {% endfor %}
+            </ul>
+        {% endif %}
+    </div>
+
+    <div class="my-3 w-100">
+        <div class="drop-container" id="doc-drop-container">
+            <span class="drop-title">Перетащите файлы сюда</span>
+            или выберите их на своем устройстве (только PDF, PNG, JPG или JPEG)
+            {{ form.doc_file }}
+        </div>
+
+        {% if form.doc_file.errors %}
+            <ul class="alert alert-danger list-style-none mt-2 p-3">
+                {% for error in form.doc_file.errors %}
+                    <li>{{ error }}</li>
+                {% endfor %}
+            </ul>
+        {% endif %}
+    </div>
+    
+    <button class="btn btn-primary" type="button" data-bs-toggle="modal" data-bs-target="#doc-modal">Отправить</button>
+
+    <!-- Окно подтверждения -->
+    <div id="doc-modal" class="modal fade" tabindex="-1">
+        <div class="modal-dialog modal-dialog-centered">
+          <div class="modal-content">
+            <div class="modal-header">
+              <h5 class="modal-title">Подтверждение действия</h5>
+              <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+            </div>
+            <div class="modal-body">
+              <p>Загрузка новых файлов документа полностью заменит все ранее загружаемые для него файлы, а также приведет к деактивации партнера до момента проверки новой информации!</p>
+            </div>
+            <div class="modal-footer">
+              <button type="button" class="btn btn-primary" data-bs-dismiss="modal">Отменить</button>
+              <button type="sumbit" class="btn btn-outline-primary" data-bs-dismiss="modal">Подтвердить</button>
+            </div>
+          </div>
+        </div>
+    </div>
+</form>
+
+<script>
+    document.addEventListener("DOMContentLoaded", function() {
+        // Настройка работы поля для загрузки файлов #doc-file-input
+        const dropContainer = document.getElementById('doc-drop-container');
+        const fileInput = document.getElementById('doc-file-input');
+
+        // Открытие окна выбора файлов при клике на контейнер
+        dropContainer.addEventListener('click', function() {
+            fileInput.click();
+        });
+
+        // Отмена стандартного поведения при перетаскивании файлов
+        dropContainer.addEventListener('dragover', function(e) {
+            e.preventDefault();
+        });
+
+        // Обработка события перетаскивания файлов
+        dropContainer.addEventListener('drop', function(e) {
+            e.preventDefault();
+            fileInput.files = e.dataTransfer.files;
+        });
+    });
+</script>
+{% endblock %}

+ 3 - 5
sharix_admin/templates/sharix_admin/partner_edit.html

@@ -2,20 +2,18 @@
 {% load static %}
 
 {% block view %}
-<a class="display-block btn btn-sm btn-outline-secondary" href="{% url 'sharix_admin:partner_detail' %}"><< Назад</a>
 
 <p class="description_service">
-    Это система управления государством, источником власти в которой является сам народ. Именно народ решает, какие законы и нормы необходимы для гармоничного существования и развития государства. Таким образом, каждый человек в демократическом обществе 
-    Получает определенный набор свобод и обязательств сформированных с учетом интересов всего сообщества. Исходя из вышесказанного, можно заключить, что демократия – это возможность для каждого человека свободно участвовать в непосредственном управлении своим государством, обществом и личной судьбой в конечном счете
+    Страница изменения данных о компании-партнере. Некоторые из внесенных изменений могут потребовать повторную активацию!
 </p>
 
 <form method="post" class="d-flex flex-column align-items-end">
     {% csrf_token %}
     {% include 'sharix_admin/include/form.html' %}
-    <button class="btn btn-primary" type="button" data-bs-toggle="modal" data-bs-target="#partner-edit-modal">Отправить</button>
+    <button class="btn btn-primary" type="button" data-bs-toggle="modal" data-bs-target="#edit-modal">Отправить</button>
 
     <!-- Окно подтверждения -->
-    <div id="partner-edit-modal" class="modal fade" tabindex="-1">
+    <div id="edit-modal" class="modal fade" tabindex="-1">
         <div class="modal-dialog modal-dialog-centered">
           <div class="modal-content">
             <div class="modal-header">

+ 1 - 1
sharix_admin/templates/sharix_admin/partners.html

@@ -33,7 +33,7 @@
     // Запрос на изменения статуса партнера
     $('.status-toggle').change(function() {
       var partners_id = $(this).data('partners-id');
-      var new_status = $(this).prop('checked') ? 'active' : 'deactivated';
+      var new_status = $(this).prop('checked') ? '0' : '1';
       $.ajax({
         url: '{% url "sharix_admin:partner/change_status" %}',
         type: 'POST',

+ 1 - 1
sharix_admin/templates/sharix_admin/providers.html

@@ -40,7 +40,7 @@
       // Запрос на изменения статуса исполнителя
       $('.status-toggle').change(function() {
         var provider_id = $(this).data('provider-id');
-        var new_status = $(this).prop('checked') ? 'active' : 'deactivated';
+        var new_status = $(this).prop('checked') ? '0' : '1';
         $.ajax({
           url: '{% url "sharix_admin:provider/change_status" %}',
           type: 'POST',

+ 28 - 0
sharix_admin/templates/sharix_admin/resource.html

@@ -6,4 +6,32 @@
     {% include 'sharix_admin/include/form.html' %}
     <button class="btn btn-primary" type="submit">Отправить</button>
 </form>
+
+
+<h6 class="mb-4">Документы</h6>
+    <ul class="list-style-none">
+        {% for doc in docs %}
+            <li class="d-flex justify-content-between">
+                <div class="d-flex align-items-center">
+                    {% if doc.ticket_status and doc.status == "deactivated" %}
+                        <i class="fa-solid fa-clock-rotate-left me-2 no-user-select fs-4 text-warning"></i>
+                    {% elif doc.status == "activated" %}
+                        <i class="fa-solid fa-check me-2 no-user-select fs-4 text-success"></i>
+                    {% else %}
+                        <i class="fa-regular fa-file me-2 no-user-select fs-4 text-primary"></i>
+                    {% endif %}
+
+                    {{ doc.get_doc_type_display }}
+                </div>
+                
+                {% if doc.ticket_status %}
+                    <a class="btn btn-sm btn-outline-primary" href="{% url "sharix_admin:resource_doc" doc.doc_type %}">Посмотреть</a>
+                {% else %}
+                    <a class="btn btn-sm btn-primary" href="{% url "sharix_admin:resource_doc_upload" doc.doc_type %}">Загрузить</a>
+                {% endif %}
+            </li>
+        {% endfor %}
+    </ul>
+
+
 {% endblock %}

+ 4 - 4
sharix_admin/templates/sharix_admin/resource_list.html → sharix_admin/templates/sharix_admin/resources.html

@@ -49,17 +49,17 @@
           </div>     
       </div>
 
-
+<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
     <script>
       // Запрос на изменения статуса ресурса
       $('.status-toggle').change(function() {
-        var resource = $(this).data('resource-id');
-        var new_status = $(this).prop('checked') ? 'active' : 'deactivated';
+        var resource_id = $(this).data('resource-id');
+        var new_status = $(this).prop('checked') ? '0' : '1';
         $.ajax({
           url: '{% url "sharix_admin:resource/change_status" %}',
           type: 'POST',
           data: {
-            'resource': resource,
+            'resource_id': resource_id,
             'new_status': new_status,
             'csrfmiddlewaretoken': '{{ csrf_token }}'
           },

+ 3 - 2
sharix_admin/templates/sharix_admin/service_categories.html

@@ -50,17 +50,18 @@
           </div>     
       </div>
 
+<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
 <script>
 
 // Запрос на изменения статуса категории сервиса
       $('.status-toggle').change(function() {
-        var service_category = $(this).data('service_category-id');
+        var service_category_id = $(this).data('service_category-id');
         var new_status = $(this).prop('checked') ? '0' : '1';
         $.ajax({
           url: '{% url "sharix_admin:service_category/change_status" %}',
           type: 'POST',
           data: {
-            'service_category': service_category,
+            'service_category_id': service_category_id,
             'new_status': new_status,
             'csrfmiddlewaretoken': '{{ csrf_token }}'
           },

+ 4 - 2
sharix_admin/templates/sharix_admin/service_tariffs.html

@@ -72,17 +72,19 @@
           {% endif %} {% endcomment %}
     </div>
 
+    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
+
 <script>
 
 // Запрос на изменения статуса тарифа сервиса
       $('.status-toggle').change(function() {
-        var service = $(this).data('service-id');
+        var service_id = $(this).data('service-id');
         var new_status = $(this).prop('checked') ? '0' : '1';
         $.ajax({
           url: '{% url "sharix_admin:service_tariff/change_status" %}',
           type: 'POST',
           data: {
-            'service': service,
+            'service_id': service_id,
             'new_status': new_status,
             'csrfmiddlewaretoken': '{{ csrf_token }}'
           },

+ 7 - 3
sharix_admin/templates/sharix_admin/staff/access_control.html

@@ -53,16 +53,20 @@
 </form>
 {% endcomment %}
 
+<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
+
+
 <script>
+
 // Запрос на изменения статуса категории сервиса
       $('.status-toggle').change(function() {
-        var service_category = $(this).data('service_category-id');
+        var permissions_id = $(this).data('permissions-id');
         var new_status = $(this).prop('checked') ? '0' : '1';
         $.ajax({
-          url: '{% url "sharix_admin:service_category/change_status" %}',
+          url: '{% url "sharix_admin:permissions/change_status" %}',
           type: 'POST',
           data: {
-            'service_category': service_category,
+            'permissions_id': permissions_id,
             'new_status': new_status,
             'csrfmiddlewaretoken': '{{ csrf_token }}'
           },

+ 88 - 0
sharix_admin/templates/sharix_admin/staff/relationship.html

@@ -0,0 +1,88 @@
+{% extends 'sharix_admin/base_admin.html' %}
+{% load i18n %}
+
+{% load render_table from django_tables2 %}
+{% load static %}
+
+{% block view %}
+{% block contenthome %}
+<p>
+Список взаимоотношений внутри сервиса в целом.
+</p>
+
+<div class="dropdown mb-3">
+        <button class="btn btn-secondary dropdown-toggle" type="button" id="howToUseDropdown" data-bs-toggle="dropdown" aria-expanded="false">
+            Как пользоваться?
+        </button>
+        <div class="dropdown-menu" aria-labelledby="howToUseDropdown">
+            <p class="dropdown-item-text custom-dropdown-text">
+	    Активация происходит через заявки, отправленные на платформу, или, если Сервис не подключен к платформе - вручную.
+	    </p>
+        </div>
+</div>
+
+    <div class="mb-3 d-flex justify-content-between align-items-center">
+      <form method="get" action="" class="d-flex align-items-center">
+          <input type="text" name="q" class="form-control" placeholder="Поиск" value="{{ request.GET.q }}" style="width: 300px; height: 38px;">
+          <button type="submit" class="btn btn-primary ms-2" style="height: 38px;">Поиск</button>
+      </form>
+      </div>
+
+    <div class="row justify-content-start">
+          <div class="maintable" id="maintable">
+            {% render_table table %}
+          </div>     
+      </div>
+
+{% comment %}
+<form method="post" style="overflow: auto">
+    {% csrf_token %}
+    <div class="container m-2">
+        {% for field in form %}
+        {{field.errors}}
+        <div class="row">
+            {{field.label_tag}}
+            {{field}}
+            <p class="fs-6 fst-italic">{{field.help_text|truncatewords:20}}</p>
+        </div>
+        {% endfor %}
+    </div>
+    <div class="text-center mt-2 mb-5">
+        <input class="btn btn-primary center" type="submit" name="apply" value="{% trans 'Submit' %}" />
+    </div>
+</form>
+{% endcomment %}
+
+<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
+
+
+<script>
+// Запрос на изменения статуса категории сервиса
+      $('.status-toggle').change(function() {
+        var relationship_id = $(this).data('relationship-id');
+        var new_status = $(this).prop('checked') ? '0' : '1';
+        $.ajax({
+          url: '{% url "sharix_admin:relationship/change_status" %}',
+          type: 'POST',
+          data: {
+            'relationship_id': relationship_id,
+            'new_status': new_status,
+            'csrfmiddlewaretoken': '{{ csrf_token }}'
+          },
+          success: function(response) {
+            var scrollTop = window.pageYOffset;
+            location.reload();
+            window.scrollTo(0, scrollTop);
+          },
+          error: function(xhr, status, error) {
+            console.log(xhr.responseText);
+          }
+        });
+      });
+
+</script>
+
+{% endblock contenthome %}
+{% endblock view %}
+
+

+ 3 - 4
sharix_admin/urls.py

@@ -55,9 +55,8 @@ urlpatterns = [
     path('resource/<int:pk>', login_required(ResourceDetailView.as_view()), name='resource_detail'),
     path('resource/add/', login_required(ResourceCreate.as_view()), name='resource/add/'),
     path('resource/edit/<int:pk>', login_required(ResourceEditView.as_view()), name='resource/edit/'),
-    # path('resource/doc/<str:doc_code>/upload', login_required(ResourceDocUploadView.as_view()),
-    #      name='partner_doc_upload'),
-    # path('resource/doc/<str:doc_code>', login_required(ResourceDocView.as_view()), name='resource_doc'),
+    path('resource/doc/<str:doc_code>/upload', login_required(ResourceDocUploadView.as_view()), name='resource_doc_upload'),
+    path('resource/doc/<str:doc_code>', login_required(ResourceDocView.as_view()), name='resource_doc'),
     path('resource/change_status/', change_resource_status, name='resource/change_status'),
 
     path('providers/', login_required(ProvidersListView.as_view()), name='providers'),
@@ -94,7 +93,7 @@ urlpatterns = [
 
 #TODO - take from platform
     path('access-control', login_required(AccessControlListView.as_view()), name='access_control'),
-    path('access_control/change_status/', change_permissions_status, name='access_control/change_status'),
+    path('access_control/change_status/', change_permissions_status, name='permissions/change_status'),
     path('relationship', login_required(RelationshipListView.as_view()), name='relationship'),    
     path('relationship/change_status/', change_relationship_status, name='relationship/change_status'),
 #    path('active_users', login_required(ActiveUsersListView.as_view()), name='active_users'),

+ 14 - 5
sharix_admin/views/partner.py

@@ -1,10 +1,16 @@
 from dbsynce.models import Company, Documents, DocumentFile
+
+from django.http import JsonResponse
+from django.http import Http404
+from django.shortcuts import render
+
+from dbsynce.lib.ticket_gen import *
 from django.contrib import messages
 from django.core.files.storage import default_storage
 from django.db import transaction
 from django.shortcuts import get_object_or_404, redirect
 from django.urls import reverse_lazy
-from django.views.generic import DetailView
+from django.views.generic import DetailView, UpdateView
 from django.views.generic.edit import FormView
 
 from sharix_admin.forms import CompanyForm, DocumentUploadForm
@@ -94,15 +100,18 @@ class MyPartnerDetailView(MyPartnerBaseView, DetailView):
         return context
 
 
-class PartnerEditView(MyPartnerBaseView, FormView):
+class PartnerEditView(MyPartnerBaseView, UpdateView):
     template_name = 'sharix_admin/partner_edit.html'
     form_class = CompanyForm
+    model = Company
     success_url = reverse_lazy('partner_detail')
     page_title = 'Изменение данных партнера'
 
     def get_form_kwargs(self):
         kwargs = super().get_form_kwargs()
-        kwargs['instance'] = get_object_or_404(Company, repr=self.request.user)
+        #docs = Documents.objects.filter(resource=self.object.id)
+        #kwargs['instance'] = get_object_or_404(Company, repr=self.request.user)
+        kwargs['instance'] = get_object_or_404(Company, id=self.object.id)
         return kwargs
 
     def form_valid(self, form):
@@ -258,8 +267,8 @@ class PartnersListView(BaseView, UserPassesTestMixin, SingleTableView):
     #    return False
         return True
 
-@login_required
-@group_required('METASERVICE-ADMIN')
+#@login_required
+#@group_required('METASERVICE-ADMIN')
 def change_partner_status(request):
     if request.method == 'POST':
         partners_id = request.POST.get('partners_id')

+ 2 - 2
sharix_admin/views/provider.py

@@ -126,8 +126,8 @@ class ProvidersListView(BaseView, UserPassesTestMixin, SingleTableView):
     #    return False
         return True
 
-@login_required
-@group_required('PARTNER-ADMIN')
+#@login_required
+#@group_required('PARTNER-ADMIN')
 def change_provider_status(request):
     if request.method == 'POST':
         provider_id = request.POST.get('provider_id')

+ 129 - 11
sharix_admin/views/resource.py

@@ -1,4 +1,9 @@
 from dbsynce.models import Resource
+
+from django.http import JsonResponse
+from django.http import Http404
+from django.shortcuts import render
+
 from django.contrib.auth.decorators import login_required
 from django.contrib.auth.mixins import UserPassesTestMixin
 from django.http import JsonResponse
@@ -17,6 +22,7 @@ from django.contrib import messages
 from django.db import transaction
 from django.urls import reverse_lazy
 from django.views.generic.edit import FormView
+from django.views.generic.edit import UpdateView
 from tickets.models import Ticket, TicketList
 
 from sharix_admin.forms import ResourceForm
@@ -25,13 +31,18 @@ from dbsynce.lib.data import *
 from .base import BaseView
 from django.db.models import Q
 
+from dbsynce.models import Documents, DocumentFile
+from sharix_admin.forms import DocumentUploadForm
+from django.shortcuts import get_object_or_404, redirect
+from django.core.files.storage import default_storage
+
 from dbsynce.docs.database.resource import Resource as ResourceHelpTexts
 from dbsynce.docs.verbose_names.resource import Resource as ResourceVerboseNames
 
 class ResourcesListView(BaseView, UserPassesTestMixin, SingleTableView):
     table_class = ResourcesTable
     queryset = Resource.objects.all()
-    template_name = 'sharix_admin/resource_list.html'
+    template_name = 'sharix_admin/resources.html'
     page_title = 'Ресурсы'
     page_name = 'resources'
 
@@ -63,27 +74,45 @@ class ResourcesListView(BaseView, UserPassesTestMixin, SingleTableView):
         return True
 
 
-@login_required
-@group_required('PARTNER-ADMIN')
+#@login_required
+#@group_required('PARTNER-ADMIN')
 def change_resource_status(request):
     if request.method == 'POST':
-        resource = request.POST.get('resource')
+        resource_id = request.POST.get('resource_id')
         new_status = request.POST.get('new_status')
 
-        resource = Resource.objects.get(pk=resource)
+        resource = Resource.objects.get(pk=resource_id)
         resource.status = new_status
         resource.save()
         return JsonResponse({'status': 'success'})
     else:
         return JsonResponse({'status': 'error'})
 
-class ResourceEditView(BaseView, FormView):
+#class ResourceEditView(BaseView, FormView):
+class ResourceEditView(BaseView, UpdateView):
     form_class = ResourceForm
+    model = Resource
     template_name = "sharix_admin/resource.html"
-    success_url = reverse_lazy("sharix_admin:resource_list")
+    success_url = reverse_lazy("sharix_admin:resources")
     page_title = 'Изменить ресурс'
     page_name = 'resource_edit'
 
+    def get_context_data(self, **kwargs):
+        context = super().get_context_data(**kwargs)
+
+        try:
+            docs = Documents.objects.filter(resource=self.object.id)
+        except Documents.DoesNotExist:
+            docs=[]
+
+        context.update({
+            'title': self.page_title,
+            'object': self.object,
+            "current_page": "sharix_admin:resources",
+        })
+        context['docs'] = docs
+        return context
+
     # Проверяем состояит ли текущий пользователь в группе PARTNER-ADMIN
     def test_func(self):
         return "PARTNER-ADMIN" in self.user_groups
@@ -114,7 +143,7 @@ class ResourceEditView(BaseView, FormView):
             doc_codes = parse_requirements(instance.requirements)
             Documents.objects.bulk_create([
                 Documents(
-                    company=instance,
+                    resource=instance,
                     user=self.request.user,
                     doc_type=doc_code
                 ) for doc_code in doc_codes
@@ -187,13 +216,13 @@ class ResourceDetailView(BaseView, DetailView):
     page_title = 'О ресурсе'
     page_name = 'resource_detail'
 
-    def detail_view(request, primary_key):
+    def detail_view(self, request, primary_key):
         try:
             resource = Resource.objects.get(pk=primary_key)
         except Resource.DoesNotExist:
             raise Http404('Provider does not exist')
 
-        return render(request, template_name, context={
+        return render(request, self.template_name, context={
             'help_texts': ResourceHelpTexts,
             'captions': ResourceVerboseNames,
             })
@@ -201,6 +230,95 @@ class ResourceDetailView(BaseView, DetailView):
     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
         context['help_texts'] = ResourceHelpTexts
-        context['captions'] = ResourceVerboseNames
+        context['captions'] = ResourceVerboseNames  
         return context
+    
+
+class ResourceDocUploadView(BaseView, FormView):
+    # FIXME: Загрузка новых документов должна деактивировать текущего партнера (предварительно это работа обработчиков)
+    template_name = 'sharix_admin/include/doc_upload.html'
+    form_class = DocumentUploadForm
+    success_url = reverse_lazy('partner_detail')
+
+    def dispatch(self, request, *args, **kwargs):
+        self.company = get_object_or_404(Resource, repr=self.request.user)
+        self.doc = Documents.objects.filter(
+            user=self.request.user,
+            resource=self.resource,
+            doc_type=kwargs.get('doc_code')
+        ).first()
+
+        self.doc_name = self.doc.get_doc_type_display()
+        self.page_title = "Изменение документа ресурса: " + self.doc_name
+
+        return super().dispatch(request, *args, **kwargs)
+
+    def form_valid(self, form):
+        with transaction.atomic():
+            # Удаляем существующие файлы и записи из базы данных
+            existing_files = DocumentFile.objects.filter(document=self.doc)
+            for existing_file in existing_files:
+                # Удаляем файл с сервера
+                if default_storage.exists(existing_file.file.path):
+                    default_storage.delete(existing_file.file.path)
+
+                # Удаляем запись о файле из базы данных
+                existing_file.delete()
+
+            # Загрузка новых файлов
+            doc_file = self.request.FILES.getlist("doc_file")
+            for file in doc_file:
+                DocumentFile.objects.create(
+                    document=self.doc,
+                    file=file
+                )
+
+            # Создание нового тикета и архивация старого
+            if self.doc.ticket_status:
+                self.doc.ticket_status.archive()
+
+            self.doc.expire_date = self.request.POST.get('doc_expire_date') if self.request.POST[
+                'doc_expire_date'] else None
+            self.doc.ticket_status = create_ticket_company_docs_verification(self.request.user, self.company, self.doc)
+
+            self.doc.save()
+
+        # Отправляем пользователю уведомление на страницу об успехе операции
+        messages.success(self.request,
+                         f'Файлы документа "{self.doc_name}" успешно загружены и теперь проходят проверку!')
+        return super().form_valid(form)
+
+
+class ResourceDocView(BaseView, DetailView):
+#class PartnerDocView(PartnerBaseView, DetailView):
+    model = Documents
+    template_name = 'sharix_admin/include/doc.html'
+    context_object_name = 'doc'
+
+    def dispatch(self, request, *args, **kwargs):
+        self.company = get_object_or_404(Resource, repr=self.request.user)
+
+        self.doc = Documents.objects.filter(
+            user=self.request.user,
+            resource=self.resource,
+            doc_type=kwargs.get('doc_code')
+        ).first()
+
+        if not self.doc:
+            return self.handle_no_permission()
+
+        self.doc_name = self.doc.get_doc_type_display()
+        self.page_title = _("Детали документа: ") + self.doc_name
+
+        return super().dispatch(request, *args, **kwargs)
+
+    def get_object(self, queryset=None):
+        return self.doc
+
+    def get_context_data(self, **kwargs):
+        context = super().get_context_data(**kwargs)
+        doc_files = DocumentFile.objects.filter(document=self.doc)
+        context.update({"doc_files": doc_files})
+        return context
+
 

+ 22 - 8
sharix_admin/views/service.py

@@ -1,16 +1,27 @@
 from dbsynce.models import Service
 from django.contrib.auth.decorators import login_required
+
+from django.http import JsonResponse
+from django.http import Http404
+from django.shortcuts import render
+
 from django.contrib.auth.mixins import UserPassesTestMixin
 from django.utils.translation import gettext as _
 from django_tables2 import SingleTableView
 from django.views.generic import DetailView
 
-from sharix_admin.tables import ServiceTable
+#from sharix_admin.tables import ServiceTable
 from sharix_admin.utils import group_required
 
+from dbsynce.models import Documents, DocumentFile
+from sharix_admin.forms import DocumentUploadForm
+from django.shortcuts import get_object_or_404, redirect
+from django.core.files.storage import default_storage
+
 from django.views.generic.edit import UpdateView, CreateView, DeleteView
 from sharix_admin.forms import ServiceTariffCreateForm, ServiceTariffUpdateForm
 from sharix_admin.tables import ServiceTariffsTable
+from sharix_admin.tables import ProvidersTable
 from .base import BaseView
 
 from sharix_admin.utils import group_required
@@ -94,7 +105,7 @@ class ServiceTariffCreate(BaseView, FormView):
 #class ServiceListView(UserPassesTestMixin, SingleTableView):
 class ServiceTariffsListView(BaseView, SingleTableView):
     page_title = _('Тарифы сервиса')
-    page_name = 'service_tariff'
+    page_name = 'service_tariffs'
     table_class = ServiceTariffsTable
     queryset = Service.objects.all()
     template_name = 'sharix_admin/service_tariffs.html'
@@ -202,7 +213,7 @@ class ServiceTariffUpdateView(BaseView, UpdateView):
 
 class ServiceTariffsMyListView(BaseView, SingleTableView):
 #class ServiceListView(UserPassesTestMixin, SingleTableView):
-    table_class = ServiceTable
+    table_class = ServiceTariffsTable
     #TODO change to concrete company
     #queryset = Service.objects.all()
     template_name = 'sharix_admin/service.html'
@@ -222,8 +233,8 @@ class ServiceTariffsMyListView(BaseView, SingleTableView):
         return False
 
 
-@login_required
-@group_required('METASERVICE_SUPERVISOR')
+#@login_required
+#@group_required('METASERVICE_SUPERVISOR')
 def change_service_status(request):
     if request.method == 'POST':
         service_id = request.POST.get('service_id')
@@ -232,21 +243,24 @@ def change_service_status(request):
         service = Service.objects.get(pk=service_id)
         service.status = new_status
         service.save()
+        return JsonResponse({'status': 'success'})
+    else:
+        return JsonResponse({'status': 'error'})
 
 class ServiceTariffDetailView(BaseView, DetailView):
     model = Service
     template_name = 'sharix_admin/service_detail.html'
     context_object_name = 'service'
     page_title = 'О тарифе'
-    page_name = 'service_detail'
+    page_name = 'service_tariff_detail'
 
-    def detail_view(request, primary_key):
+    def detail_view(self, request, primary_key):
         try:
             service = Service.objects.get(pk=primary_key)
         except Service.DoesNotExist:
             raise Http404('Service does not exist')
 
-        return render(request, template_name, context={
+        return render(request, self.template_name, context={
             'help_texts': ServiceHelpTexts,
             'captions': ServiceVerboseNames,
             })

+ 12 - 6
sharix_admin/views/service_category.py

@@ -1,5 +1,9 @@
 from dbsynce.models import ServiceCategory
 from django.urls import reverse
+from django.http import JsonResponse
+from django.http import Http404
+from django.shortcuts import render
+
 from django.utils.translation import gettext as _
 from django.views.generic.edit import UpdateView, CreateView, DeleteView
 from django_tables2 import SingleTableView
@@ -236,19 +240,21 @@ class ServiceCategoryUpdateView(BaseView, UpdateView):
 #            return True
 #        return False
 
-@login_required
-@group_required('METASERVICE-ADMIN')
+#@login_required
+#@group_required('METASERVICE-ADMIN')
 def change_service_category_status(request):
     if request.method == 'POST':
-        service_category = request.POST.get('resource')
+        service_category_id = request.POST.get('service_category_id')
         new_status = request.POST.get('new_status')
 
-        service_category = ServiceCategory.objects.get(pk=service_category)
+        service_category = ServiceCategory.objects.get(pk=service_category_id)
         service_category.status = new_status
         service_category.save()
         return JsonResponse({'status': 'success'})
     else:
         return JsonResponse({'status': 'error'})
+    
+
 
 class ServiceCategoryDetailView(BaseView, DetailView):
     model = ServiceCategory
@@ -257,13 +263,13 @@ class ServiceCategoryDetailView(BaseView, DetailView):
     page_title = 'О категории услуг'
     page_name = 'service_category_detail'
 
-    def detail_view(request, primary_key):
+    def detail_view(self, request, primary_key):
         try:
             service_category = ServiceCategory.objects.get(pk=primary_key)
         except ServiceCategory.DoesNotExist:
             raise Http404('ServiceCategory does not exist')
 
-        return render(request, template_name, context={
+        return render(request, self.template_name, context={
             'help_texts': ServiceCategoryHelpTexts,
             'captions': ServiceCategoryVerboseNames,
             })

+ 9 - 9
sharix_admin/views/staff.py

@@ -63,7 +63,7 @@ class RelationshipListView(BaseView, SingleTableView):
     page_name = 'relationship'
     table_class = RelationshipTable
     queryset = Relationship.objects.all()
-    template_name = 'sharix_admin/staff/access_control.html'
+    template_name = 'sharix_admin/staff/relationship.html'
 
     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
@@ -91,13 +91,13 @@ class RelationshipListView(BaseView, SingleTableView):
         return False
 
 
-@login_required
-@group_required('PLATFORM-ADMIN')
+#@login_required
+#@group_required('PLATFORM-ADMIN')
 def change_relationship_status(request):
     if request.method == 'POST':
-        relationship_id = request.POST.get('relationship')
+        relationship_id = request.POST.get('relationship_id')
         new_status = request.POST.get('new_status')
-        relationship = Relationship.objects.get(pk=relationship)
+        relationship = Relationship.objects.get(pk=relationship_id)
         relationship.status = new_status
         relationship.save()
         return JsonResponse({'status': 'success'})
@@ -105,13 +105,13 @@ def change_relationship_status(request):
         return JsonResponse({'status': 'error'})
 
 
-@login_required
-@group_required('PLATFORM-ADMIN')
+#@login_required
+#@group_required('PLATFORM-ADMIN')
 def change_permissions_status(request):
     if request.method == 'POST':
-        permissions_id = request.POST.get('permissions')
+        permissions_id = request.POST.get('permissions_id')
         new_status = request.POST.get('new_status')
-        permissions = Permissions.objects.get(pk=permissions)
+        permissions = Permissions.objects.get(pk=permissions_id)
         permissions.status = new_status
         permissions.save()
         return JsonResponse({'status': 'success'})