Browse Source

fixed service_category pages for correct operating

ShariX Developer 18 hours ago
parent
commit
e5d00864b8

+ 38 - 26
sharix_admin/forms/service.py

@@ -1,6 +1,6 @@
 from dbsynce.models import ServiceCategory, Service, Company
 from django import forms
-
+from sharix_admin.forms import BaseForm
 
 class ServiceTariffUpdateForm(forms.ModelForm):
     def __init__(self, *args, **kwargs):
@@ -55,45 +55,54 @@ class ServiceTariffCreateForm(forms.ModelForm):
             'ticket_status': forms.TextInput(attrs={'readonly': True}),
         }
 
+#TODO Merge with dicts!
+PRICE_CHOICES = [
+    ('1', 'Только время'),
+    ('2', 'Только расстояние'),
+    ('3', 'За единицу услуги'),
+    ('4', 'Время за расстояние'),
+    ('5', 'Единицы за расстояние'),
+    ('6', 'Единицы за время'),
+]
+
+
+class ServiceCategoryUpdateForm(BaseForm, forms.ModelForm):
+    price_type = forms.ChoiceField(choices=PRICE_CHOICES, label="Ценообразование")
 
-class ServiceCategoryUpdateForm(forms.ModelForm):
     def __init__(self, *args, **kwargs):
         super(ServiceCategoryUpdateForm, self).__init__(*args, **kwargs)
 
     class Meta:
         model = ServiceCategory
         fields = [
-            'status',
-            'ticket_status',
-            'id_metaservice',
+            #'status',
+            #'ticket_status',
+            #'id_metaservice',
             'codename',
+            'caption',
             'description',
-            'requirements',
+            #'requirements',
             'price_type',
             'link_agreement',
             'is_global',
             'is_visible'
         ]
-        widgets = {
-            'status': forms.TextInput(attrs={'readonly': True}),
-            'ticket_status': forms.TextInput(attrs={'readonly': True}),
-        }
-
+        #widgets = {
+        #    'status': forms.TextInput(attrs={'readonly': True}),
+        #    'ticket_status': forms.TextInput(attrs={'readonly': True}),
+        #}
 
-PRICE_CHOICES = [
-    ('one', 'text #1'),
-    ('two', 'text #2'),
-    ('three', 'text #3'),
-]
 
-
-class ServiceCategoryCreateForm(forms.ModelForm):
-    codename = forms.CharField(label="Название услуги")
-    requirements = forms.CharField(label="Требования")
+class ServiceCategoryCreateForm(BaseForm, forms.ModelForm):
+    codename = forms.CharField(label="Кодовое короткое название услуги")
+    caption = forms.CharField(label="Название услуги")
+    #requirements = forms.CharField(label="Требования")
     price_type = forms.ChoiceField(choices=PRICE_CHOICES, label="Ценообразование")
     description = forms.CharField(label="Описание")
-    is_global = forms.BooleanField(label="Доступно во всех сервисах", required=False)
-    is_visible = forms.BooleanField(label="Доступно для планирования цепочек во всех сервисах", required=False)
+    link_agreement = forms.CharField(label="Ссылка на договор-оферту")
+    metaservice_comission = forms.FloatField(label="Комиссия Сервиса")
+#    is_global = forms.BooleanField(label="Доступно во всех сервисах", required=False)
+#    is_visible = forms.BooleanField(label="Доступно для планирования цепочек во всех сервисах", required=False)
 
     def __init__(self, *args, **kwargs):
         super(ServiceCategoryCreateForm, self).__init__(*args, **kwargs)
@@ -102,11 +111,14 @@ class ServiceCategoryCreateForm(forms.ModelForm):
         model = ServiceCategory
         fields = [
             'codename',
-            'requirements',
+            'caption',
+            #'requirements',
             'price_type',
             'description',
-            'is_global',
-            'is_visible',
+            'link_agreement',
+            'metaservice_comission',
+ #           'is_global',
+ #           'is_visible',
         ]
 
         widgets = {
@@ -114,7 +126,7 @@ class ServiceCategoryCreateForm(forms.ModelForm):
         }
 
 
-class ServiceInformationUpdateForm(forms.ModelForm):
+class ServiceInformationUpdateForm(BaseForm, forms.ModelForm):
 
     def __init__(self, *args, **kwargs):
         super(ServiceInformationUpdateForm, self).__init__(*args, **kwargs)

+ 57 - 9
sharix_admin/tables.py

