blezz-tech пре 1 месец
родитељ
комит
bb1e28149b

+ 2 - 0
forms/__init__.py

@@ -1 +1,3 @@
 from .order_local import *
+from .order_sports import *
+from .resource_sports import *

+ 47 - 0
forms/order_sports.py

@@ -0,0 +1,47 @@
+from django import forms
+from webservice_running.models import Event
+from dbsynce.models import Orders
+from dbsynce.models import Client
+from dbsynce.models import Company
+from dbsynce.models import Service
+from dbsynce.models import ServiceCategory
+from dbsynce.models import Provider
+from tickets.models import Ticket
+from django.contrib.auth import get_user_model
+
+from sharix_admin.forms import OrderForm
+
+class OrderSportsForm(OrderForm):
+    def __init__(self, *args, **kwargs):
+        super(OrderSportsForm, self).__init__(*args, **kwargs)
+        # Добавляем класс .form-control для всех полей формы
+        for field in iter(self.fields):
+            if 'class' not in self.fields[field].widget.attrs:
+                self.fields[field].widget.attrs.update({'class': 'form-control'})
+                
+#    class Meta:
+#        model = Orders
+#        fields = [
+#            'status', 'title', 'note', 'time_placed', 'time_start', 'time_start_real',
+#            'time_start_predicted', 'time_finish_real', 'time_finish_predicted',
+#            'real_price', 'predicted_price', 'asap', 'ticket', 'service',
+#            'service_category', 'client', 'provider', 'receiver', 'company'
+#        ]
+#        widgets = {
+#            'time_placed': forms.DateTimeInput(attrs={'type': 'datetime-local'}),
+#            'time_start': forms.DateTimeInput(attrs={'type': 'datetime-local'}),
+#            'time_start_real': forms.DateTimeInput(attrs={'type': 'datetime-local'}),
+#            'time_start_predicted': forms.DateTimeInput(attrs={'type': 'datetime-local'}),
+#            'time_finish_real': forms.DateTimeInput(attrs={'type': 'datetime-local'}),
+#            'time_finish_predicted': forms.DateTimeInput(attrs={'type': 'datetime-local'}),
+#        }
+#
+#    def __init__(self, *args, **kwargs):
+#        super().__init__(*args, **kwargs)
+#        self.fields['receiver'].queryset = get_user_model().objects.all()
+#        self.fields['client'].queryset = Client.objects.all()
+#        self.fields['company'].queryset = Company.objects.all()
+#        self.fields['provider'].queryset = Provider.objects.all()
+#        self.fields['service'].queryset = Service.objects.all()
+#        self.fields['service_category'].queryset = ServiceCategory.objects.all()
+#        self.fields['ticket'].queryset = Ticket.objects.all()

+ 20 - 0
forms/resource_sports.py

@@ -0,0 +1,20 @@
+from dbsynce.models import Resource
+from webservice_running.models import Place
+from django import forms
+
+
+class ResourceSportsForm(forms.ModelForm):
+    def __init__(self, *args, **kwargs):
+        super(ResourceSportsForm, self).__init__(*args, **kwargs)
+        # Добавляем класс .form-control для всех полей формы
+        for field in iter(self.fields):
+            if 'class' not in self.fields[field].widget.attrs:
+                self.fields[field].widget.attrs.update({'class': 'form-control'})
+
+    class Meta:
+        model = Place
+        #model = Resource
+        fields = [
+            'address',
+            'resource',
+        ]

+ 156 - 0
tables.py