@@ -325,11 +325,12 @@ class ServiceTariffsTable(tables.Table):
 
 class ServiceCategoriesTable(tables.Table):
     id = tables.Column(attrs={"td": {"width": "50px"}})
-    codename = tables.LinkColumn(
+
+    caption = tables.LinkColumn(
         'sharix_admin:service_category/edit/',
         verbose_name='Услуга',
         orderable=False,
-        text=lambda record: record.codename,
+        text=lambda record: record.caption,
         args=[tables.A('pk')],
         attrs={
             "a": {"style": "pointer-events: none;"},
@@ -337,6 +338,19 @@ class ServiceCategoriesTable(tables.Table):
             "td": {"class": "name_col"}
         }
     )
+
+    #codename = tables.LinkColumn(
+    #    'sharix_admin:service_category/edit/',
+    #    verbose_name='Тех.название',
+    #    orderable=False,
+    #    text=lambda record: record.codename,
+    #    args=[tables.A('pk')],
+    #    attrs={
+    #        "a": {"style": "pointer-events: none;"},
+    #        'th': {'scope': 'col'},
+    #        "td": {"class": "name_col"}
+    #    }
+    #)
     description = tables.LinkColumn(
         'sharix_admin:service_category/edit/',
         orderable=False, verbose_name='Описание',
@@ -348,6 +362,14 @@ class ServiceCategoriesTable(tables.Table):
             "td": {"class": "description_col"}
         }
     )
+
+    metaservice_comission = tables.Column(
+        verbose_name=_('Комиссия Сервиса'),
+        attrs={
+            'th': {'scope': 'col'},
+            "td": {"width": "15%"}}
+    )
+
     edit = tables.LinkColumn(
         'sharix_admin:service_category/edit/',
         verbose_name='',
@@ -359,17 +381,27 @@ class ServiceCategoriesTable(tables.Table):
             "td": {"class": "edit_col"}
         }
     )
-    deletee = tables.LinkColumn(
-        'sharix_admin:service_category/delete/',
-        verbose_name='',
+    
+    check = tables.BooleanColumn(
+        verbose_name=_('Activity'),
         orderable=False,
-        text="D",
-        args=[tables.A('pk')],
         attrs={
             'th': {'scope': 'col'},
-            "td": {"class": "delete_col"}
+            "td": {"width": "5%"}
         }
     )
+    #TODO change to 'change status!'
+    #deletee = tables.LinkColumn(
+    #    'sharix_admin:service_category/delete/',
+    #    verbose_name='',
+    #    orderable=False,
+    #    text="D",
+    #    args=[tables.A('pk')],
+    #    attrs={
+    #        'th': {'scope': 'col'},
+    #        "td": {"class": "delete_col"}
+    #    }
+    #)
 
     class Meta:
         model = ServiceCategory
@@ -385,9 +417,25 @@ class ServiceCategoriesTable(tables.Table):
             'link_agreement',
             'is_global',
             'is_visible',
-            'caption'
+            'codename',
         )
 
+    def render_check(self, value, record):
+        if record.status == '0':
+            #if record.status == 'active':
+            return format_html(
+                '<input class="form-check-input status-toggle" checked type="checkbox" id="flexCheckDefault" data-service_category-id="{}">',
+                record.id
+            )
+            #return format_html('<input class="form-check-input status-toggle" checked type="checkbox" id="flexCheckDefault" data-service_category-id="{}">')
+            #return format_html('<input class="form-check-input status-toggle" disabled  checked type="checkbox"')
+        else:
+            return format_html(
+                '<input class="form-check-input status-toggle" type="checkbox" id="flexCheckDefault" data-service_category-id="{}">',
+                record.id
+            )
+            #return format_html('<input class="form-check-input status-toggle" disabled  type="checkbox"')
+
     # def render_delete(self, value, record):
     #     return format_html('<a href="/service_category/delete" class="btn btn-outline-danger">_(Delete)</a>')
 

+ 57 - 6
sharix_admin/templates/sharix_admin/service_categories.html

@@ -15,17 +15,68 @@
   }
 </style>
 