@@ -0,0 +1,156 @@
+import django_tables2 as tables
+from dbsynce.models import *
+from webservice_running.models import *
+from django.contrib.auth import get_user_model
+from django.utils.html import format_html
+from django.utils.translation import gettext_lazy as _
+
+from dbsynce.lib.dicts import *
+#from webservice_running.lib.dicts import *
+
+
+class EventTable(tables.Table):
+    id = tables.Column(
+        verbose_name=_('ID'),
+        attrs={
+                "td": {"width": "5%"}
+        }
+    )
+    title = tables.LinkColumn(
+        'sharix_admin:order_detail',
+        args=[tables.A('pk')],
+        verbose_name=_('Title'),
+        attrs={
+            "td": {"width": "20%"}
+        }
+    )
+    status = tables.Column(
+        accessor='status',
+        #accessor='status_by_code(status)',
+        verbose_name=_('Status'),
+        attrs={
+            "td": {"width": "15%"}
+        }
+    )
+    receiver = tables.Column(
+        accessor='receiver.get_full_name',
+        verbose_name=_('Receiver'),
+        #'sharix_admin:user_detail',
+        #args=[tables.A('pk')],
+        attrs={
+            "td": {"width": "20%"}
+        }
+    )
+    time_created = tables.DateTimeColumn(
+        verbose_name=_('Created'),
+        attrs={
+            "td": {"width": "20%"}
+        }
+    )
+
+    class Meta:
+        model = Orders
+        attrs = {
+            "class": "table table-layout-fixed"
+        }
+        exclude = (
+            'id_metaservice',
+            'note',
+            'time_placed',
+            'time_start',
+            'time_start_real',
+            'time_start_predicted',
+            'time_finish_real',
+            'time_finish_predicted',
+            'real_price',
+            'predicted_price',
+            'asap',
+            'is_global',
+            'is_visible',
+            'ticket',
+            'service',
+            'service_category',
+            'client',
+            'provider',
+            'company')
+
+class PlaceTable(tables.Table):
+    id = tables.LinkColumn(
+        'sharix_admin:resource_detail',
+        args=[tables.A('pk')],
+        verbose_name=_('ID'),
+        attrs={
+            "td": {"width": "5%"}
+        }
+    )
+    # В user ссылка LinkColumn на страницу Аси "Информация о партнере" страница partner_information_form
+    user = tables.Column(
+        accessor='user.get_full_name',
+        order_by=('user.first_name', 'user.last_name'),
+        verbose_name=_('Responsible'),
+        attrs={
+            "td": {"width": "15%"}
+        }
+    )
+    status = tables.Column(
+        verbose_name=_('Status'),
+        attrs={
+            'th': {'scope': 'col'},
+            "td": {"width": "20%"}
+        }
+    )
+
+    resource_type = tables.Column(
+        attrs={
+            'th': {'scope': 'col'},
+            "td": {"width": "20%"}
+        }
+    )
+
+    edit = tables.LinkColumn(
+        'sharix_admin:resource/edit/',
+        verbose_name='',
+        orderable=False,
+        text="E",
+        args=[tables.A('pk')],
+        attrs={
+            'th': {'scope': 'col'},
+            "td": {"class": "edit_col"},
+            "td": {"width": "10%"}
+        }
+    )
+
+    check = tables.BooleanColumn(
+        verbose_name='',
+        attrs={
+            'th': {'scope': 'col'},
+            "td": {"width": "10%"}
+        }
+    )
+
+    # paginate_by = 10
+    class Meta:
+        model = Resource
+        attrs = {
+            "class": "table table-layout-fixed"
+        }
+        exclude = (
+            'id_metaservice',
+            'requirements',
+            'is_global',
+            'is_visible',
+            'ticket_status'
+        )
+    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-resource-id="{}">',
+                record.id
+            )
+        else:
+            return format_html(
+                '<input class="form-check-input status-toggle" type="checkbox" id="flexCheckDefault" data-resource-id="{}">',
+                record.id
+            )
+
+

+ 9 - 0
templates/webservice_running/order_sports.html

@@ -0,0 +1,9 @@
+{% extends 'sharix_admin/base_admin.html' %}
+
+{% block view %}
+<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="submit">Отправить</button>
+</form>
+{% endblock %}

+ 72 - 0
templates/webservice_running/order_sports_detail.html

@@ -0,0 +1,72 @@
+{% extends 'sharix_admin/base_admin.html' %}
+{% load static %}
+
+{% block view %}
+<p class="description_service">
+Тут представлена информация о Заказе {{ order.title }}. Действия с заказом осуществляются через мобильное приложение.
+</p>
+
+<div class="card w-100 mb-4">
+    <div class="card-body position-relative">
+        <h5 class="card-title fw-bold mb-4">{{ order.title }}</h5>
+
+        <ul class="list-style-none">
+		<li><b>{{ captions.status }}</b> {{ order.status }}</li>
+		<li><b>{{ captions.asap }}</b> {{ order.asap }}</li>
+		<li><b>{{ captions.note }}</b> {{ order.note }}</li>
+		<li><b>{{ captions.time_created }}</b> {{ order.time_created }}</li>
+		<li><b>{{ captions.time_placed }}</b> {{ order.time_placed }}</li>
+		<li><b>{{ captions.time_start }}</b> {{ order.time_start }}</li>
+		<li><b>{{ captions.time_start_real }}</b> {{ order.time_start_real }}</li>
+		<li><b>{{ captions.time_finish_real }}</b> {{ order.time_finish_real }}</li>
+		<li><b>{{ captions.real_price }}</b> {{ order.real_price }}</li>
+		<li><b>{{ captions.predicted_price }}</b> {{ order.predicted_price }}</li>
+		<li><b>{{ captions.service }}</b> {{ order.service.caption }}</li>
+		<li><b>{{ captions.service_category }}</b> {{ order.service_category.caption }}</li>
+		<li><b>{{ captions.client }}</b> {{ order.client.user.get_full_name }}</li>
+		<li><b>{{ captions.receiver }}</b> {{ order.receiver.get_full_name }}</li>
+		<li><b>{{ captions.company }}</b> {{ order.company.legal_name }}</li>
+		<li><b>{{ captions.provider }}</b> {{ order.provider.user.get_full_name }}</li>
+		{% comment%}
+
+		<li><b>Юр. адрес</b> {{ company.address }}</li>
+            
+            <li><b>БИК</b> {{ company.bik }}</li>
+            <li><b>Банк</b> {{ company.bank_name }}</li>
+	    {% endcomment %}
+
+        </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 %}

+ 46 - 0
templates/webservice_running/orders_sports.html

@@ -0,0 +1,46 @@
+{% extends 'sharix_admin/base_admin.html' %}
+{% load render_table from django_tables2 %}
+{% load i18n %}
+{% 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>
+
+{% if "METASERVICE-CLIENT" in user_groups %}
+<h1></h1>
+  <div class="container text-end mt-2">
+          <a class="btn btn-primary" id="bord" href={% url "sharix_admin:order/add/" %}>{% trans 'Add' %}</a>
+  </div>
+{% endif %}
+
+    <div class="row justify-content-start">
+          <div class="maintable" id="maintable">
+{% render_table table %}
+          </div>
+      </div>
+
+{% endblock contenthome %}
+{% endblock view %}

+ 9 - 0
templates/webservice_running/resource_sports.html

@@ -0,0 +1,9 @@
+{% extends 'sharix_admin/base_admin.html' %}
+
+{% block view %}
+<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="submit">Отправить</button>
+</form>
+{% endblock %}

+ 52 - 0
templates/webservice_running/resource_sports_detail.html

@@ -0,0 +1,52 @@
+{% extends 'sharix_admin/base_admin.html' %}
+{% load static %}
+
+{% block view %}
+<p class="description_service">
+Тут представлена информация о Ресурсе {{ resource.id }}. Редактировать информацию может только представитель Партнера Сервиса с ролью PARTNER ADMIN.
+</p>
+
+<div class="card w-100 mb-4">
+    <div class="card-body position-relative">
+        <h5 class="card-title fw-bold mb-4">{{ resource.id }}</h5>
+
+        <ul class="list-style-none">
+                <li><b>{{ captions.user }}</b> {{ resource.user.get_full_name }}</li>
+                <li><b>{{ captions.status }}</b> {{ resource.status }}</li>
+                <li><b>{{ captions.resource_type }}</b> {{ resource.resource_type }}</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 %}

+ 81 - 0
templates/webservice_running/resource_sports_list.html