-<p class="description_service">Это система управления государством, источником власти в которой является сам народ. Именно народ решает, какие законы и нормы необходимы для гармоничного существования и развития государства. Таким образом, каждый человек в демократическом обществе 
-        Получает определенный набор свобод и обязательств сформированных с учетом интересов всего сообщества. Исходя из вышесказанного, можно заключить, что демократия – это возможность для каждого человека свободно участвовать в непосредственном управлении своим государством, обществом и личной судьбой в конечном счете.</p>
-      <div class="row justify-content-start">
+<p class="description_service">
+На данной странице можно посмотреть имеющиеся Категории сервиса. Это глобальные виды услуг для Сервиса, которые активируются на платформе (при наличии подключения к ней). Партнеры и исполнители могут добавлять свои услуги и ресурсы только в контексте данных категорий. 
+</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>
+
+{% if "METASERVICE-ADMIN" in user_groups %}
+<h1></h1>
+  <div class="container text-end mt-2">
+          <a class="btn btn-primary" id="bord" href={% url "sharix_admin:service_category/add/" %}>{% trans 'Add' %}</a>
+  </div>
+{% endif %}
+
+    <div class="row justify-content-start">
           <div class="maintable" id="maintable">
             {% render_table table %}
           </div>     
       </div>
 
-  <div class="container text-end mt-2">
-    <a class="btn btn-primary" id="bord" href="/service_category/add">{% trans 'Add' %}</a>
-  </div>
+<script>
+
+// Запрос на изменения статуса категории сервиса
+      $('.status-toggle').change(function() {
+        var service_category = $(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,
+            '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 %}
 

+ 0 - 3
sharix_admin/templates/sharix_admin/service_category_form.html

@@ -2,9 +2,7 @@
 {% load i18n %}
 
 {% block view %}
-{% block contenthome %}
 <div class="container">
-<h1 class="mainHeader">{{ title }}</h1>
 <form method="post" style="overflow: auto">
     {% csrf_token %}
     <div class="container m-2">
@@ -22,5 +20,4 @@
     </div>
 </form>
 </div>
-{% endblock contenthome %}
 {% endblock view %}

+ 2 - 2
sharix_admin/urls.py

@@ -77,8 +77,8 @@ urlpatterns = [
     #path('service_category/<int:pk>', login_required(ServiceCategoryDetailView.as_view()), name='service_category'),
     path('service_category/edit/<int:pk>', login_required(ServiceCategoryUpdateView.as_view()), name='service_category/edit/'),
     path('service_category/add/', login_required(ServiceCategoryCreate.as_view()), name='service_category/add/'),
-    path('service_category/delete/<int:pk>', login_required(ServiceCategoryDelete.as_view()), name='service_category/delete/'),
-    path('service_category/change_status/', change_service_status, name='service_category/change_status'),
+#    path('service_category/delete/<int:pk>', login_required(ServiceCategoryDelete.as_view()), name='service_category/delete/'),
+    path('service_category/change_status/', change_service_category_status, name='service_category/change_status'),
 
 #CHECK Maybe obsolete
     #path('service_information/add/', login_required(ServiceInformationCreate.as_view()),

+ 192 - 50
sharix_admin/views/service_category.py

@@ -8,31 +8,99 @@ from sharix_admin.forms import ServiceCategoryCreateForm, ServiceCategoryUpdateF
 from sharix_admin.tables import ServiceCategoriesTable
 from .base import BaseView
 
+from sharix_admin.utils import group_required
+from django.contrib.auth.decorators import login_required
+from django.urls import reverse_lazy
+from django.views.generic.edit import FormView
+from django.db import transaction
+from django.contrib import messages
 
-class ServiceCategoryCreate(BaseView, CreateView):
-    page_title = _('Услуги сервиса')
-    page_name = 'service_category'
-    model = ServiceCategory
+from django.db.models import Q
+from django.contrib.auth.mixins import UserPassesTestMixin
+
+class ServiceCategoryCreate(BaseView, FormView):
     form_class = ServiceCategoryCreateForm
     template_name = "sharix_admin/service_category_form.html"
+    success_url = reverse_lazy("sharix_admin:service_categories")
+    page_title = 'Добавить категорию услуг'
+    page_name = 'service_category/add/'
 
-    def get_context_data(self, **kwargs):
-        context = super().get_context_data(**kwargs)
-        context.update({
-            'object': self.object,
-        })
-        return context
-
-    def get_success_url(self):
-        return reverse('service_category')
-
-    def test_func(self) -> bool or None:
+    # Проверяем не состояит ли текущий пользователь в группе METASERVICE-ADMIN
+    def test_func(self):
         group_names = ('METASERVICE-ADMIN')
-        if bool(self.request.user.groups.filter(name=group_names)) or self.request.user.is_superuser:
+        if bool(self.request.user.groups.filter(name=group_names)): #or self.request.user.is_superuser:
             return True
         return False
-
-
+            #return not "METASERVICE-ADMIN" in self.user_groups
+
+    def form_valid(self, form):
+        with transaction.atomic():
+            # Сохраняем форму, чтобы получить объект компании
+            instance = form.save(commit=False)
+
+            # Присваиваем полю repr идентификатор текущего пользователя
+            instance.repr = self.request.user
+
+            # Создаем новую запись в БД, чтобы иметь доступ к ID
+            instance.save()
+
+            #TODO ADD INTEGRATION WITH PLATFORM!
+            # Создание тикета на активацию Категории услуг на Платформе.
+            # Создаем объект тикета и присваиваем его полю ticket_status
+            #instance.ticket_status = create_ticket_company_activation(self.request.user, instance)
+
+            # Создание тикета на утверждение прав пользователя
+            #create_ticket_role_activation_partner_admin(self.request.user, instance)
+
+            # Сохраняем новые изменения
+            instance.save()
+
+            #TODO! Это делать на платформе!
+            # Создаем необходимые объекты документов по requirements указанных в созданной company
+            # Используем bulk_create для создания всех объектов одновременно
+            #doc_codes = parse_requirements(instance.requirements)
+            #Documents.objects.bulk_create([
+            #    Documents(
+            #        company=instance,
+            #        user=self.request.user,
+            #        doc_type=doc_code
+            #    ) for doc_code in doc_codes
+            #])
+
+        # Отправляем пользователю уведомление на страницу о успехе операции
+        messages.success(
+            self.request,
+            'Ваша заявка на добавление категории услуг успешно отправлена на Платформу и теперь проходит проверку! Если Сервис не подключен к Платформе, можете активировать категорию услуг в списке вручную.'
+        )
+
+        return super().form_valid(form)  # Возвращаем успешный ответ
+
+
+#class ServiceCategoryCreate(BaseView, CreateView):
+#    page_title = _('Услуги сервиса')
+#    page_name = 'service_category'
+#    model = ServiceCategory
+#    form_class = ServiceCategoryCreateForm
+#    template_name = "sharix_admin/service_category_form.html"
+#
+#    def get_context_data(self, **kwargs):
+#        context = super().get_context_data(**kwargs)
+#        context.update({
+#            'object': self.object,
+#        })
+#        return context
+#
+#    def get_success_url(self):
+#        return reverse('service_category')
+#
+#    def test_func(self) -> bool or None:
+#        group_names = ('METASERVICE-ADMIN')
+#        if bool(self.request.user.groups.filter(name=group_names)) or self.request.user.is_superuser:
+#            return True
+#        return False
+
+
+#class ServiceCategoriesListView(UserPassesTestMixin, SingleTableView):
 class ServiceCategoriesListView(BaseView, SingleTableView):
     page_title = _('Услуги сервиса')
     page_name = 'service_category'
@@ -40,6 +108,18 @@ class ServiceCategoriesListView(BaseView, SingleTableView):
     queryset = ServiceCategory.objects.all()
     template_name = 'sharix_admin/service_categories.html'
 
+    def get_queryset(self):
+        queryset = super().get_queryset()
+        search_query = self.request.GET.get('q', '').strip()
+        if search_query:
+            queryset = queryset.filter(
+                Q(id__icontains=search_query) |
+                Q(caption__icontains=search_query) |
+                Q(codename__icontains=search_query) |
+                Q(description__icontains=search_query)
+            ).distinct()
+        return queryset
+
     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
         context.update({
@@ -51,24 +131,28 @@ class ServiceCategoriesListView(BaseView, SingleTableView):
         queryset = queryset.annotate.order_by("-" if is_descending else "")
         return (queryset, True)
 
-    def test_func(self) -> bool or None:
-        group_names = ('METASERVICE-ADMIN')
-        if bool(self.request.user.groups.filter(name=group_names)) or self.request.user.is_superuser:
-            return True
-        return False
+    #def test_func(self) -> bool or None:
+    #    return True
+    #    group_names = ('METASERVICE-ADMIN')
+    #    if bool(self.request.user.groups.filter(name=group_names)) or self.request.user.is_superuser:
+    #        return True
+    #    return False
 
 
 class ServiceCategoryUpdateView(BaseView, UpdateView):
     model = ServiceCategory
-    form_class = ServiceCategoryCreateForm
+    page_title = _('Редактирование услуг Сервиса')
+    form_class = ServiceCategoryUpdateForm
+    success_url = reverse_lazy("sharix_admin:service_categories")
     template_name = "sharix_admin/service_category_form.html"
+    page_name = 'service_category/edit/'
 
     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
         context.update({
             'title': _('Услуги сервиса'),
             'object': self.object,
-            "current_page": "service_category"
+            "current_page": "sharix_admin:service_categories"
         })
         return context
 
@@ -78,28 +162,86 @@ class ServiceCategoryUpdateView(BaseView, UpdateView):
             return True
         return False
 
-    def get_success_url(self):
-        return reverse('service_category')
-
-
-class ServiceCategoryDelete(BaseView, DeleteView):
-    model = ServiceCategory
-    template_name = "sharix_admin/service_category_delete.html"
-
-    def get_context_data(self, **kwargs):
-        context = super().get_context_data(**kwargs)
-        context.update({
-            'title': 'Услуги сервиса',
-            'object': self.object,
-            "current_page": "service_category"
-        })
-        return context
-
-    def get_success_url(self):
-        return reverse('service_category')
-
-    def test_func(self) -> bool or None:
-        group_names = ('METASERVICE-ADMIN')
-        if bool(self.request.user.groups.filter(name=group_names)) or self.request.user.is_superuser:
-            return True
-        return False
+    #def get_success_url(self):
+    #    return success_url
+        #return reverse_lazy('sharix_admin:service_categories')
+
+    def form_valid(self, form):
+        with transaction.atomic():
+            # Сохраняем форму, чтобы получить объект ресурса
+            instance = form.save(commit=False)
+
+            # Присваиваем полю repr идентификатор текущего пользователя
+            instance.repr = self.request.user
+
+            # Создаем новую запись в БД, чтобы иметь доступ к ID
+            instance.save()
+
+            #TODO ADD INTEGRATION WITH PLATFORM
+
+            # Создание тикета на активацию категории услуги.
+            # Создаем объект тикета и присваиваем его полю ticket_status
+            #instance.ticket_status = create_ticket_resource_activation_by_metaservice_supervisor(self.request.user, instance)
+
+            # Создание тикета на утверждение прав пользователя
+            # create_ticket_role_activation_partner_admin(self.request.user, instance)
+
+            # Сохраняем новые изменения
+            instance.save()
+
+            #TODO ADD INTEGRATION WITH PLATFORM
+            # Создаем необходимые объекты документов по requirements указанных в созданной company
+            # Используем bulk_create для создания всех объектов одновременно
+            #doc_codes = parse_requirements(instance.requirements)
+            #Documents.objects.bulk_create([
+            #    Documents(
+            #        company=instance,
+            #        user=self.request.user,
+            #        doc_type=doc_code
+            #    ) for doc_code in doc_codes
+            #])
+
+        # Отправляем пользователю уведомление на страницу о успехе операции
+        messages.success(
+            self.request,
+            'Ваша заявка на изменение категории услуг успешно отправлена и теперь проходит проверку! Если Сервис не подключен к платформе - актифируйте самостоятельно.'
+        )
+
+        return super().form_valid(form)  # Возвращаем успешный ответ
+
+
+#class ServiceCategoryDelete(BaseView, DeleteView):
+#    model = ServiceCategory
+#    template_name = "sharix_admin/service_category_delete.html"
+#
+#    def get_context_data(self, **kwargs):
+#        context = super().get_context_data(**kwargs)
+#        context.update({
+#            'title': 'Услуги сервиса',
+#            'object': self.object,
+#            "current_page": "service_category"
+#        })
+#        return context
+#
+#    def get_success_url(self):
+#        return reverse('service_category')
+#
+#    def test_func(self) -> bool or None:
+#        group_names = ('METASERVICE-ADMIN')
+#        if bool(self.request.user.groups.filter(name=group_names)) or self.request.user.is_superuser:
+#            return True
+#        return False
+
+@login_required
+@group_required('METASERVICE-ADMIN')
+def change_service_category_status(request):
+    if request.method == 'POST':
+        service_category = request.POST.get('resource')
+        new_status = request.POST.get('new_status')
+
+        service_category = ServiceCategory.objects.get(pk=service_category)
+        service_category.status = new_status
+        service_category.save()
+        return JsonResponse({'status': 'success'})
+    else:
+        return JsonResponse({'status': 'error'})