@@ -0,0 +1,81 @@
+{% extends 'sharix_admin/base_admin.html' %}
+{% load render_table from django_tables2 %}
+{% load i18n %}
+{% load static %}
+
+{% block view %}
+{% block contenthome %}
+
+<style>
+  a {
+    color: black;
+    text-decoration: none;
+  }
+  a:hover {
+    color: black;
+  }
+</style>
+
+<p class="description_service">
+        На этой странице представлены список средств и объектов, необходимых для обеспечения функционирования сервиса. 
+        Активация ресурсов происходит через <a href="{% url 'tickets:ticket_list_list' %}" class="text-primary">заявки</a>.
+    </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="container text-end mt-2">
+      <a href="{% url 'sharix_admin:resource/add/' %}" class="btn btn-primary" style="height: 38px;">Добавить ресурс</a>
+    </div>
+
+    <div class="row justify-content-start">
+          <div class="maintable" id="maintable">
+            {% render_table table %}
+          </div>     
+      </div>
+
+
+    <script>
+      // Запрос на изменения статуса ресурса
+      $('.status-toggle').change(function() {
+        var resource = $(this).data('resource-id');
+        var new_status = $(this).prop('checked') ? 'active' : 'deactivated';
+        $.ajax({
+          url: '{% url "sharix_admin:resource/change_status" %}',
+          type: 'POST',
+          data: {
+            'resource': resource,
+            '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 %}

+ 1 - 1
urls.py

@@ -45,7 +45,7 @@ urlpatterns_webadmin_local = [
     path('order_local/edit/<int:pk>', login_required(OrderEditView.as_view()), name='order_local/edit'),
 
 
-    path('orders_sports/', login_required(OrdersSportsView.as_view()), name='orders_sports'),
+    path('orders_sports/', login_required(OrdersSportsListView.as_view()), name='orders_sports'),
     path('order_sports/<int:pk>', login_required(OrderSportsDetailView.as_view()), name='order_sports_detail'),
     #todo - move from views.order_reg to this one
     path('order_sports/add/', login_required(OrderSportsCreateView.as_view()), name='order_sports/add/'),

+ 2 - 0
views/__init__.py

@@ -2,3 +2,5 @@
 from .local_pages import *
 from .sports_pages import *
 from .order_local import *
+from .order_sports import *
+from .resource_sports import *

+ 1 - 1
views/order_local.py

@@ -26,7 +26,7 @@ from django.contrib.auth import get_user_model
 class OrdersLocalListView(OrdersListView):
 #class OrdersListView(UserPassesTestMixin, SingleTableView):
 #    table_class = OrdersTable
-#    queryset = Orders.objects.all()
+    queryset = Orders.objects.all()
     template_name = 'webservice_running/orders_local.html'
 #    page_title = 'Заказы'
     page_name = 'orders_local'

+ 127 - 0
views/order_sports.py

@@ -0,0 +1,127 @@
+from dbsynce.models import Orders
+from webservice_running.models import Event
+from django.contrib.auth.decorators import login_required
+from django.contrib.auth.mixins import UserPassesTestMixin
+from django.http import JsonResponse
+from django.utils.translation import gettext as _
+from django_tables2 import SingleTableView
+from sharix_admin.tables import OrdersTable
+from webservice_running.tables import EventTable
+from sharix_admin.views import OrdersListView, OrderCreateView, OrderDetailView, OrderEditView
+from sharix_admin.utils import group_required
+from datetime import datetime, timedelta
+from dbsynce.lib.core import parse_requirements, get_admin_url
+from dbsynce.models import Documents
+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 import DetailView
+from tickets.models import Ticket, TicketList
+from sharix_admin.forms import OrderForm
+from sharix_admin.utils import *
+from dbsynce.lib.data import *
+from sharix_admin.views import BaseView
+from django.db.models import Q
+from django.contrib.auth import get_user_model
+
+class OrdersSportsListView(OrdersListView):
+#class OrdersListView(UserPassesTestMixin, SingleTableView):
+    table_class = EventTable
+#    table_class = OrdersTable
+    queryset = Event.objects.all()
+    template_name = 'webservice_running/orders_sports.html'
+#    page_title = 'Заказы'
+    page_name = 'orders_sports'
+
+    def get_context_data(self, **kwargs):
+        context = super().get_context_data(**kwargs)
+        context.update({
+            'title': _('Orders'),
+            'object_list': context['object_list'],
+        })
+        return context
+
+    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(user__first_name__icontains=search_query) | 
+                Q(user__first_name__icontains=search_query) |
+                Q(status__icontains=search_query)
+            ).distinct()
+        return queryset
+
+    def testing(self, queryset, is_descending):
+        queryset = queryset.annotate.order_by("-" if is_descending else "")
+        return (queryset, True)
+
+    def test_func(self) -> bool or None:
+        return True
+
+@login_required
+@group_required('PARTNER-SUPERVISOR')
+def change_order_local_status(request):
+    if request.method == 'POST':
+        order_id = request.POST.get('order_local') 
+        new_status = request.POST.get('new_status')
+
+        try:
+            order = Orders.objects.get(pk=order_id)
+            order.status = new_status
+            order.save()
+            return JsonResponse({'status': 'success'})
+        except Orders.DoesNotExist:
+            return JsonResponse({'status': 'error', 'message': 'Order not found'}, status=404)
+    return JsonResponse({'status': 'error'}, status=400)
+
+class OrderSportsEditView(OrderEditView):
+#    form_class = OrderForm
+    template_name = "webservice_running/order_sports.html"
+    success_url = reverse_lazy("webservice_running:orders_sports")
+#    page_title = 'Изменить заказ'
+    page_name = 'order_sports_edit'
+
+    def test_func(self):
+        return "METASERVICE-CLIENT" in self.user_groups
+
+    def form_valid(self, form):
+        with transaction.atomic():
+            instance = form.save(commit=False)
+            instance.repr = self.request.user
+            instance.save()
+            instance.save()
+            doc_codes = parse_requirements(instance.requirements)
+        messages.success(self.request, 'Заказ успешно обновлён!')
+        return super().form_valid(form)
+
+class OrderSportsCreateView(OrderCreateView):
+    template_name = "webservice_running/order_sports.html"
+    success_url = reverse_lazy("webservice_running:orders_sports")
+    page_name = 'order_sports/add/'
+
+    def test_func(self):
+        return "METASERVICE-CLIENT" in self.user_groups
+        #return not "METASERVICE-CLIENT" in self.user_groups
+
+    def form_valid(self, form):
+        with transaction.atomic():
+            instance = form.save(commit=False)
+            instance.repr = self.request.user
+            instance.save()
+            instance.ticket_status = create_ticket_order(self.request.user, instance)
+            instance.save()
+        messages.success(self.request, 'Заказ успешно создан!')
+        return super().form_valid(form)
+
+class OrderSportsDetailView(OrderDetailView):
+#    model = Orders
+    template_name = 'webservice_running/order_sports.html'
+    context_object_name = 'order_sports'
+
+    def get_context_data(self, **kwargs):
+        context = super().get_context_data(**kwargs)
+        context['title'] = _('Order Sports Details')
+        return context

+ 207 - 0
views/resource_sports.py

@@ -0,0 +1,207 @@
+from dbsynce.models import Resource
+from django.contrib.auth.decorators import login_required
+from django.contrib.auth.mixins import UserPassesTestMixin
+from django.http import JsonResponse
+from django.utils.translation import gettext as _
+from django_tables2 import SingleTableView
+from django.views.generic import DetailView
+
+from sharix_admin.tables import ResourcesTable
+from webservice_running.tables import PlaceTable
+from sharix_admin.utils import group_required
+
+
+from datetime import datetime, timedelta
+from dbsynce.lib.core import parse_requirements, get_admin_url
+from dbsynce.models import Documents
+from django.contrib import messages
+from django.db import transaction
+from django.urls import reverse_lazy
+from django.views.generic.edit import FormView
+from tickets.models import Ticket, TicketList
+
+from sharix_admin.forms import ResourceForm
+from sharix_admin.utils import *
+from dbsynce.lib.data import *
+from sharix_admin.views.base import BaseView
+from django.db.models import Q
+
+from dbsynce.docs.database.resource import Resource as ResourceHelpTexts
+from dbsynce.docs.verbose_names.resource import Resource as ResourceVerboseNames
+
+class ResourcesSportsListView(ResourcesListView):
+    table_class = PlaceTable
+    queryset = Place.objects.all()
+    template_name = 'webservice_running/resource_sports.html'
+    page_title = 'Places'
+    page_name = 'resources_sports'
+
+    def get_context_data(self, **kwargs):
+        context = super().get_context_data(**kwargs)
+        context.update({
+            'title': _('Places'),
+            'object_list': context['object_list'],
+        })
+        return context
+
+    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(user__first_name__icontains=search_query) |
+                Q(user__last_name__icontains=search_query) |
+                Q(status__icontains=search_query)
+            ).distinct()
+        return queryset
+
+    def test_func(self) -> bool or None:
+        #group_names = ('PARTNER-ADMIN')
+        #if bool(self.request.user.groups.filter(name=group_names)) or self.request.user.is_superuser:
+        #    return True
+        #return False
+        return True
+
+
+@login_required
+@group_required('PARTNER-ADMIN')
+def change_resource_status(request):
+    if request.method == 'POST':
+        resource = request.POST.get('resource')
+        new_status = request.POST.get('new_status')
+
+        resource = Resource.objects.get(pk=resource)
+        resource.status = new_status
+        resource.save()
+        return JsonResponse({'status': 'success'})
+    else:
+        return JsonResponse({'status': 'error'})
+
+class ResourceSportsEditView(ResourceEditView):
+    form_class = ResourceSportsForm
+    template_name = "webservice_running/resource_sports.html"
+    success_url = reverse_lazy("webservice:resource_sports_list")
+    page_title = 'Изменить место'
+    page_name = 'resource_sports_edit'
+
+    # Проверяем состояит ли текущий пользователь в группе PARTNER-ADMIN
+    def test_func(self):
+        return "PARTNER-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()
+
+            # Создание тикета на активацию ресурса.
+            # Создаем объект тикета и присваиваем его полю 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()
+
+            # Создаем необходимые объекты документов по 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 ResourceSportsCreate(ResourceCreate):
+    form_class = ResourceSportsForm
+    template_name = "webservice_running/resource_sports.html"
+    success_url = reverse_lazy("webservice:main_sports")
+    page_title = 'Добавить ресурс'
+    page_name = 'resource_sports/add/'
+
+    # Проверяем не состояит ли текущий пользователь в группе PARTNER-ADMIN
+#    def test_func(self):
+#        return not "PARTNER-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()
+
+            # Создание тикета на активацию ресурса.
+            # Создаем объект тикета и присваиваем его полю ticket_status
+            instance.ticket_status = create_ticket_resource_activation_by_metaservice_supervisor(self.request.user, instance)
+
+            # Создание тикета на утверждение прав пользователя
+            create_ticket_resource_activation_by_partner_admin(self.request.user, instance)
+
+            # Сохраняем новые изменения
+            instance.save()
+
+            # Создаем необходимые объекты документов по requirements указанных в созданной company
+            # Используем bulk_create для создания всех объектов одновременно
+            doc_codes = parse_requirements(instance.requirements)
+            Documents.objects.bulk_create([
+                Documents(
+                    #TODO add info about company
+                    resource=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 ResourceSportsDetailView(ResourceDetailVies):
+    model = Place
+    template_name = 'webservice_running/resource_sports_detail.html'
+    context_object_name = 'resource_sports'
+    page_title = 'О ресурсе'
+    page_name = 'resource_sports_detail'
+
+    def detail_view(request, primary_key):
+        try:
+            resource = Place.objects.get(pk=primary_key)
+        except Place.DoesNotExist:
+            raise Http404('Provider does not exist')
+
+        return render(request, template_name, context={
+            'help_texts': ResourceHelpTexts,
+            'captions': ResourceVerboseNames,
+            })
+
+    def get_context_data(self, **kwargs):
+        context = super().get_context_data(**kwargs)
+        context['help_texts'] = ResourceHelpTexts
+        context['captions'] = ResourceVerboseNames
+        return context
+