Browse Source

Merge branch 'master' of blezz-tech/sharix-open-webservice-running into master

100 changed files with 6177 additions and 808 deletions
  1. 17 1
      .gitignore
  2. 44 0
      README.md
  3. 0 0
      __init__.py
  4. 5 0
      admin.py
  5. 3 0
      admin/__init__.py
  6. 17 0
      admin/favoritecontacts.py
  7. 17 0
      admin/frequentaddress.py
  8. 17 0
      admin/preferreddrivers.py
  9. 5 0
      apiviews/__init__.py
  10. 44 0
      apiviews/favoritecontacts.py
  11. 44 0
      apiviews/frequentaddress.py
  12. 64 0
      apiviews/orders_local.py
  13. 12 0
      apiviews/personinfo.py
  14. 44 0
      apiviews/preferreddrivers.py
  15. 14 0
      apps.py
  16. 0 29
      authorization-fog-pass.html
  17. 0 28
      authorization.html
  18. 10 0
      config.py
  19. 0 727
      css/style.css
  20. 14 0
      forms.py
  21. 6 0
      handlers/.gitignore
  22. 75 0
      handlers/BotClass.py
  23. 75 0
      handlers/README.md
  24. 16 0
      handlers/applications.json
  25. 11 0
      handlers/bin/gen-passwords.py
  26. 15 0
      handlers/bin/gen_users.sh
  27. 18 0
      handlers/bin/gen_web_users.py
  28. 10 0
      handlers/classes/Answer.py
  29. 248 0
      handlers/classes/Order.py
  30. 97 0
      handlers/classes/OrderTicket.py
  31. 78 0
      handlers/classes/Ticket.py
  32. 38 0
      handlers/classes/Ticket_user.py
  33. 11 0
      handlers/conf/bin/install.sh
  34. 8 0
      handlers/conf/bin/service-failure-check.sh
  35. 15 0
      handlers/conf/bin/service-watcher.sh
  36. 17 0
      handlers/conf/open_handler@.service
  37. 6 0
      handlers/conf/service-monitor/service-failure-watcher@.service
  38. 9 0
      handlers/conf/service-monitor/service-failure-watcher@.timer
  39. 6 0
      handlers/conf/service-monitor/service-watcher.service
  40. 9 0
      handlers/conf/service-monitor/service-watcher.timer
  41. 37 0
      handlers/config.py
  42. 30 0
      handlers/core/JabberBot.py
  43. 11 0
      handlers/core/SystemdKiller.py
  44. 17 0
      handlers/core/lib.py
  45. 12 0
      handlers/core/utils.py
  46. 223 0
      handlers/handlers/open_access_request_pending.py
  47. 53 0
      handlers/handlers/open_basic_bot.py
  48. 192 0
      handlers/jsonAndRequest.py
  49. 60 0
      handlers/main.py
  50. 123 0
      handlers/old_st_request_assigned.py
  51. 123 0
      handlers/old_st_request_done.py
  52. 90 0
      handlers/old_st_request_new.py
  53. 123 0
      handlers/old_st_request_wontfix.py
  54. 120 0
      handlers/open_access_request_accepted.py
  55. 121 0
      handlers/open_access_request_pending.py
  56. 50 0
      handlers/open_basic_bot.py
  57. 120 0
      handlers/open_neg_request_accepted.py
  58. 107 0
      handlers/open_neg_request_pending.py
  59. 176 0
      handlers/open_service_request_accepted.py
  60. 178 0
      handlers/open_service_request_assigned.py
  61. 221 0
      handlers/open_service_request_booked.py
  62. 173 0
      handlers/open_service_request_booked_v2.py
  63. 130 0
      handlers/open_service_request_closed.py
  64. 141 0
      handlers/open_service_request_declined.py
  65. 150 0
      handlers/open_service_request_done.py
  66. 131 0
      handlers/open_service_request_forcemajeure.py
  67. 140 0
      handlers/open_service_request_pending.py
  68. 133 0
      handlers/open_service_request_preforcemajeure.py
  69. 120 0
      handlers/open_service_request_prestart.py
  70. 179 0
      handlers/open_service_request_process.py
  71. 129 0
      handlers/open_st_request_assigned.py
  72. 130 0
      handlers/open_st_request_done.py
  73. 130 0
      handlers/open_st_request_dublicate.py
  74. 129 0
      handlers/open_st_request_in_process.py
  75. 148 0
      handlers/open_st_request_new.py
  76. 148 0
      handlers/open_st_request_reopened.py
  77. 134 0
      handlers/open_st_request_wontfix.py
  78. 202 0
      handlers/open_student_handler.py
  79. 123 0
      handlers/open_template_bot.py
  80. 21 0
      handlers/order_functions.py
  81. 14 0
      handlers/requirements.txt
  82. 86 0
      handlers/st_request_in_process.py
  83. 10 0
      handlers/starter.sh
  84. 99 0
      handlers/status_changer.py
  85. 51 0
      handlers/status_handlers.py
  86. 0 3
      img/Vector.svg
  87. 0 3
      img/arrow.svg
  88. 0 4
      img/arrows.svg
  89. BIN
      img/assist.png
  90. BIN
      img/drive.png
  91. 0 6
      img/iot.svg
  92. BIN
      img/logo.png
  93. 0 2
      img/logo_open.svg
  94. BIN
      img/mc.png
  95. BIN
      img/mir.png
  96. BIN
      img/paymo.png
  97. 0 1
      img/people.svg
  98. 0 3
      img/plus.svg
  99. 0 1
      img/settings.svg
  100. BIN
      img/sharix-logo-final-400x-1-5@2x.png

+ 17 - 1
.gitignore

@@ -1,2 +1,18 @@
+# VSCode
+.vscode
+
+# venv
+venv
+.venv
+
+# Python
+__pycache__/
+*/__pycache__
+*.py[cod]
+*$py.class
+
+# Django
+migrations/*
+!migrations/__init__.py
 # Desktop Services Store
-.DS_Store
+.DS_Store

+ 44 - 0
README.md

@@ -0,0 +1,44 @@
+# Design Template
+
+A module for processing customer orders implemented as a Django application.
+
+## Installation
+
+1) Download or clone repository
+
+```bash
+git clone -b unstable https://git.sharix-app.org/ShariX_Open/sharix-open-webservice-running.git webservice_running
+```
+
+2) Install required dependencies in project settings
+
+```python
+INSTALLED_APPS = [   
+    ...
+    'webservice_running',
+    ...
+]
+```
+
+3) Connects application routes to the project
+
+```python
+  urlpatterns = (
+  [
+    ...
+    path('webservice/', include("webservice_running.urls"), name='webservice_running'),
+    ...
+  ]
+  )
+```
+
+4) Delete the migration files in the **migrations** folder (everything except __init__.py)
+
+Start test the server:
+
+```bash
+python manage.py runserver 8000
+```
+
+If the port has not been selected, it is 8000 by default. If selected port is busy, use another one (for example, try
+increasing port number by 1 until the server starts). A link to the website should appear in the terminal.

+ 0 - 0
__init__.py


+ 5 - 0
admin.py

@@ -0,0 +1,5 @@
+from django.contrib import admin
+
+from webservice_running.models import OrdersLocal
+
+admin.site.register(OrdersLocal)

+ 3 - 0
admin/__init__.py

@@ -0,0 +1,3 @@
+from .favoritecontacts import FavoritecontactsAdmin
+from .frequentaddress import FrequentaddressAdmin
+from .preferreddrivers import PreferreddriversAdmin

+ 17 - 0
admin/favoritecontacts.py

@@ -0,0 +1,17 @@
+from django.contrib import admin
+
+from webservice_running.models import Favoritecontacts
+
+
+@admin.register(Favoritecontacts)
+class FavoritecontactsAdmin(admin.ModelAdmin):
+    list_display = (
+        'id',
+        'client',
+        'full_name',
+        'phone_number',
+    )
+    list_filter = (
+        'id',
+        'client'
+    )

+ 17 - 0
admin/frequentaddress.py

@@ -0,0 +1,17 @@
+from django.contrib import admin
+
+from webservice_running.models import Frequentaddress
+
+
+@admin.register(Frequentaddress)
+class FrequentaddressAdmin(admin.ModelAdmin):
+    list_display = (
+        'client',
+        'address',
+        'description',
+        'id',
+    )
+    list_filter = (
+        'client',
+        'id'
+    )

+ 17 - 0
admin/preferreddrivers.py

@@ -0,0 +1,17 @@
+from django.contrib import admin
+
+from webservice_running.models import Preferreddrivers
+
+
+@admin.register(Preferreddrivers)
+class PreferreddriversAdmin(admin.ModelAdmin):
+    list_display = (
+        'id',
+        'client',
+        'provider_id',
+    )
+    list_filter = (
+        'id',
+        'client',
+        'provider_id'
+    )

+ 5 - 0
apiviews/__init__.py

@@ -0,0 +1,5 @@
+from .favoritecontacts import FavoritecontactsMVS
+from .frequentaddress import FrequentaddressMVS
+from .orders_local import OrdersLocalMVS
+from .personinfo import PersonInfoMVS
+from .preferreddrivers import PreferreddriversMVS

+ 44 - 0
apiviews/favoritecontacts.py

@@ -0,0 +1,44 @@
+from django.db.models import CharField
+from django.db.models.functions import Cast
+from rest_framework import viewsets, permissions
+from rest_framework.response import Response
+
+from webservice_running.models import Favoritecontacts
+from webservice_running.serializer import FavoritecontactsSerializer
+
+
+class FavoritecontactsMVS(viewsets.ModelViewSet):
+    queryset = Favoritecontacts.objects.all()
+    serializer_class = FavoritecontactsSerializer
+    permission_classes = [
+        permissions.IsAuthenticated
+    ]
+
+    def list(self, request, *args, **kwargs):
+        client = self.request.query_params.get('client')
+        queryset = Favoritecontacts.objects.all()
+        if client is not None:
+            queryset = queryset \
+                .annotate(client_int=Cast('client', output_field=CharField())) \
+                .filter(client_int=client)
+        serializer = self.get_serializer(queryset, many=True)
+        return Response(serializer.data)
+
+    def delete(self, request, *args, **kwargs):
+        client = self.request.query_params.get('client')
+        queryset = Favoritecontacts.objects.all()
+        if not client:
+            return Response(
+                {'error': 'client parameter is required'},
+                status=status.HTTP_400_BAD_REQUEST
+            )
+
+        queryset = queryset \
+            .annotate(client_int=Cast('client', output_field=CharField())) \
+            .filter(client_int=client)
+        queryset.delete()
+
+        return Response(
+            {'message': f'Objects with client {client} were deleted'},
+            status=status.HTTP_204_NO_CONTENT
+        )

+ 44 - 0
apiviews/frequentaddress.py

@@ -0,0 +1,44 @@
+from django.db.models import CharField
+from django.db.models.functions import Cast
+from rest_framework import viewsets, permissions
+from rest_framework.response import Response
+
+from webservice_running.models import Frequentaddress
+from webservice_running.serializer import FrequentaddressSerializer
+
+
+class FrequentaddressMVS(viewsets.ModelViewSet):
+    queryset = Frequentaddress.objects.all()
+    serializer_class = FrequentaddressSerializer
+    permission_classes = [
+        permissions.IsAuthenticated
+    ]
+
+    def list(self, request, *args, **kwargs):
+        client = self.request.query_params.get('client')
+        queryset = Frequentaddress.objects.all()
+        if client is not None:
+            queryset = queryset \
+                .annotate(client_int=Cast('client', output_field=CharField())) \
+                .filter(client_int=client)
+        serializer = self.get_serializer(queryset, many=True)
+        return Response(serializer.data)
+
+    def delete(self, request, *args, **kwargs):
+        client = self.request.query_params.get('client')
+        queryset = Frequentaddress.objects.all()
+        if not client:
+            return Response(
+                {'error': 'client parameter is required'},
+                status=status.HTTP_400_BAD_REQUEST
+            )
+
+        queryset = queryset \
+            .annotate(client_int=Cast('client', output_field=CharField())) \
+            .filter(client_int=client)
+        queryset.delete()
+
+        return Response(
+            {'message': f'Objects with client {client} were deleted'},
+            status=status.HTTP_204_NO_CONTENT
+        )

+ 64 - 0
apiviews/orders_local.py

@@ -0,0 +1,64 @@
+from django.shortcuts import get_object_or_404
+from rest_framework import viewsets, permissions
+from rest_framework.response import Response
+
+from webservice_running.models import OrdersLocal
+from webservice_running.serializer import OrdersLocalSerializer
+
+
+# from dbsynce.models import Orders, Service, ServiceCategory, Provider, Client
+# from sharix_admin.models import SharixUser
+# from tickets.models import Task
+# from tickets.serializer import TaskSerializer
+
+class OrdersLocalMVS(viewsets.ModelViewSet):
+    queryset = OrdersLocal.objects.all()
+    serializer_class = OrdersLocalSerializer
+    # permission_classes = [IsOwnerOrReadOnly]
+    permission_classes = [
+        permissions.IsAuthenticated
+    ]
+
+    def get_object(self):
+        """
+        Returns the object the view is displaying.
+
+        You may want to override this if you need to provide non-standard
+        queryset lookups.  Eg if objects are referenced using multiple
+        keyword arguments in the url conf.
+        """
+        # queryset = self.filter_queryset(self.get_queryset())
+        queryset = OrdersLocal.objects.select_related('order_synced__ticket')
+
+        # Perform the lookup filtering.
+        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
+
+        assert lookup_url_kwarg in self.kwargs, (
+                'Expected view %s to be called with a URL keyword argument '
+                'named "%s". Fix your URL conf, or set the `.lookup_field` '
+                'attribute on the view correctly.' %
+                (self.__class__.__name__, lookup_url_kwarg)
+        )
+
+        filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
+        obj = get_object_or_404(queryset, **filter_kwargs)
+
+        # May raise a permission denied
+        self.check_object_permissions(self.request, obj)
+
+        return obj
+
+    def update(self, request, *args, **kwargs):
+        partial = kwargs.pop('partial', False)
+        instance = self.get_object()  # OrdersLocal.objects.select_related('order_synced__ticket').get(id=1)
+        serializer = self.get_serializer(instance, data=request.data, partial=partial)
+        # for serializer in serializers:
+        serializer.is_valid(raise_exception=True)
+        self.perform_update(serializer)
+
+        if getattr(instance, '_prefetched_objects_cache', None):
+            # If 'prefetch_related' has been applied to a queryset, we need to
+            # forcibly invalidate the prefetch cache on the instance.
+            instance._prefetched_objects_cache = {}
+
+        return Response(serializer.data)

+ 12 - 0
apiviews/personinfo.py

@@ -0,0 +1,12 @@
+from django.contrib.auth import get_user_model
+from rest_framework import viewsets, permissions
+
+from webservice_running.serializer import PersonInfoSerializer
+
+
+class PersonInfoMVS(viewsets.ReadOnlyModelViewSet):
+    queryset = get_user_model().objects.all()
+    serializer_class = PersonInfoSerializer
+    permission_classes = [
+        permissions.IsAuthenticated
+    ]

+ 44 - 0
apiviews/preferreddrivers.py

@@ -0,0 +1,44 @@
+from django.db.models import CharField
+from django.db.models.functions import Cast
+from rest_framework import viewsets, permissions
+from rest_framework.response import Response
+
+from webservice_running.models import Preferreddrivers
+from webservice_running.serializer import PreferreddriversSerializer
+
+
+class PreferreddriversMVS(viewsets.ModelViewSet):
+    queryset = Preferreddrivers.objects.all()
+    serializer_class = PreferreddriversSerializer
+    permission_classes = [
+        permissions.IsAuthenticated
+    ]
+
+    def list(self, request, *args, **kwargs):
+        client = self.request.query_params.get('client')
+        queryset = Preferreddrivers.objects.all()
+        if client is not None:
+            queryset = queryset \
+                .annotate(client_int=Cast('client', output_field=CharField())) \
+                .filter(client_int=client)
+        serializer = self.get_serializer(queryset, many=True)
+        return Response(serializer.data)
+
+    def delete(self, request, *args, **kwargs):
+        client = self.request.query_params.get('client')
+        queryset = Preferreddrivers.objects.all()
+        if not client:
+            return Response(
+                {'error': 'client parameter is required'},
+                status=status.HTTP_400_BAD_REQUEST
+            )
+
+        queryset = queryset \
+            .annotate(client_int=Cast('client', output_field=CharField())) \
+            .filter(client_int=client)
+        queryset.delete()
+
+        return Response(
+            {'message': f'Objects with client {client} were deleted'},
+            status=status.HTTP_204_NO_CONTENT
+        )

+ 14 - 0
apps.py

@@ -0,0 +1,14 @@
+from django.apps import AppConfig
+
+from core.utils.AuthAPI import AuthAPI
+
+api = AuthAPI("<module_login>", "<module_password>")
+
+
+class WebserviceRunningConfig(AppConfig):
+    default_auto_field = 'django.db.models.BigAutoField'
+    name = 'webservice_running'
+
+# class OpenlocalConfig(AppConfig):
+#     default_auto_field = "django.db.models.BigAutoField"
+#     name = "openlocal"

+ 0 - 29
authorization-fog-pass.html

@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <meta name="viewport" content="width=device-width, initial-scale=1" />
-    <link rel="shortcut icon" type="image/png" href="https://animaproject.s3.amazonaws.com/home/favicon.png" />
-    <link rel="stylesheet" type="text/css" href="css/style.css" />
-  </head>
-  <body>
-    <div class="container-auth">
-
-      <div class="authfog-block">
-          <img class="logo400" src="img/logo_open.svg">
-          <form action="" method="" >
-            <p>Код для восстановления пароля был отправлен Вам по SMS на номер</p>
-            <p class="userNum">+7******1212</p>
-            <input type="number" name="phone">
-            <p class="resend">Отправить код повторно через</p>
-            <p id="secLeft">300 сек</p>
-            <div class="buttons">
-              <a id="enter" href="authorization.html">Войти</a>
-              <button type="submit" class="next">Далее</button>
-            </div>
-          </form>
-      </div>
-
-    </div>
-  </body>
-</html>

+ 0 - 28
authorization.html

@@ -1,28 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta charset="UTF-8" />
-    <meta name="viewport" content="width=device-width, initial-scale=1" />
-    <link rel="shortcut icon" type="image/png" href="https://animaproject.s3.amazonaws.com/home/favicon.png" />
-    <link rel="stylesheet" type="text/css" href="css/style.css" />
-  </head>
-  <body>
-    <div class="container-auth">
-
-      <div class="auth-block">
-          <img class="logo400" src="img/logo_open.svg">
-          <form action="personal_acc.html" method="">
-            <input type="text" placeholder="Телефон или e-mail" name="login">
-            <input type="password" placeholder="Пароль" name="password">        
-            <p id="incorrect">Проверьте корректность логина или пароля</p>
-            <a id="forgot-pass" href="authorization-fog-pass.html">Забыли пароль?</a>
-            <div class="buttons">
-              <a id="register" href="register.html">Регистрация</a>
-              <button type="submit" class="enter">Войти</button>
-            </div>
-          </form>
-      </div>
-
-    </div>
-  </body>
-</html>

+ 10 - 0
config.py

@@ -0,0 +1,10 @@
+# Подключение к базе данных
+host = "host"
+SSH_H = "46.138.247.90"
+user = "user"
+password = "password"
+port = 334
+db_name = "db_name"
+# Подключение к боту
+jid = "test@msg.sharix-app.org"
+jidpassword = "test1234@"

+ 0 - 727
css/style.css

@@ -1,727 +0,0 @@
-@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap');
-@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;500;600;700&display=swap');
-
-
-
-*{
-    margin: 0;
-    padding: 0;
-    font-family: 'Roboto', sans-serif;
-}
-
-main {
-    margin-top: 156px;
-}
-
-.wrapper {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    flex-wrap: wrap;
-}
-
-h2 {
-    font-size: 24px;
-}
-
-section {
-    margin-top: 26px;
-}
-
-section h2 {
-    margin-bottom: 35px;
-}
-
-input[type="number"]::-webkit-outer-spin-button,
-input[type="number"]::-webkit-inner-spin-button {
-  -webkit-appearance: none;
-  margin: 0;
-}
-
-
-/* header */
-
-
-header {
-    position: fixed;
-    margin-top: 11px;
-    top: 0;
-    left: 50%;
-    transform: translateY(-50%);
-    transform: translateX(-50%);
-    width: clamp(300px, 60vw, 1040px);
-    background: #FFFFFF;
-    box-shadow: 4px 5px 40px 0px #EEEEEE;
-    border-radius: 15px;
-    height: 60px;
-}
-
-header img {
-    margin: 9px 30px;
-}
-
-.logout {
-    position: fixed;
-    padding: 0;
-    margin-top: 15px;
-    top: 0;
-    left: 82%;
-    height: 70px;
-    width: 55px;
-}
-
-.logoutCircle {
-    position: absolute;
-    width: 55px;
-    height: 55px;
-    border-radius: 100%;
-    background: #FFFFFF;
-    box-shadow: 4px 5px 40px #EEEEEE;
-}
-
-.logoutText {
-    font-family: 'Open Sans', sans-serif;
-    position: absolute;
-    left: 0;
-    right: 0;
-    bottom: 0;
-    text-align: center;
-    font-size: 10px;
-    text-decoration: none;
-    color: #b20000;
-}
-
-.logoutCircle img {
-    display: block;
-    margin: auto;
-    margin-top: 30%;
-    margin-bottom: 5px;
-}
-
-
-/* footer */
-
-
-footer {
-    padding-top: 23px;
-    padding-bottom: 23px;
-    margin-top: 48px;
-    background: #F3F3F3;
-}
-
-footer>ul {
-    margin-left: auto;
-    margin-right: auto;
-    width: clamp(300px, 60vw, 1174px);
-    list-style: none;
-    display: flex;
-    justify-content: end;
-    flex-wrap: wrap;
-}
-
-footer li {
-    margin-left: 20px;
-}
-
-footer a {
-    color: #000;
-    text-decoration: none;
-    font-size: 14px;
-}
-
-footer #deleteAcc {
-    margin-right: auto;
-    margin-left: 0;
-}
-
-@media (max-width: 1000px) {
-    footer>ul {
-        flex-direction: column;
-    }
-    footer #deleteAcc {
-        margin-right: 0;
-        margin-left: 0;
-    }
-
-    footer li {
-        margin-left: 0px;
-    }
-    
-}
-
-
-/* personal_acc */
-
-
-.container-acc {
-    width: clamp(300px, 60vw, 650px);
-    margin-left: auto;
-    margin-right: auto;
-    margin-top: 10vh;
-}
-
-
-
-.container-acc .person {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    border: 1px solid #C4C4C4;
-    box-sizing: border-box;
-    border-radius: 32px;
-    padding: 25px 32px;
-    margin-bottom: 24px;
-}
-
-.container-acc #userPhoto {
-    border-radius: 100%;
-}
-
-.container-acc .aboutUser {
-    margin-right: auto;
-    margin-left: 32px;
-}
-
-.container-acc .name {
-    font-size: 36px;
-    margin-bottom: 22px;
-}
-
-.container-acc .email {
-    font-size: 18px;
-    color: #A3A3A3;
-}
-
-.container-acc #settings {
-    margin-bottom: 32px;
-    cursor: pointer;
-}
-
-@media (max-width: 740px) {
-    .container-acc .person {
-        flex-direction: column;
-        text-align: center;
-    }
-
-    .container-acc .aboutUser {
-        margin: 0;
-        margin-top: 10px;
-    }
-    
-
-    .container-acc #settings {
-        margin-bottom: 0;
-        margin-top: 20px;
-    }
-}
-
-
-
-
-
-.container-acc .bnh>div {
-    border: 1px solid #C4C4C4;
-    box-sizing: border-box;
-    width: 311px;
-    min-height: 144px;
-    border-radius: 32px;
-    padding: 33px 21px;
-    margin-bottom: 24px;
-}
-
-.container-acc .bnh h2 {
-    display: inline-block;
-    margin-bottom: 20px;
-}
-
-.container-acc .bnh img {
-    float: right;
-    margin-right: 19px;
-}
-
-.container-acc .balance img {
-    margin-top: 5px;
-}
-
-.container-acc .history img {
-    margin-top: 10px;
-}
-
-.container-acc .balanceValue {
-    font-size: 24px;
-}
-
-.container-acc .historyElement { 
-    font-size: 18px;
-    width: 30px;
-    color: #4a4a4a;
-}
-
-.container-acc .historyElement p {
-    white-space: nowrap;
-    overflow: hidden;
-    text-overflow: ellipsis;
-}
-
-
-
-
-.container-acc .service {
-    border: 1px solid #C4C4C4;
-    box-sizing: border-box;
-    width: 311px;
-    min-height: 140px;
-    border-radius: 32px;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    margin-bottom: 24px;
-}
-
-@media (max-width: 1040px) {
-    .container-acc .bnh,
-    .container-acc .services,
-    .container-acc .courses {
-        flex-direction: column;
-    }
-}
-
-
-.container-acc .course {
-    box-sizing: border-box;
-    width: 317px;
-    min-height: 188px;
-    background: #4a4a4a;
-    border: 1px solid #000;
-    box-sizing: border-box;
-    border-radius: 30px;
-    padding-top: 18px;
-    padding-left: 22px;
-    padding-bottom: 18px;
-    margin-bottom: 24px;
-}
-
-.container-acc .courses a {
-    color: #fff;
-    font-size: 32px;
-    font-weight: 700;
-    text-decoration: none;
-}
-
-.container-acc .courses p {
-    margin-top: 15px;
-}
- 
-.container-acc .modal {
-    display: none; /* Hidden by default */
-    position: fixed; /* Stay in place */
-    z-index: 1; /* Sit on top */
-    padding-top: 30vh; /* Location of the box */
-    left: 0;
-    top: 0;
-    width: 100%; /* Full width */
-    height: 100%; /* Full height */
-    overflow: scroll; /* Enable scroll if needed */
-    background-color: rgb(0,0,0); /* Fallback color */
-    background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
-}
-
-@media (max-width: 800px) {
-    .container-acc .modal {
-        padding-top: 20px;
-    }
-}
-  
-  
-.container-acc .modal-content {
-    position: relative;
-    margin: auto;
-    padding-left: 24px;
-    padding-right: 24px;
-    padding-bottom: 30px;
-    width: clamp(300px, 60vw, 493px);
-    background: #FFFFFF;
-    border: 1px solid #CACACA;
-    box-sizing: border-box;
-    border-radius: 24px;
-
-}
-
-.container-acc .modal form {
-    display: flex;
-    flex-wrap: wrap;
-    justify-content: space-between;
-}
-
-.container-acc .modal input {
-    padding: 15px;
-    margin-top: 15px;
-    background: #FFFFFF;
-    border: 1px solid #9D9D9D;
-    box-sizing: border-box;
-    border-radius: 6px;
-    height: 45px;
-}
-
-.container-acc .formElement {
-    margin-top: 32px;
-    font-size: 14px;
-    font-weight: 600;
-    
-}
-
-
-.container-acc #name {
-    width: 216px; 
-}
-
-.container-acc #surname {
-    width: 208px;
-}
-
-.container-acc #email {
-    width: 253px;
-}
-
-.container-acc #phone {
-    width: 171px;
-    
-}
-
-.container-acc .formBtns {
-    margin-top: 58px;
-    margin-left: auto;
-    font-family: 'Open Sans', sans-serif;
-}
-
-.container-acc #closeModal {
-    font-size: 14px;
-    font-weight: 600;
-    color: #479FF8;
-    margin-right: 30px;
-}
-
-.container-acc #save {
-    font-size: 14px;
-    font-weight: 700;
-    outline: none;
-    border: none;
-    width: 135px;
-    height: 35px;
-    color: #fff;
-    background: linear-gradient(226.01deg, #00A4FF -13.24%, #0076C7 119.18%);
-    border-radius: 6px;
-    cursor: pointer;
-}
-
-
-/* payment */
-
-
-.column-wrapper {
-    width: clamp(300px, 60vw, 790px);
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    text-align: center;
-    margin-left: auto;
-    margin-right: auto;
-}
-
-.column-wrapper p {
-    font-family: 'Open Sans', sans-serif;
-    font-size: 18px;
-    color: #5F5E5E;
-    line-height: 24.51px;
-    margin-bottom: 25px;
-}
-
-.column-wrapper form {
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    text-align: center;
-    margin-left: auto;
-    margin-right: auto;
-}
-
-
-
-.req-wrapper .payImages {
-    width: clamp(300px, 60vw, 315px);
-    display: flex;
-    justify-content: space-around;
-    flex-wrap: wrap;
-    align-items: center;
-    margin-top: 9px;
-}
-
-.req-wrapper .payImages img {
-    height: 100%;
-    width: auto;
-    margin-bottom: 40px;
-}
-
-.req-wrapper #sum {
-    width: 309px;
-    height: 52px;
-    background: #FFFFFF;
-    border: 1px solid #9D9D9D;
-    box-sizing: border-box;
-    border-radius: 6px;
-    padding-left: 10px;
-    margin-top: 15px;
-    margin-bottom: 34px;
-
-    font-size: 18px;
-}
-
-.req-wrapper #sum::placeholder{
-    color: #C4C4C4;
-}
-
-.req-wrapper #pay {
-    font-size: 18px;
-    font-weight: 700;
-    outline: none;
-    border: none;
-    width: 211px;
-    height: 52px;
-    color: #fff;
-    background: #4a4a4a;
-    border-radius: 11px;
-    cursor: pointer;
-}
-
-.req-wrapper #back {
-    color: #4a4a4a;
-    font-family: 'Open Sans', sans-serif;
-    font-weight: 600;
-    font-size: 18px;
-    margin-top: 20px;
-    
-}
-
-.req-wrapper + hr {
-    margin-left: auto;
-    margin-right: auto;
-    margin-top: 60px;
-    margin-bottom: 14px;
-    width: clamp(300px, 60vw, 750px);
-}
-
-.container-req {
-    width: clamp(300px, 60vw, 820px);
-    margin-left: auto;
-    margin-right: auto;
-    margin-top: 40px;
-}
-
-.requisites>div {
-    background: #FFFFFF;
-    border: 1px solid #C4C4C4;
-    box-sizing: border-box;
-    border-radius: 32px;
-    padding-left: 34px;
-    padding-right: 34px;
-    padding-top: 20px;
-    padding-bottom: 10px;
-}
-
-.requisites>div p {
-    font-size: 18px;
-    color: #5F5E5E;
-    margin-bottom: 20px;
-}
-
-.requisites>div a {
-    color: #004879;
-}
-
-.footer-pay {
-    margin-top: 25px;
-}
-
-.getPay-footer {
-    margin-top: 0;
-}
-
-
-/* payment_mess */
-
-
-.fullH {
-    text-align: center;
-    display: flex;
-    flex-direction: column;
-    margin-top: 0;
-    height: 50em;
-}
-
-
-.fullH p {
-    font-size: 36px;
-    font-weight: 700;
-    margin-top: 230px;
-    margin-bottom: 37px;
-}
-
-.fullH #back {
-    font-family: 'Roboto', sans-serif;
-    font-weight: 600;
-    color: #4a4a4a;
-    font-size: 18px;
-}
-
-
-/* auths */
-
-
-.auth-block,
-.authfog-block {
-    width: clamp(300px, 60vw, 544px);
-    min-height: 559px;
-    border-radius: 32px;
-    box-sizing: border-box;
-    padding: 86px 106px;
-    border: 1px solid #9d9d9de3;
-    margin-left: auto;
-    margin-right: auto;
-    margin-top: 25vh;
-}
-
-.logo400 {
-    display: block;
-    width: 204px;
-    margin-left: auto;
-    margin-right: auto;
-}
-
-.auth-block form,
-.authfog-block form {
-    margin-top: 60px;
-    margin-left: auto;
-    margin-right: auto;
-    width: 312px;
-}
-
-
-.auth-block input,
-.authfog-block input {
-    display: block;
-    height: 45px;
-    box-sizing: border-box;
-    width: 100%;
-    border-radius: 6px;
-    padding: 0px 12px;
-    background: #FFFFFF;
-    border: 1px solid #9D9D9D;
-    font-size: 18px;
-    
-}
-
-.auth-block input[name="password"] {
-    margin-top: 20px;
-    margin-bottom: 15px;
-}
-
-.auth-block #incorrect {
-    display: none;
-    color: #ff1616;
-    font-size: 14px;
-    margin-top: 30px;
-    margin-bottom: 30px;
-}
-
-.auth-block #forgot-pass {
-    color: #4a4a4a;
-    font-weight: 700;
-    font-size: 14px;
-}
-
-.auth-block .buttons,
-.authfog-block .buttons {
-    margin-top: 35px;
-    display: flex;
-    justify-content: space-between;
-    flex-wrap: wrap;
-    align-items: center;
-}
-
-.auth-block #register,
-.authfog-block #enter {
-    color: #4a4a4a;
-    font-weight: 600;
-    font-size: 14px;
-}
-
-.auth-block .enter,
-.authfog-block .next {
-    box-sizing: border-box;
-    width: 103px;
-    height: 35px;
-    font-weight: 700;
-    font-family: 'Open Sans', sans-serif;
-    color: #fff;
-    font-size: 14px;
-    cursor: pointer;
-    outline: none;
-    border: none;
-    background: #4a4a4a;
-    border-radius: 7px;
-}
-
-.authfog-block {
-    padding: 60px 98px;
-}
-
-.authfog-block form {
-    text-align: center;
-    width: 337px;
-}
-
-.authfog-block form p {
-    font-size: 18px;
-}
-
-.authfog-block .userNum {
-    margin-top: 44px;
-    font-weight: 700;
-}
-
-
-.authfog-block input[name="phone"] {
-    margin-top: 20px;
-    margin-bottom: 20px;
-    width: 207px;
-    margin-left: auto;
-    margin-right: auto;
-}
-
-.authfog-block .resend {
-    font-weight: 700;
-    color: #a7a7a7;
-}
-
-.authfog-block #secLeft {
-    color: #a7a7a7;
-    font-weight: 300;
-    margin-top: 8px;
-}
-
-.authfog-block .buttons {
-    margin-top: 42px;
-}
-
-@media (max-width: 830px) {
-    .auth-block,
-    .authfog-block {
-        padding: 100px 10px;
-    }
-
-    .auth-block form,
-    .authfog-block form {
-        margin-top: 30px;
-        width: 200px;
-    }
-}

+ 14 - 0
forms.py

@@ -0,0 +1,14 @@
+from django import forms
+
+from webservice_running.models import OrdersLocal
+
+
+class OrderRegForm(forms.ModelForm):
+    class Meta:
+        model = OrdersLocal
+        fields = '__all__'
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        for field in self.fields.values():
+            field.widget.attrs['class'] = 'form-control'

+ 6 - 0
handlers/.gitignore

@@ -0,0 +1,6 @@
+__pycache__/
+env/
+config.py
+*bottickets.log
+*.log
+*~

+ 75 - 0
handlers/BotClass.py

@@ -0,0 +1,75 @@
+import json
+import sys
+from datetime import datetime
+
+import xmpp
+
+
+# Основной класс бота
+class JabberBot:
+    def __init__(self, jid, password, port):
+        self.jidd = jid
+        jid = xmpp.JID(jid)
+        self.user, self.server, self.password, self.port = jid.getNode(), jid.getDomain(), password, port
+        self.connect()
+        self.auth()
+
+    # Метод проверки подключения к серверу xmpp
+    def connect(self):
+        self.conn = xmpp.Client(self.server, self.port, debug=[])
+        conn_result = self.conn.connect()
+        if not conn_result:
+            print("Can't connect to server!\n")
+            sys.exit(1)
+
+    # Метод аутентификации
+    def auth(self):
+        # по идее, тут может быть актуально также передать информацию относительно порта, например
+        auth_result = self.conn.auth(self.user, self.password)
+        if not auth_result:
+            print(self.user, self.password)
+            print("Can't to authorize!\n")
+            sys.exit(1)
+
+    # Метод для привязки функций к событиям
+    def register_handler(self, name, handler):
+        self.conn.RegisterHandler(name, handler)
+
+    def step_on(self):
+        try:
+            self.conn.Process(1)  # с какой частотой происходит подключение к серверу, в данном случае каждую секунду
+        except KeyboardInterrupt:
+            return 0
+        return 1
+
+    def bot_log(self, message):
+        # надо строчку лога сделать более информативной
+        logfile = open("logs/" + datetime.now().strftime('%Y-%m-%d') + "-" + self.user + ".log", "a")
+        logfile.write(message)
+        logfile.close()
+        print(message)
+
+    def send_notification(self, recipient, message):
+        self.conn.send(xmpp.Message(recipient, message))
+        self.bot_log("Message sent successfully" + " " + recipient + " " + message)
+
+    # recipient - это конкретный jid следующего обработчика заявки, ticket - json с заявкой.
+    def proceed_status(self, recipient, ticket):
+        # тут могут быть различные проверки дополнительные, а так вообще эта функция нужна для передачи заявки на обработку следующему
+        jsonTicket = json.dumps(ticket.__dict__)
+        self.conn.send(xmpp.Message(recipient, jsonTicket))
+        self.bot_log("Message sent successfully" + " " + recipient + " " + jsonTicket)
+
+    # сюда можно как параметры передавать переменную для значения Process в вызываемой функции, а также передавать информацию о том, какой из обработчиков ввызывать в бесконечном цикле
+    def start(self, handler, *args):
+        self.conn.sendInitPresence()  # статус аккаунта бота (активен или нет)
+        print("Bot started!")
+        while self.step_on():
+            # это вызов конкретной функции для обработки статуса конкретным ботом
+            # handler(args)
+            handler()
+            pass
+
+    def stop(self):
+        # Disconnect from the Jabber server
+        self.client.disconnect()

+ 75 - 0
handlers/README.md

@@ -0,0 +1,75 @@
+# Open Template Bot
+
+#### Simple example for processing orders
+
+## Install and run
+
+1. Rename **config_template.py** to **config.py**
+2. Create env
+
+```
+python -m venv env #for Windows
+python3 -m venv env #for Linux
+```
+
+3. Activate env
+
+```
+.\env\Scripts\activate #Windows
+source env/bin/activate #Linux
+```
+
+4. Instatt requirements
+
+```
+pip3 install -r requirements.txt
+```
+
+5. Run Bot
+
+```
+python3 open_template_bot.py
+```
+
+## Testing
+
+https://democonv.sharix-app.org/ - testing client
+
+## Users recommended for testing
+
+user: test@ej.sharix-app.org
+user: test1@ej.sharix-app.org
+
+## Useful commands for Ejabberctl while testing Bot
+
+```
+ejabberdctl register $username ej $password
+
+ejabberdctl change-password User Host newPassword
+
+ejabberdctl check_account user1 localhost
+
+ejabberdctl unregister badlop3 localhost
+ejabberdctl registered_users localhost
+ejabberdctl help registered_users
+```
+
+# Create MUC room
+
+```
+ejabberdctl create_room room_name muc_service xmpp_domain
+```
+
+# Destroy MUC room
+
+```
+#ejabberdctl destroy_room room_name muc_service
+```
+
+# List unused MUC rooms
+
+```
+ejabberdctl rooms_unused_list xmpp_domain number_of_days
+```
+
+https://docs.ejabberd.im/admin/ejabberdctl/muc-admin/

+ 16 - 0
handlers/applications.json

@@ -0,0 +1,16 @@
+{
+  "applications": [
+    {
+      "id": "1",
+      "desc": "описание 1"
+    },
+    {
+      "id": "2",
+      "desc": "описание 2"
+    },
+    {
+      "id": "3",
+      "desc": "описание 3"
+    }
+  ]
+}

+ 11 - 0
handlers/bin/gen-passwords.py

@@ -0,0 +1,11 @@
+import hashlib
+
+import config
+
+botlist = config.BOTLIST
+
+for i in range(len(botlist)):
+    print(
+        botlist[i],
+        hashlib.md5((botlist[i] + config.PASSWORD).encode('utf-8')).hexdigest()
+    )

+ 15 - 0
handlers/bin/gen_users.sh

@@ -0,0 +1,15 @@
+#!/bin/bash
+
+#берем список ботов и паролей к ним и создаем или апдейтим пользователей (если уже созданы) на сервере
+python3 gen-passwords.py | while IFS=' ' read -ra line; do ejabberdctl register ${line[0]} ej.sharix-app.org ${line[1]}; done;
+python3 gen-passwords.py | while IFS=' ' read -ra line; do ejabberdctl change-password ${line[0]} ej.sharix-app.org ${line[1]}; done;
+#ejabberdctl register $username ej $password
+
+#ejabberdctl change-password User Host newPassword
+
+#ejabberdctl check_account user1 localhos
+#
+#ejabberdctl unregister badlop3 localhost
+#ejabberdctl registered_users localhost
+#ejabberdctl help registered_userst
+

+ 18 - 0
handlers/bin/gen_web_users.py

@@ -0,0 +1,18 @@
+import hashlib
+
+import config
+import jsonAndRequest as jsreq
+
+botlist = config.BOTLIST
+
+for i in range(len(botlist)):
+    print(
+        botlist[i],
+        hashlib.md5((botlist[i] + config.PASSWORD).encode('utf-8')).hexdigest()
+    )
+    print(jsreq.createUser(
+        botlist[i],
+        botlist[i],
+        hashlib.md5((botlist[i] + config.PASSWORD).encode('utf-8')).hexdigest(),
+        config.API_URL + "my/api/v1/platform/sharix-users/"
+    ))

+ 10 - 0
handlers/classes/Answer.py

@@ -0,0 +1,10 @@
+class Answer(object):
+    def __init__(
+            self,
+            order_id,
+            provider,
+            answer
+    ):
+        self.order_id = order_id
+        self.provider = provider
+        self.answer = answer

+ 248 - 0
handlers/classes/Order.py

@@ -0,0 +1,248 @@
+class Order(object):
+    def __init__(
+            self,
+            id,
+            ticket,
+            status,
+            title,
+            note,
+            id_metaservice,
+            is_global,
+            is_visible,
+            service,
+            service_category,
+            time_created,
+            time_placed,
+            time_start=None,
+            time_start_predicted=None,
+            time_finish_predicted=None,
+            time_start_real=None,
+            time_finish_real=None,
+            order_place_type=None,
+            order_place_start=None,
+            order_place_start_gps=None,
+            order_place_start_real=None,
+            order_place_start_real_gps=None,
+            order_place_finish_predicted=None,
+            order_place_finish_predicted_gps=None,
+            order_place_finish_real=None,
+            order_place_finish_real_gps=None,
+            predicted_price=None,
+            real_price=None,
+            payment_transaction_id=None,
+            rating_id=None,
+            provider=None,
+            provider_screen_name=None,
+            receiver=None,
+            receiver_screen_name=None,
+            client=None,
+            resource=None,
+            attempts=None,
+            asap=None,
+            money_limit=None,
+            tasks=None,
+            proceed_before_arrival=False,
+            confirmation=False
+    ):
+        self.id = id
+        self.ticket = ticket
+        self.status = status
+        self.title = title
+        self.note = note
+        self.id_metaservice = id_metaservice
+        self.is_global = is_global
+        self.is_visible = is_visible
+        self.service = service
+        self.service_category = service_category
+        self.time_created = time_created
+        self.time_placed = time_placed
+        self.time_start = time_start
+        self.time_start_predicted = time_start_predicted
+        self.time_finish_predicted = time_finish_predicted
+        self.time_start_real = time_start_real
+        self.time_finish_real = time_finish_real
+        self.order_place_type = order_place_type
+        self.order_place_start = order_place_start
+        self.order_place_start_gps = order_place_start_gps
+        self.order_place_start_real = order_place_start_real
+        self.order_place_start_real_gps = order_place_start_real_gps
+        self.order_place_finish_predicted = order_place_finish_predicted
+        self.order_place_finish_predicted_gps = order_place_finish_predicted_gps
+        self.order_place_finish_real = order_place_finish_real
+        self.order_place_finish_real_gps = order_place_finish_real_gps
+        self.predicted_price = predicted_price
+        self.real_price = real_price
+        self.payment_transaction_id = payment_transaction_id
+        self.rating_id = rating_id
+        self.provider = provider
+        self.provider_screen_name = provider_screen_name
+        self.receiver = receiver
+        self.receiver_screen_name = receiver_screen_name
+        self.client = client
+        self.resource = resource
+        self.attempts = attempts
+        self.asap = asap
+        self.money_limit = money_limit
+        self.tasks = tasks
+        self.proceed_before_arrival = proceed_before_arrival
+        self.confirmation = confirmation
+
+    def __str__(self):
+        return "{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12}, {13}, {14}, {15}, {16}, {17}, {18}, {19}, {20}, {21}, {22}, {23}, {24}, {25}, {26}, {27}, {28}, {29}, {30}, {31}, {32}, {33}, {34}, {35}, {36}, {37}, {38}".format(
+            self.id,
+            self.ticket,
+            self.status,
+            self.title,
+            self.note,
+            self.id_metaservice,
+            self.is_global,
+            self.is_visible,
+            self.service,
+            self.service_category,
+            self.time_created,
+            self.time_placed,
+            self.time_start,
+            self.time_start_predicted,
+            self.time_finish_predicted,
+            self.time_start_real,
+            self.time_finish_real,
+            self.order_place_type,
+            self.order_place_start,
+            self.order_place_start_gps,
+            self.order_place_start_real,
+            self.order_place_start_real_gps,
+            self.order_place_finish_predicted,
+            self.order_place_finish_predicted_gps,
+            self.order_place_finish_real,
+            self.order_place_finish_real_gps,
+            self.predicted_price,
+            self.real_price,
+            self.payment_transaction_id,
+            self.rating_id,
+            self.provider,
+            self.provider_screen_name,
+            self.receiver,
+            self.receiver_screen_name,
+            self.client,
+            self.resource,
+            self.attempts,
+            self.asap,
+            self.money_limit,
+            self.tasks,
+            self.proceed_before_arrival,
+            self.confirmation
+        )
+
+
+# Тестовый класс User и Address (ВАЖНО!!!) поля классов должны называться также как и поля json объекта
+'''
+#Full json order example
+https://wiki.sharix-app.org/doku.php/open/tech/dev/sharix_open_-_primery_json
+
+{
+
+"ticket": 123,
+"status": 111,
+
+"priority": 1, 
+"title": "123",
+"note": "123",
+"due_date": 2023-05-15T17:16:22.955601Z,
+
+"id_metaservice": 1,
+"is_global": false,
+"is_visible": false,
+"service": 1,
+"service_category": 1,
+
+"status_changed_date": "2023-05-15T17:16:22.955601Z",
+"time_placed": "2023-05-15T16:40:32.179777Z",
+"time_start": "2023-05-15T16:40:32.179777Z",
+"time_start_predicted": "2023-05-15T16:40:32.179777Z",
+"time_finish_predicted": "2023-05-15T16:40:32.179777Z",
+"time_start_real": "2023-05-15T16:40:32.179777Z",
+"time_finish_real": "2023-05-15T16:40:32.179777Z",
+
+"order_place_type": "address",
+"order_place_start": "р-н Беговой",
+"order_place_start_gps": "55.751941, 37.607513",
+"order_place_start_sector": 4,
+"order_place_start_real": "р-н Беговой",
+"order_place_start_real_gps": "55.751941, 37.607513",
+"order_place_finish_predicted": "р-н Мещанский",
+"order_place_finish_predicted_gps": "55.751941, 37.607513",
+"order_place_finish_sector": 4,
+"order_place_finish_real": "р-н Мещанский",
+"order_place_finish_real_gps": "55.751941, 37.607513",
+
+"predicted_price": 1000,
+"real_price": 1001,
+"payment_transaction_id": 1,
+"rating_id": 1,
+
+"provider": 1,
+"provider_screen_name": "Vasya Ispolnitelev",
+"receiver": 1,
+"receiver_screen_name": "Marfa Clientovna",
+"client": 1,
+"client_screen_name": "Fedor Client",
+"resource": 1,
+"attempts": null
+}
+'''
+# надо адаптировать класс к новому формату JSON
+# class Order(object):
+#     def __init__(self, id,order_synced, ticket, status, title, note, due_date, id_metaservice, is_global, is_visible, service, service_category, status_changed_date,time_created, time_placed, time_start=None, time_start_predicted=None, time_finish_predicted=None, time_start_real=None, time_finish_real=None, order_place_type=None, order_place_start=None, order_place_start_gps=None, order_place_start_real=None, order_place_start_real_gps=None, order_place_finish_predicted=None, order_place_finish_predicted_gps=None, order_place_finish_real=None, order_place_finish_real_gps=None, predicted_price=None, real_price=None, payment_transaction_id=None, rating_id=None, provider=None, provider_screen_name=None, receiver=None, receiver_screen_name=None, client=None, resource=None, attempts=None, asap=None):
+#         self.order_synced = order_synced
+#         self.id = id
+#         self.ticket = ticket
+#         self.status = status
+
+#         self.title = title
+#         self.note = note
+#         self.due_date = due_date
+
+#         self.id_metaservice = id_metaservice
+#         self.is_global = is_global
+#         self.is_visible = is_visible
+#         self.service = service
+#         self.service_category = service_category
+
+#         self.status_changed_date = status_changed_date
+#         self.time_created = time_created
+#         self.time_placed = time_placed
+#         self.time_start = time_start
+#         self.time_start_predicted = time_start_predicted
+#         self.time_finish_predicted = time_finish_predicted
+#         self.time_start_real = time_start_real
+#         self.time_finish_real = time_finish_real
+
+#         self.order_place_type =order_place_type
+#         self.order_place_start = order_place_start
+#         self.order_place_start_gps = order_place_start_gps
+#         self.order_place_start_real = order_place_start_real
+#         self.order_place_start_real_gps = order_place_start_real_gps
+#         self.order_place_finish_predicted = order_place_finish_predicted
+#         self.order_place_finish_predicted_gps = order_place_finish_predicted_gps
+#         self.order_place_finish_real = order_place_finish_real
+#         self.order_place_finish_real_gps = order_place_finish_real_gps
+
+#         self.predicted_price = predicted_price
+#         self.real_price = real_price
+
+#         self.payment_transaction_id = payment_transaction_id
+#         self.rating_id = rating_id
+
+#         self.provider = provider
+#         self.provider_screen_name = provider_screen_name
+#         self.receiver = receiver
+#         self.receiver_screen_name = receiver_screen_name
+#         self.client = client
+#         self.resource = resource
+#         self.attempts = attempts
+#         self.asap = asap
+#         #доделать до конца по аналогии с закоммиченным json
+#     def __str__(self):
+#         return "{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12}, {13}, {14}, {15}, {16}, {17}, {18}, {19}, {20}, {21}, {22}, {23}, {24}, {25}, {26}, {27}, {28}, {29}, {30}, {31}, {32} , {33} ,{34}".format(self.order_synced, self.id, self.ticket, self.status, self.title, self.note, self.due_date, self.id_metaservice, self.is_global, self.is_visible, self.service, self.service_category, self.status_changed_date, self.time_created,self.time_placed, self.time_start, self.time_start_predicted, self.time_finish_predicted, self.time_start_real, self.time_finish_real, self.order_place_type, self.order_place_start, self.order_place_start_gps, self.order_place_start_real, self.order_place_start_real_gps, self.order_place_finish_predicted, self.order_place_finish_predicted_gps, self.order_place_finish_real, self.order_place_finish_real_gps, self.predicted_price, self.real_price, self.payment_transaction_id, self.rating_id, self.provider, self.provider_screen_name, self.receiver, self.receiver_screen_name, self.client, self.resource, self.attempts, self.asap)
+
+# \n добавляете в местах с пустой строкой в шаблоне

+ 97 - 0
handlers/classes/OrderTicket.py

@@ -0,0 +1,97 @@
+class OrderTicket(object):
+    def __init__(
+            self,
+            service_category,
+            driverSearchEngine,
+            comment,
+            arrivalTime,
+            additionalServices,
+            tasks,
+            spendingLimit,
+            isWithPaymentDocument,
+            id,
+            isProceedBeforeArrival
+    ):
+        self.service_category = service_category
+        self.driverSearchEngine = driverSearchEngine
+        self.comment = comment
+        self.arrivalTime = arrivalTime
+        self.additionalServices = additionalServices
+        self.tasks = tasks
+        self.spendingLimit = spendingLimit
+        self.isWithPaymentDocument = isWithPaymentDocument
+        self.id = id
+        self.isProceedBeforeArrival = isProceedBeforeArrival
+
+
+# ticket json example
+'''
+{
+        "id": 2,
+        "status": 111,
+        "created_date": "2023-05-15",
+        "status_changed_date": "2023-05-15T17:16:22.955601Z",
+        "priority": 0,
+        "title": "Test",
+        "note": "{\n    \n    \"ticket\": 1,\n    \"state\": 1,\n    \"id_metaservice\": 1,\n    \"is_global\": false,\n    \"is_visible\": false,\n    \"service\": 1,\n    \"service_category\": 1,\n\n    \"time_placed\": 1}"
+        "due_date": "2023-05-15",
+        "task_list": 10,
+        "created_by": 1,
+        "type": 1,
+        "assigned_to": 1
+}
+'''
+
+# ticket minimal example
+'''
+{
+        "id": 2,
+        "status": 111,
+        "created_date": "2023-05-15",
+        "status_changed_date": "2023-05-15T17:16:22.955601Z",
+        "priority": 0,
+        "title": null,
+        "note": null,
+        "due_date": null,
+        "task_list": 10,
+        "created_by": 1,
+        "type": 1,
+        "assigned_to": null
+}
+{
+  "service_category": 2,
+  "driverSearchEngine": 0,
+  "comment": "Yyyy",
+  "arrivalTime": "2023-12-07T14:39:54Z",
+  "additionalServices": [],
+  "tasks": [
+    {
+      "text": "Eeee",
+      "address": "Jjjj"
+    }
+  ],
+  "spendingLimit": 6668,
+  "isWithPaymentDocument": true,
+  "id": 294830,
+  "isProceedBeforeArrival": true
+}
+
+'''
+
+# class OrderTicketOLD(object):
+#     def __init__(self, id, status, created_date, status_changed_date, priority, title=None, note=None, due_date=None, task_list=None, created_by=None, type=None, assigned_to=None):
+#         self.id = id
+#         self.status = status
+#         self.created_date = created_date
+#         self.status_changed_date = status_changed_date
+#         self.priority = priority
+#         self.title = title
+#         self.note = note
+#         self.due_date = due_date
+#         self.task_list = task_list
+#         self.created_by = created_by
+#         self.type = type
+#         self.assigned_to = assigned_to
+
+#     def  __str__(self):
+#         return "{0}, {1}, {2}, {3}, {4}, {5}, {6},\n{7}, {8}, {9}, {10}, {11}\n".format(self.id, self.status, self.created_date, self.status_changed_date, self.priority, self.title, self.note, self.due_date, self.task_list, self.created_by, self.type, self.assigned_to)

+ 78 - 0
handlers/classes/Ticket.py

@@ -0,0 +1,78 @@
+from datetime import datetime
+from config import DEFAULT_INTERVAL_ATTEMPTS
+
+class Ticket(object):
+    def __init__(
+            self,
+            id,
+            status,
+            ticket_list,
+            ticket_type,
+            title,
+            created_at,
+            updated_at,
+            due_date,
+            priority,
+            created_by,
+            assigned_to=None,
+            note=None,
+
+            interval_attempts: int = DEFAULT_INTERVAL_ATTEMPTS
+    ):
+        self.id = id
+        self.status = status
+        self.ticket_list = ticket_list
+        self.ticket_type = ticket_type
+        self.title = title
+        self.created_at = created_at
+        self.updated_at = updated_at
+        self.due_date = due_date
+        self.priority = priority
+        self.created_by = created_by
+        self.assigned_to = assigned_to
+        self.note = note
+
+        self.interval_attempts = interval_attempts
+
+    def __str__(self):
+        return "{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}".format(
+            self.id,
+            self.status,
+            self.ticket_list,
+            self.ticket_type,
+            self.title,
+            self.created_at,
+            self.updated_at,
+            self.due_date,
+            self.priority,
+            self.created_by,
+            self.assigned_to
+        )
+
+    def to_dict(self):
+        """ Method to convert the object to a dictionary, if needed for JSON responses or serialization """
+        return {
+            "id": self.id,
+            "status": self.status,
+            "ticket_list": self.ticket_list,
+            "ticket_type": self.ticket_type,
+            "title": self.title,
+            "created_at": self.created_at,
+            "updated_at": self.updated_at,
+            "due_date": self.due_date,
+            "priority": self.priority,
+            "created_by": self.created_by,
+            "assigned_to": self.assigned_to,
+            "note": self.note
+        }
+
+    def update_status(self, new_status):
+        self.status = new_status
+        self.updated_at = datetime.now().isoformat()
+
+    def assign_to(self, user_id):
+        self.assigned_to = user_id
+
+    def get_summary(self):
+        return f"Ticket '{self.title}' (ID: {self.id}) - Status: {self.status}, Priority: {self.priority}"
+

+ 38 - 0
handlers/classes/Ticket_user.py

@@ -0,0 +1,38 @@
+class Ticket_user(object):
+    def __init__(
+            self,
+            id,
+            status,
+            title,
+            ticket_type,
+            created_at,
+            updated_at,
+            due_date,
+            priority,
+            created_by,
+            assigned_to
+    ):
+        self.id = id
+        self.status = status
+        self.title = title
+        self.ticket_type = ticket_type
+        self.created_at = created_at
+        self.updated_at = updated_at
+        self.due_date = due_date
+        self.priority = priority
+        self.created_by = created_by
+        self.assigned_to = assigned_to
+
+    def __str__(self):
+        return "{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}\n".format(
+            self.id,
+            self.status,
+            self.title,
+            self.ticket_type,
+            self.created_at,
+            self.updated_at,
+            self.due_date,
+            self.priority,
+            self.created_by,
+            self.assigned_to
+        )

+ 11 - 0
handlers/conf/bin/install.sh

@@ -0,0 +1,11 @@
+
+mkdir -p /etc/systemd/system/service-monitor
+
+cp -r ./conf/service-monitor /etc/systemd/system/service-monitor
+
+cp ./conf/bin/service-failure-check.sh /usr/local/bin
+cp ./conf/bin/service-watcher.sh /usr/local/bin
+
+
+chmod +x /usr/local/bin/service-failure-check.sh
+chmod +x /usr/local/bin/service-watcher.sh

+ 8 - 0
handlers/conf/bin/service-failure-check.sh

@@ -0,0 +1,8 @@
+#!/bin/bash
+
+SERVICE="$1"
+if ! systemctl is-active --quiet "$SERVICE"; then
+    echo "$(date): Сервис $SERVICE всё ещё не работает. Уведомление отправлено."
+    # Пример отправки уведомления (настройте под свою систему):
+    echo "Сервис $SERVICE не работает!" | mail -s "Ошибка сервиса" admin@example.com
+fi

+ 15 - 0
handlers/conf/bin/service-watcher.sh

@@ -0,0 +1,15 @@
+#!/bin/bash
+
+SERVICES=("service1" "service2" "service3" "service4" "service5" 
+          "service6" "service7" "service8" "service9" "service10")
+
+for service in "${SERVICES[@]}"; do
+    if ! systemctl is-active --quiet "$service"; then
+        echo "$(date): Сервис $service не работает. Перезапуск..."
+
+        systemctl restart "$service"
+        systemctl start "service-failure-watcher@${service}.timer"
+
+        echo "$(date): Таймер для $service активирован"
+    fi
+done

+ 17 - 0
handlers/conf/open_handler@.service

@@ -0,0 +1,17 @@
+[Unit]
+Description=ShariX Handler Open Basic Bot: $I
+After=network.target
+
+[Service]
+Type=simple
+User=root
+WorkingDirectory=/root/sharix-open-webapp-base/webservice_running/handlers
+ExecStart=/root/sharix-open-webapp-base/webservice_running/handlers/.venv/bin/python3 /root/sharix-open-webapp-base/webservice_running/handlers/main.py -b %i
+Restart=always
+RestartSec=60s
+
+TimeoutStopSec=30
+KillSignal=SIGTERM
+
+[Install]
+WantedBy=multi-user.target

+ 6 - 0
handlers/conf/service-monitor/service-failure-watcher@.service

@@ -0,0 +1,6 @@
+[Unit]
+Description=Проверка статуса сервиса %I
+
+[Service]
+Type=oneshot
+ExecStart=/usr/local/bin/service-failure-check.sh %i

+ 9 - 0
handlers/conf/service-monitor/service-failure-watcher@.timer

@@ -0,0 +1,9 @@
+[Unit]
+Description=Проверка сервиса %I через 15 минут
+
+[Timer]
+OnActiveSec=15m
+Unit=service-failure-watcher@%i.service
+
+[Install]
+WantedBy=timers.target

+ 6 - 0
handlers/conf/service-monitor/service-watcher.service

@@ -0,0 +1,6 @@
+[Unit]
+Description=Мониторинг и восстановление сервисов
+
+[Service]
+Type=oneshot
+ExecStart=/usr/local/bin/service-watcher.sh

+ 9 - 0
handlers/conf/service-monitor/service-watcher.timer

@@ -0,0 +1,9 @@
+[Unit]
+Description=Ежечасная проверка сервисов
+
+[Timer]
+OnCalendar=hourly
+Persistent=true
+
+[Install]
+WantedBy=timers.target

+ 37 - 0
handlers/config.py

@@ -0,0 +1,37 @@
+# rename this file to config.py
+BOTLIST = [
+    'open_basic_bot',
+    'status_changer',
+    'open_access_request_accepted',
+    'open_access_request_pending',
+    'open_neg_request_accepted',
+    'open_neg_request_pending',
+    'open_service_request_accepted',
+    'open_service_request_assigned',
+    'open_service_request_booked',
+    'open_service_request_booked_v2',
+    'open_service_request_closed',
+    'open_service_request_declined',
+    'open_service_request_done',
+    'open_service_request_forcemajeure',
+    'open_service_request_pending',
+    'open_service_request_preforcemajeure',
+    'open_service_request_prestart',
+    'open_service_request_process',
+    'open_st_request_assigned',
+    'open_st_request_done',
+    'open_st_request_dublicate',
+    'open_st_request_in_process',
+    'open_st_request_new',
+    'open_st_request_reopened',
+    'open_st_request_wontfix'
+]
+JSERVER = "ej.sharix-app.org"
+PASSWORD = "12345"
+PORT = 5222
+API_URL = "https://testopen.sharix-app.org/"
+
+# LOG_DIR = "/var/log/"
+LOG_DIR = "./log/"
+
+DEFAULT_INTERVAL_ATTEMPTS = 10

+ 30 - 0
handlers/core/JabberBot.py

@@ -0,0 +1,30 @@
+import logging
+import slixmpp
+import config
+from datetime import datetime
+
+
+class JabberBot(slixmpp.ClientXMPP):
+    """
+    Класс для работы с Jabber
+    """
+
+    def __init__(self, jid, password):
+        slixmpp.ClientXMPP.__init__(self, jid, password)
+
+        # Register plugins
+        self.register_plugin('xep_0030') # Service Discovery
+        self.register_plugin('xep_0004') # Data Forms
+        self.register_plugin('xep_0060') # PubSub
+        self.register_plugin('xep_0199') # XMPP Ping
+
+    def log(self, message):
+        # надо строчку лога сделать более информативной
+        logfile = open("logs/" + datetime.now().strftime('%Y-%m-%d') + "-" + self.user + ".log", "a")
+        logfile.write(message)
+        logfile.close()
+        print(message)
+
+    def stop(self):
+        self.disconnect()
+

+ 11 - 0
handlers/core/SystemdKiller.py

@@ -0,0 +1,11 @@
+import signal
+import threading
+
+class SystemdKiller:
+    def __init__(self):
+        self.exit_event = threading.Event()
+        signal.signal(signal.SIGINT, self.exit_handler)
+        signal.signal(signal.SIGTERM, self.exit_handler)
+
+    def exit_handler(self, signum, frame):
+        self.exit_event.set()  # Устанавливаем флаг прерывания

+ 17 - 0
handlers/core/lib.py

@@ -0,0 +1,17 @@
+
+def filter_interval_tickets(tickets):
+    """ Очистка тикетов, у которых закончились попытки """
+    return list(filter(lambda ticket: ticket.interval_attempts > 0, tickets))
+
+def run_process(interval_attempts_unlimited, processing):
+    """Обработка одного тикета с удалением."""
+    def go(ticket):    
+        ticket.interval_attempts -= 1
+        if ticket.interval_attempts <= 0:
+            interval_attempts_unlimited(ticket)
+            return None  # Маркер для удаления
+        else:
+            processing(ticket)
+        return ticket
+
+    return go

+ 12 - 0
handlers/core/utils.py

@@ -0,0 +1,12 @@
+from classes.Ticket import Ticket
+from typing import List
+
+def get_init_data(status: int) -> List[Ticket]:
+    return [
+        Ticket(0, "t", 0,0,0,0,0,0,0,0,0,"note", 1),
+        Ticket(1, "t", 0,1,0,0,0,0,0,0,0,"note", 2),
+        Ticket(2, "t", 0,2,0,0,0,0,0,0,0,"note", 1),
+        Ticket(3, "t", 0,3,0,0,0,0,0,0,0,"note", 2),
+        Ticket(4, "t", 0,4,0,0,0,0,0,0,0,"note", 1),
+        Ticket(5, "t", 0,5,0,0,0,0,0,0,0,"note", 1),
+    ]

+ 223 - 0
handlers/handlers/open_access_request_pending.py

@@ -0,0 +1,223 @@
+import hashlib
+from datetime import datetime
+import config
+import logging
+from core.JabberBot import JabberBot
+from slixmpp.stanza import Message
+import jsonAndRequest as jsreq
+from time import sleep
+from core.lib import run_process
+from classes.Ticket import Ticket
+from typing import List
+from concurrent.futures import ThreadPoolExecutor
+from core.SystemdKiller import SystemdKiller
+from core.utils import get_init_data
+
+botname = "open_access_request_pending"
+operating_status = 320
+
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+bot = JabberBot(JID, PASSWORD)
+
+listen_to = [
+    "test@ej.sharix-app.org",
+    "open_template_bot@ej.sharix-app.org"
+]
+""" Список jid, от которых можно получать сообщения этому боту """
+
+proceed_to = [
+    JID,
+    "open_st_request_declined@ej.sharix-app.org",
+    "open_service_request_forcemajeure@ej.sharix-app.org"
+]
+""" Список jid, кому бот может отправлять сообщения в результате обработки заявки """
+
+INTERVAL_ATTEMPTS = 3
+""" Количество попыток отправки сообщения """
+# INTERVAL_TIME = 30 * 60  # 30 минут в секундах
+INTERVAL_TIME = 5 # Для проверки
+""" Интервал времени между попытками отправки сообщения """
+
+TEMP_TICKETS: List[Ticket] = []
+""" Список тикетов для добавления в очередь обработки """
+ID_TICKETS_FOR_REMOVE: List[int] = []
+""" Список id тикетов для удаления """
+
+def message_handler(msg: Message):
+    """Обработчик входящих сообщений"""
+
+    if msg['type'] in ('chat', 'normal'):
+        text = msg['body']  # текст сообщения боту
+        sender = msg['from']  # отправитель сообщения
+
+        sender_name = str(sender).split("/")[0]
+        if sender_name in listen_to:
+            if text is not None:
+                logging.info(f"Сообщение получено")
+
+                # match ACTION:
+                #     case "add_ticket":
+                #         match sender_name:
+                #             case "open_*_request_*":
+                #                 TEMP_TICKETS.append(ticket)
+                #     case "remove_ticket":
+                #         ID_TICKETS_FOR_REMOVE.append(id)
+
+
+def start_handler():
+    """Событие запуска обработчика."""
+
+    logging.info(">>>>>  %s  |---| %s  <<<<<", JID, PASSWORD)
+
+    tickets: List[Ticket] = get_init_data(operating_status)
+
+    with ThreadPoolExecutor() as executor:
+        killer = SystemdKiller()
+
+        while not killer.exit_event.is_set():
+            # Получение тикетов от других обработчиков
+            tickets += TEMP_TICKETS
+            TEMP_TICKETS.clear()
+
+            # Фильтрация тикетов от лишних id
+            tickets = [ticket for ticket in tickets if ticket.id not in ID_TICKETS_FOR_REMOVE]
+            ID_TICKETS_FOR_REMOVE.clear()
+
+            # Параллельная обработка всех тикетов
+            processed = list(executor.map(run_process(interval_attempts_unlimited, processing), tickets))
+            
+            # Фильтрация тикетов
+            tickets = [t for t in processed if t is not None]
+            
+            logging.debug(tickets)
+            logging.debug("Sleep")
+            killer.exit_event.wait(timeout=INTERVAL_TIME)
+
+
+# START CUSTOM FUNCTIONS
+
+def interval_attempts_unlimited(ticket: Ticket) -> None:
+    logging.debug(f"Лимит попыток обработки тикета {ticket.id} исчерпан")
+    
+    # db.changestatus
+    # bot.send_message(JID, f"Сообщение отправлено {JID}: {datetime.now()}")
+    # bot message:
+    # {
+    #   "action": "add_ticket"
+    #   "ticket_id":      0
+    #   "ticket_list_id": 0
+    # }
+
+
+def processing(ticket: Ticket) -> None:
+    logging.debug(f"Начало обработки тикета {ticket.id}")
+
+    message = f"Тикет {ticket.id} ожидает решения"
+
+    send_notification_to_admins(ticket, message)
+    bot.send_message(ticket.assigned_to, message)
+
+    logging.debug(f"Конец обработки тикета {ticket.id}")
+
+
+def send_notification_to_admins(ticket: Ticket, admins: List[str], message: str) -> None:
+    """Отправка уведомления администратору о новом тикете."""
+    for admin in admins:
+        bot.send_message(admin, message)
+    logging.info(f"Уведомление отправлено администраторам: {ticket.id}")
+
+# def get_token():
+#     return jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/auth/token/login/")
+
+# def set_tasklist(token):
+#     global tasklist
+
+#     tasklist = []
+#     tasklist = jsreq.requestGetList(token, config.API_URL + "/tickets/api/tickets/?list_id=10")
+
+
+# END CUSTOM FUNCTIONS
+
+
+#  ---------------------------------------
+#  ---------------------------------------
+#  ---------------------------------------
+#  ---------------------------------------
+#  ---------------------------------------
+
+
+# # обработчик входящих сообщений
+# def message_handler(conn, mess):
+#     text = mess.getBody()  # текст сообщения боту
+#     user = mess.getFrom()  # отправитель сообщения
+
+#     print(str(user).split("/")[0])
+#     if (str(user).split("/")[0]) in listen_to:
+#         print(text)
+#         print(mess)
+
+#         if text is not None:
+#             orderObj = jsreq.jsonToOrderTicket(text)
+#             print(orderObj)
+#             tasklist.append(orderObj)
+#             bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+# def open_access_request_pending_wait(period, localtask):
+#     bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+#     time.sleep(period)
+
+#     # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+#     localtask.title = localtask.title + "1"
+
+#     # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+#     bot.proceed_status(proceed_to[1], localtask)
+#     bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ перенаправлен\n")
+
+
+# def open_access_request_pending_process(localtask):
+#     bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+#     push_notifications(localtask)
+#     open_access_request_pending_wait(100, localtask)
+
+
+# # Пока не уверен
+# def push_notifications(localtask):
+#     # Отправка уведомлений
+#     # ...
+#     return True
+
+
+# def open_access_request_pending():
+#     while (len(tasklist)):
+#         localtask = tasklist.pop(0)
+#         bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+#         print("EACH TASKLIST", tasklist)
+
+#         if (localtask.status != operating_status):
+#             bot.proceed_status(proceed_to[-1], localtask)
+#             bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+#             continue
+
+#         # if (localtask.title!="10"):
+#         #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+#         #     t1.start()
+
+#         # if (localtask.title=="101"):
+#         #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+#         #     t1.start()
+
+#         t1 = threading.Thread(target=open_access_request_pending_process, args=(localtask))
+#         t1.start()
+
+#         # если никакие обработчики не подошли - отправляем обратно в очередь
+#         bot.proceed_status(proceed_to[0], localtask)
+#         print("Заказ возвращен в очередь\n")
+#         print(tasklist)
+
+
+# # пустой список заказов

+ 53 - 0
handlers/handlers/open_basic_bot.py

@@ -0,0 +1,53 @@
+import hashlib
+from datetime import datetime
+import config
+import logging
+from core.JabberBot import JabberBot
+from slixmpp.stanza import Message
+
+botname = "open_basic_bot"
+operating_status = 0
+
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+bot = JabberBot(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = [
+    "open_basic_bot@ej.sharix-app.org",
+    "test_user@ej.sharix-app.org"
+]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [
+    "another_bot@ej.sharix-app.org"
+]
+
+def message_handler(msg: Message):
+    """Обработчик входящих сообщений"""
+
+    if msg['type'] in ('chat', 'normal'):
+        text = msg['body']  # текст сообщения боту
+        sender = msg['from']  # отправитель сообщения
+
+        if (str(sender).split("/")[0]) in listen_to:
+            if text is not None:
+                logging.info(f"Сообщение получено")
+
+def start_handler():
+    """Событие запуска обработчика."""
+
+    logging.info(">>>>>  %s  |---| %s  <<<<<", JID, PASSWORD)
+
+    logging.info("Сообщение отправлено")
+
+    bot.send_message(JID, f"Сообщение отправлено {JID}: {datetime.now()}")
+
+
+# START CUSTOM FUNCTIONS
+
+
+
+# END CUSTOM FUNCTIONS

+ 192 - 0
handlers/jsonAndRequest.py

@@ -0,0 +1,192 @@
+import json
+
+import requests
+
+import config
+from classes.Answer import Answer
+from classes.Order import Order
+from classes.OrderTicket import OrderTicket
+from classes.Ticket_user import Ticket_user
+
+
+# Функция преобразования json в объект класса Order
+def jsonToOrder(jsonstring) -> Order:
+    jsonObj = json.loads(jsonstring)
+    print(jsonObj)
+    u = Order(**jsonObj)
+    return u
+
+
+# Функция преобразования json в объект класса OrderTicket
+def jsonToOrderTicket(jsonstring) -> OrderTicket:
+    print(jsonstring)
+    jsonObj = json.loads(jsonstring)
+    print(jsonObj)
+    u = OrderTicket(**jsonObj)
+    return u
+
+
+# Функция обращения к апи и получение токена
+def requestGetToken(login, password, url) -> str:
+    login = "79999999999"
+    password = "12345"
+    # login = "11111111111"
+    # password = "Sharix!"
+    # url = "https://user.sharix-app.org/auth/token/login/"
+    data = {
+        "password": password,
+        "phone_number": login
+    }
+    response = requests.post(url, json=data)
+    result = response.json()
+    return result['auth_token']
+
+
+# Функция обращения к апи и получение токена
+
+
+def msg_to_text(jsonstring):
+    jsonObj = json.loads(jsonstring)
+    u = jsonObj
+    return u
+
+
+def createUser(username, phone, password, url) -> str:
+    data = {
+        "username": username,
+        "phone_number": phone,
+        "password": password
+    }
+    response = requests.post(url, json=data)
+    result = response.json()
+    return result
+
+
+# Функция обращения к апи и получение списка пользователей
+
+
+def requestGetListUser():
+    auth_token = requestGetToken()
+    print(auth_token)
+    headers = {'Authorization': f'Token {auth_token}'}
+    url = 'https://user.sharix-app.org/platform/api/sharix-users/'
+    response = requests.get(url, headers=headers)
+    print(response)
+    print(response.json())
+
+
+# def requestGetList(auth_token, url):
+#     headers = {'Authorization': f'Token {auth_token}'}
+#     response = requests.get(url, headers=headers)
+#     #response = requests.get(config.API_URL+"/dbsynce/api/orders/", headers=headers)
+#     ordertext=response.json()
+#     startlist = []
+
+#     if not ordertext:
+#         print("Empty array")
+#     else:
+#         for i in ordertext:
+#             print (i, "PROCESSING")
+#             try:
+#                 orderticket = OrderTicket(**i)
+#                 print(i, "ORDER ", orderticket)
+#                 startlist.append(orderticket)
+#             except Exception as ex:
+#                 print(ex)
+#     print (startlist)
+#     return startlist
+
+
+def requestGetList(auth_token, url):
+    headers = {'Authorization': f'Token {auth_token}'}
+    response = requests.get(url, headers=headers)
+    # response = requests.get(config.API_URL+"/dbsynce/api/orders/", headers=headers)
+    ordertext = response.json()
+    startlist = []
+
+    if not ordertext:
+        print("Empty array")
+    else:
+        for i in ordertext:
+            print(i, "PROCESSING")
+            try:
+                order = Order(**i)
+                print(i, "ORDER ", order)
+                startlist.append(order)
+            except Exception as ex:
+                print(ex)
+    print(startlist)
+    return startlist
+
+
+def requestGetTicket_user(auth_token, url):
+    headers = {'Authorization': f'Token {auth_token}'}
+    response = requests.get(url, headers=headers)
+
+    # response = requests.get(config.API_URL+"/dbsynce/api/orders/", headers=headers)
+    tickettext = response.json()
+    startlist = []
+    if not tickettext:
+        print("Empty array")
+    else:
+        for i in tickettext:
+            try:
+                ticket = Ticket_user(**i)
+                startlist.append(ticket)
+            except Exception as ex:
+                print(ex)
+    print(startlist)
+    return startlist
+
+
+def requestPatchTicketUser(token, url, data):
+    headers = {'Authorization': f'Token {token}'}
+    response = requests.patch(url, json=data, headers=headers)
+    return response
+
+
+def change_groups(auth_token, url, group):
+    headers = {
+        'Content-Type': 'application/json',
+        'Authorization': f'Token {auth_token}'
+    }
+    response = requests.get(url, headers=headers)
+    user_data = response.json()
+    current_groups = user_data.get('groups', [])
+    updated_groups = list(set([group] + current_groups))
+    data = {'groups': updated_groups}
+    print(data)
+    response = requests.put(url, json=data, headers=headers)
+    print(url)
+    print(user_data)
+    return response
+
+
+def change_status_company(auth_token, url, id_metaservice):
+    headers = {
+        'Content-Type': 'application/json',
+        'Authorization': f'Token {auth_token}'
+    }
+    response = requests.get(url, headers=headers)
+    user_data = response.json()
+    print(user_data)
+    current_metaservice = user_data.get('id_metaservice', [])
+    repsonse = requests.put(config.API_URL + f"dbsynce/api/company/{id_metaservice}", json=data, headers=headers)
+    return response
+
+
+def to_answer(jsonstring):
+    json_answer = json.loads(jsonstring)
+    print(json_answer)
+    u = Answer(**json_answer)
+    return u
+
+
+def change_to_task(localtask, token):
+    headers = {
+        'Authorization': f'Token {token}',
+        'Content-Type': 'application/json'  # Установка заголовка Content-Type
+    }
+    data = json.dumps(localtask.__dict__)
+    response = requests.patch(config.API_URL + f"/dbsynce/api/orders/{localtask.id}/", headers=headers, data=data)
+    return response

+ 60 - 0
handlers/main.py

@@ -0,0 +1,60 @@
+import config
+from core.JabberBot import JabberBot
+import logging
+from argparse import ArgumentParser
+import importlib
+
+if __name__ == '__main__':
+    # Setup the command line arguments.
+    parser = ArgumentParser(description=JabberBot.__doc__)
+
+    # Output verbosity options.
+    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
+                        action="store_const", dest="loglevel",
+                        const=logging.ERROR, default=logging.INFO)
+    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
+                        action="store_const", dest="loglevel",
+                        const=logging.DEBUG, default=logging.INFO)
+
+    # JID and password options.
+    parser.add_argument("-b", "--bot", dest="bot",
+                        help="Bot name")
+
+    args = parser.parse_args()
+
+    # Setup logging.
+    logging.basicConfig(level=args.loglevel,
+                        format='%(levelname)-8s %(message)s')
+
+
+    if args.bot and args.bot in config.BOTLIST:
+        module = importlib.import_module("handlers." + args.bot)
+
+        start_handler = module.start_handler
+        message_handler = module.message_handler        
+
+        bot = module.bot 
+        
+        # Отправляет информацию о присутствии бота, чтобы показать,
+        # что он онлайн и готов к взаимодействию.
+        bot.send_presence()
+        # bot.get_roster() # TODO: Возможно не нужно
+
+        logging.info(f"Bot {bot.jid} started!")
+
+        bot.add_event_handler("message", message_handler)
+
+        # Connect to the XMPP server and start processing XMPP stanzas.
+        bot.connect()
+        
+        start_handler()
+
+        # TODO: Сделать корректную обработку остановки программы;
+        # Ctrl+C, Ctrl+Z
+        # systemctl stop с последующей отправкой кодов и корректной остановкой программы
+
+        bot.stop()
+    else:
+        print("Select using -n flag for select availible bot from botlist:\n")
+        for botname in config.BOTLIST:
+            print(f"- {botname}")

+ 123 - 0
handlers/old_st_request_assigned.py

@@ -0,0 +1,123 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "status_changer"
+
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["status_changer@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = ["numbers"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+# def message_handler(conn, mess):
+#     text = mess.getBody()#текст сообщения боту
+#     user = mess.getFrom()#отправитель сообщения
+#     if (str(user).split("/")[0]) in listen_to:
+#         # print (str(user).split("/")[0])
+#         if text is not None:
+#             orderObj = jsreq.jsonToOrder(text)
+#             tasklist.append(orderObj)
+#             bot.bot_log(str(datetime.now())+" Поступивший заказ успешно добавлен в очередь обработки\n")
+
+def status_changer_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет ожидает\n")
+    time.sleep(period)
+
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет подождал и возвращен в очередь\n")
+
+
+def status_changer_process(ticket):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет в обработчике\n")
+    tickets_new = jsreq.requestGetTicket_user(token, config.API_URL + f"tickets/api/ticket_list/{ticket.id}")
+    # if ticket.id == 2103:
+    #     for ticket_new in tickets_new:
+    #         metaservice_admin(ticket_new,ticket.group)
+    if ticket.id == 2101:
+        for ticket_new in tickets_new:
+            company_status(ticket_new)
+    elif ticket.id == 2102:
+        for ticket_new in tickets_new:
+            company_status(ticket_new, ticket.group)
+    elif ticket.id == '':
+        print('should be soon')  # дополнить по всем айди тикетов
+    # if ticket_new != []:
+    #     print(ticket_new)
+    # api/v1/platform/sharix-users/1/
+
+    # bot.proceed_status(proceed_to[1], localtask)
+    # bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет успешно обработан и отправлен на pending\n")
+
+
+def company_status(ticket_new):
+    if ticket_new.status == 141:  # нужны доп проверки
+        answer = jsreq.change_status_company(token, config.API_URL + f"dbsynce/api/client/{ticket_new.created_by}/")
+        if answer != 200:
+            print(f'Ошибка{answer}')
+    else:
+        print('Статус не ACCESS')
+
+
+# def company_status(ticket_new):
+#     if ticket_new.status == 141:#нужны доп проверки
+#         answer=jsreq.change_status_company(token, config.API_URL+f"dbsynce/api/client/{ticket_new.created_by}/",ticket_new.created_by)
+#         if answer!=200:
+#             print(f'Ошибка{answer}')
+#     else:   
+#         print('Статус не ACCESS')
+
+
+def metaservice_admin(ticket_new, group):
+    if ticket_new.status == 141:  # нужны доп проверки
+        answer = jsreq.change_groups(token, config.API_URL + f"api/v1/platform/sharix-users/{ticket_new.created_by}/",
+                                     group)
+        if answer != 200:
+            print(f'Ошибка{answer}')
+    else:
+        print('Статус не ACCESS')
+
+
+def status_changer():
+    while True:
+        ticketlist = jsreq.requestGetList(token, config.API_URL + "tickets/api/ticket_list/")
+        for ticket in ticketlist:
+            bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Тикет в очереди на обработке\n")
+            t1 = threading.Thread(target=status_changer_process, args=(ticket,))
+            t1.start()
+            t1.join()  # Ожидаем завершения обработки тикета
+        time.sleep(300)  # Обновляем ticketlist каждые 5 минут
+
+
+# Авторизация и запуск бота
+
+# пустой список
+ticketlist = []
+
+token = jsreq.requestGetToken(config.API_URL + "api/v1/auth/token/login/")
+# ticketlist=jsreq.requestGetList(token, config.API_URL+"/dbsynce/api/orders/") ###Должна быть проверка между двумя
+
+# # print (len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.start(status_changer)

+ 123 - 0
handlers/old_st_request_done.py

@@ -0,0 +1,123 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "status_changer"
+
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["status_changer@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = ["numbers"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+# def message_handler(conn, mess):
+#     text = mess.getBody()#текст сообщения боту
+#     user = mess.getFrom()#отправитель сообщения
+#     if (str(user).split("/")[0]) in listen_to:
+#         # print (str(user).split("/")[0])
+#         if text is not None:
+#             orderObj = jsreq.jsonToOrder(text)
+#             tasklist.append(orderObj)
+#             bot.bot_log(str(datetime.now())+" Поступивший заказ успешно добавлен в очередь обработки\n")
+
+def status_changer_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет ожидает\n")
+    time.sleep(period)
+
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет подождал и возвращен в очередь\n")
+
+
+def status_changer_process(ticket):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет в обработчике\n")
+    tickets_new = jsreq.requestGetTicket_user(token, config.API_URL + f"tickets/api/ticket_list/{ticket.id}")
+    # if ticket.id == 2103:
+    #     for ticket_new in tickets_new:
+    #         metaservice_admin(ticket_new,ticket.group)
+    if ticket.id == 2101:
+        for ticket_new in tickets_new:
+            company_status(ticket_new)
+    elif ticket.id == 2102:
+        for ticket_new in tickets_new:
+            company_status(ticket_new, ticket.group)
+    elif ticket.id == '':
+        print('should be soon')  # дополнить по всем айди тикетов
+    # if ticket_new != []:
+    #     print(ticket_new)
+    # api/v1/platform/sharix-users/1/
+
+    # bot.proceed_status(proceed_to[1], localtask)
+    # bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет успешно обработан и отправлен на pending\n")
+
+
+def company_status(ticket_new):
+    if ticket_new.status == 141:  # нужны доп проверки
+        answer = jsreq.change_status_company(token, config.API_URL + f"dbsynce/api/client/{ticket_new.created_by}/")
+        if answer != 200:
+            print(f'Ошибка{answer}')
+    else:
+        print('Статус не ACCESS')
+
+
+# def company_status(ticket_new):
+#     if ticket_new.status == 141:#нужны доп проверки
+#         answer=jsreq.change_status_company(token, config.API_URL+f"dbsynce/api/client/{ticket_new.created_by}/",ticket_new.created_by)
+#         if answer!=200:
+#             print(f'Ошибка{answer}')
+#     else:   
+#         print('Статус не ACCESS')
+
+
+def metaservice_admin(ticket_new, group):
+    if ticket_new.status == 141:  # нужны доп проверки
+        answer = jsreq.change_groups(token, config.API_URL + f"api/v1/platform/sharix-users/{ticket_new.created_by}/",
+                                     group)
+        if answer != 200:
+            print(f'Ошибка{answer}')
+    else:
+        print('Статус не ACCESS')
+
+
+def status_changer():
+    while True:
+        ticketlist = jsreq.requestGetList(token, config.API_URL + "tickets/api/ticket_list/")
+        for ticket in ticketlist:
+            bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Тикет в очереди на обработке\n")
+            t1 = threading.Thread(target=status_changer_process, args=(ticket,))
+            t1.start()
+            t1.join()  # Ожидаем завершения обработки тикета
+        time.sleep(300)  # Обновляем ticketlist каждые 5 минут
+
+
+# Авторизация и запуск бота
+
+# пустой список
+ticketlist = []
+
+token = jsreq.requestGetToken(config.API_URL + "api/v1/auth/token/login/")
+# ticketlist=jsreq.requestGetList(token, config.API_URL+"/dbsynce/api/orders/") ###Должна быть проверка между двумя
+
+# # print (len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.start(status_changer)

+ 90 - 0
handlers/old_st_request_new.py

@@ -0,0 +1,90 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import requests
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "st_request_new"
+
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["st_request_new@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = ["numbers"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+# def message_handler(conn, mess):
+#     text = mess.getBody()#текст сообщения боту
+#     user = mess.getFrom()#отправитель сообщения
+#     if (str(user).split("/")[0]) in listen_to:
+#         # print (str(user).split("/")[0])
+#         if text is not None:
+#             orderObj = jsreq.jsonToOrder(text)
+#             tasklist.append(orderObj)
+#             bot.bot_log(str(datetime.now())+" Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def status_new_process(ticket):
+    tickets_new = jsreq.requestGetTicket_user(token, config.API_URL + f"tickets/api/ticket_list/{ticket.id}")
+    for ticket_new in tickets_new:
+        send_to_user(ticket_new)
+
+
+def send_to_user(ticket_new):
+    user = jsreq.requestGetListUser(token)
+    print(user.json()[0]['id'])
+    headers = {'Authorization': f'Token {token}'}
+    url = config.API_URL + f"tickets/api/ticket_list/{ticket_new.id}"
+    if ticket_new.assigned_to == None:
+        ticket_new.assigned_to = user.json()[0]['id']
+        user = 'test@ej.sharix-app.org'
+        print({'id': ticket_new.id, 'assigned_to': ticket_new.assigned_to})
+        response = requests.put(url, json={'id': ticket_new.id, 'assigned_to': ticket_new.assigned_to}, headers=headers)
+        print(response)
+        if response:
+            bot.send_notification(user, ticket_new)
+
+
+def status_new():
+    while True:
+        ticketlist = jsreq.requestGetList(token, config.API_URL + "tickets/api/ticket_list/")
+        for ticket in ticketlist:
+            bot.bot_log(
+                botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Тикет отправлен в очередь на обработку\n")
+            t1 = threading.Thread(target=status_new_process, args=(ticket,))
+            t1.start()
+            t1.join()  # Ожидаем завершения обработки тикета
+        time.sleep(300)  # Обновляем ticketlist каждые 5 минут
+
+
+# Авторизация и запуск бота
+
+# пустой список
+ticketlist = []
+
+token = jsreq.requestGetToken(config.API_URL + "api/v1/auth/token/login/")
+# ticketlist=jsreq.requestGetList(token, config.API_URL+"/dbsynce/api/orders/") ###Должна быть проверка между двумя
+
+# # print (len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.start(status_new)

+ 123 - 0
handlers/old_st_request_wontfix.py

@@ -0,0 +1,123 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "st_request_wontfix"
+
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["st_request_wontfix@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = ["numbers"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+# def message_handler(conn, mess):
+#     text = mess.getBody()#текст сообщения боту
+#     user = mess.getFrom()#отправитель сообщения
+#     if (str(user).split("/")[0]) in listen_to:
+#         # print (str(user).split("/")[0])
+#         if text is not None:
+#             orderObj = jsreq.jsonToOrder(text)
+#             tasklist.append(orderObj)
+#             bot.bot_log(str(datetime.now())+" Поступивший заказ успешно добавлен в очередь обработки\n")
+
+def status_changer_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет ожидает\n")
+    time.sleep(period)
+
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет подождал и возвращен в очередь\n")
+
+
+def status_changer_process(ticket):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет в обработчике\n")
+    tickets_new = jsreq.requestGetTicket_user(token, config.API_URL + f"tickets/api/ticket_list/{ticket.id}")
+    # if ticket.id == 2103:
+    #     for ticket_new in tickets_new:
+    #         metaservice_admin(ticket_new,ticket.group)
+    if ticket.id == 2101:
+        for ticket_new in tickets_new:
+            company_status(ticket_new)
+    elif ticket.id == 2102:
+        for ticket_new in tickets_new:
+            company_status(ticket_new, ticket.group)
+    elif ticket.id == '':
+        print('should be soon')  # дополнить по всем айди тикетов
+    # if ticket_new != []:
+    #     print(ticket_new)
+    # api/v1/platform/sharix-users/1/
+
+    # bot.proceed_status(proceed_to[1], localtask)
+    # bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет успешно обработан и отправлен на pending\n")
+
+
+def company_status(ticket_new):
+    if ticket_new.status == 141:  # нужны доп проверки
+        answer = jsreq.change_status_company(token, config.API_URL + f"dbsynce/api/client/{ticket_new.created_by}/")
+        if answer != 200:
+            print(f'Ошибка{answer}')
+    else:
+        print('Статус не ACCESS')
+
+
+# def company_status(ticket_new):
+#     if ticket_new.status == 141:#нужны доп проверки
+#         answer=jsreq.change_status_company(token, config.API_URL+f"dbsynce/api/client/{ticket_new.created_by}/",ticket_new.created_by)
+#         if answer!=200:
+#             print(f'Ошибка{answer}')
+#     else:   
+#         print('Статус не ACCESS')
+
+
+def metaservice_admin(ticket_new, group):
+    if ticket_new.status == 141:  # нужны доп проверки
+        answer = jsreq.change_groups(token, config.API_URL + f"api/v1/platform/sharix-users/{ticket_new.created_by}/",
+                                     group)
+        if answer != 200:
+            print(f'Ошибка{answer}')
+    else:
+        print('Статус не ACCESS')
+
+
+def status_changer():
+    while True:
+        ticketlist = jsreq.requestGetList(token, config.API_URL + "tickets/api/ticket_list/")
+        for ticket in ticketlist:
+            bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Тикет в очереди на обработке\n")
+            t1 = threading.Thread(target=status_changer_process, args=(ticket,))
+            t1.start()
+            t1.join()  # Ожидаем завершения обработки тикета
+        time.sleep(300)  # Обновляем ticketlist каждые 5 минут
+
+
+# Авторизация и запуск бота
+
+# пустой список
+ticketlist = []
+
+token = jsreq.requestGetToken(config.API_URL + "api/v1/auth/token/login/")
+# ticketlist=jsreq.requestGetList(token, config.API_URL+"/dbsynce/api/orders/") ###Должна быть проверка между двумя
+
+# # print (len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.start(status_changer)

+ 120 - 0
handlers/open_access_request_accepted.py

@@ -0,0 +1,120 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_access_request_accepted"
+
+operating_status = 321
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["test@ej.sharix-app.org", "open_template_bot@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_st_request_declined@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_access_request_accepted_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и отправлен в очередь\n")
+
+
+def open_access_request_accepted_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    send_data(localtask)
+
+
+# Пока не уверен
+def send_data(localtask):
+    # Заглушка отправка данных в БД
+    # ...
+    return True
+
+
+def open_access_request_accepted():
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+
+        if (localtask.status != operating_status):
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_access_request_accepted_process, args=(localtask))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/auth/token/login/")
+
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist = jsreq.requestGetList(token, config.API_URL + "/tickets/api/tickets/?list_id=10")
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_access_request_accepted)

+ 121 - 0
handlers/open_access_request_pending.py

@@ -0,0 +1,121 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_access_request_pending"
+
+operating_status = 320
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["test@ej.sharix-app.org", "open_template_bot@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_st_request_declined@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_access_request_pending_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[1], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ перенаправлен\n")
+
+
+def open_access_request_pending_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    push_notifications(localtask)
+    open_access_request_pending_wait(100, localtask)
+
+
+# Пока не уверен
+def push_notifications(localtask):
+    # Отправка уведомлений
+    # ...
+    return True
+
+
+def open_access_request_pending():
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+
+        if (localtask.status != operating_status):
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_access_request_pending_process, args=(localtask))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/auth/token/login/")
+
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist = jsreq.requestGetList(token, config.API_URL + "/tickets/api/tickets/?list_id=10")
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_access_request_pending)

+ 50 - 0
handlers/open_basic_bot.py

@@ -0,0 +1,50 @@
+import hashlib
+from datetime import datetime
+import config
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+botname = "open_basic_bot"
+operating_status = 0
+
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+bot: JabberBot = JabberBot(JID, PASSWORD, PORT)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = [
+    "test_user@ej.sharix-app.org"
+]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [
+    "another_bot@ej.sharix-app.org"
+]
+
+
+def message_handler(conn, mess):
+    """обработчик входящих сообщений"""
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+    if (str(user).split("/")[0]) in listen_to:
+        if text is not None:
+            msg = jsreq.msg_to_text(text)
+            bot.bot_log(str(datetime.now()) + " Сообщение получено\n")
+
+
+def start_handler(self):
+    """Событие запуска обработчика."""
+
+    bot.proceed_status(listen_to[0], {'msg': 'some_info'})
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Сообщение отправлено\n")
+
+# START CUSTOM FUNCTIONS
+
+
+
+# END CUSTOM FUNCTIONS
+
+bot.register_handler('message', message_handler)
+bot.start(start_handler)

+ 120 - 0
handlers/open_neg_request_accepted.py

@@ -0,0 +1,120 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_neg_request_accepted"
+
+operating_status = 321
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["test@ej.sharix-app.org", "open_template_bot@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_st_request_declined@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_neg_request_accepted_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и отправлен в очередь\n")
+
+
+def open_neg_request_accepted_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    send_data(localtask)
+
+
+# Пока не уверен
+def send_data(localtask):
+    # Заглушка отправка данных в БД
+    # ...
+    return True
+
+
+def open_neg_request_accepted():
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+
+        if (localtask.status != operating_status):
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_neg_request_accepted_process, args=(localtask))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/auth/token/login/")
+
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist = jsreq.requestGetList(token, config.API_URL + "/tickets/api/tickets/?list_id=10")
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_neg_request_accepted)

+ 107 - 0
handlers/open_neg_request_pending.py

@@ -0,0 +1,107 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+# В этом файле содержится только то, что запускает конкретный обработчик
+
+# botname="open_st_request_assigned"
+botname = "open_neg_request_pending"
+operating_status = 420
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+# раскомментировать, когда перейдем на разные пароли
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["open_neg_request_pending@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = ["open_neg_request_pending@ej.sharix-app.org", "open_neg_request_declined@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+    # user = mess.getNode()#только jid
+
+    # нужна проверка, данный обработчик вообще должен от данного отправителя получать сообщения или нет. Подсказка ниже
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+# TODO - для обработчиков Ticket скорее надо будет функции вынести в отдельную библиотеку, они типовые же
+def pending_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает пользовательской реакции\n")
+    time.sleep(period)
+
+    # ВАЖНО! НАДО ВСТАВИТЬ ИЗМЕНЕНИЕ СТАТУСА ЧЕРЕЗ API
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[1], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ отклонен\n")
+
+
+def open_neg_request_pending():
+    # print("Тут описывается работа со списком задач в данном статусе")
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+
+        # если боту почему-то пришла не его заявка - это явно ошибка движения процессов и отдаем в форсмажор - этот обработчик указывать стоит всегда последним
+        # if (localtask.status!=operating_status):
+        #    bot.proceed_status(proceed_to[-1],localtask)
+        #    bot.bot_log(botname+" "+str(datetime.now())+" "+"Заказ не по адресу, перенаправляем на форсмажор\n")
+        #    continue
+
+        # TODO: send_notifications - изучить как в комнату
+
+        # ЖДАТЬ НАДО ПОДОЛЬШЕ
+        t1 = threading.Thread(target=pending_wait, args=(100, localtask))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        # bot.proceed_status(proceed_to[0],localtask)
+        # print("Заказ возвращен в очередь\n")
+        # print (tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/auth/token/login/")
+
+# ВАЖНО! Надо понять, по такому ли запросу разумно делать фильтр - или поменять порядок
+tasklist = jsreq.requestGetList(token, config.API_URL + "/tickets/api/tickets/?status=210&list_id=10")
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_neg_request_pending)

+ 176 - 0
handlers/open_service_request_accepted.py

@@ -0,0 +1,176 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_service_request_accepted"
+
+operating_status = '221'
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["open_service_request_assigned@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_service_request_process@ej.sharix-app.org",
+              "open_service_request_declined@ej.sharix-app.org", "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+def log_handler():
+    while True:
+        with open(f'{botname}.txt', 'a') as log_file:
+            log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {botname} is still running...\n")
+        time.sleep(3600)
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    if (str(user).split("/")[0]) in listen_to:
+        if text is not None:
+            orderObj = jsreq.jsonToOrder(text)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_service_request_accepted_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и отправлен в очередь\n")
+
+
+def open_service_request_accepted_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    # order = jsreq.jsonToOrder(localtask)
+    localtask.status = '231'
+    jsreq.change_to_task(localtask, token)
+    bot.proceed_status(proceed_to[1], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ отправлен\n")
+    # if order.time_start_predicted < 100:
+    #     # Заглушка. Проверка может ли заказ быть переназначен
+    #     if True:
+    #         # Заглушка. Сбросить пометку предзаказа
+    #         # ...
+
+    #         bot.proceed_status(proceed_to[1],localtask)
+    #         bot.bot_log(botname+" "+str(datetime.now())+" "+"Заказ отправлен\n")
+    #     else:
+    #         bot.proceed_status(proceed_to[2],localtask)
+    #         bot.bot_log(botname+" "+str(datetime.now())+" "+"Заказ отправлен\n")
+    # else:
+    #     # Заглушка. Обработана заявка на устанавление взаимоотношений?
+    #     if True:
+    #         # Заглушка. Взаимоотношения установлены ?
+    #         if True:
+    #             # Заглушка. Отобразить в предварительных заказах исполнителям.
+    #             send_message()
+    #             # Заглушка. Исполнитель откликнулся на заказ?
+    #             if True:
+    #                 # У пользователя стоит ручной выбор из нескольких исполнителей?
+    #                 if True:
+    #                     # Заглушка создать дочернюю локальную заявку с информацией от исполнителя
+    #                     create_ticket()
+    #                     # Заглушка отобразить в предварительных клиенту
+    #                     send_message()
+
+    #                     # Заглушка. Клиент выбрал конкретную заявку?
+    #                     if True:
+    #                         # Заглушка. обновление локальной копии. Замена основной
+    #                         pass
+    #                     else:
+    #                         bot.proceed_status(proceed_to[3],localtask)
+    #                         bot.bot_log(botname+" "+str(datetime.now())+" "+"Заказ отправлен\n")
+    #                 else:
+    #                     bot.proceed_status(proceed_to[3],localtask)
+    #                     bot.bot_log(botname+" "+str(datetime.now())+" "+"Заказ отправлен\n")
+    #             else:
+    #                 #Заглушка. Заказ ждет очередную итерацию обработки списка
+    #                 open_service_request_accepted_process(localtask)
+    #         else:
+    #             bot.proceed_status(proceed_to[1],localtask)
+    #             bot.bot_log(botname+" "+str(datetime.now())+" "+"Заказ отправлен\n")
+    #     else:
+    #         #Заглушка. Заказ ждет очередную итерацию обработки списка
+    #         open_service_request_accepted_process(localtask)
+    #         pass
+
+
+def send_message():
+    pass
+
+
+def create_ticket():
+    pass
+
+
+def open_service_request_accepted():
+    log_thread = threading.Thread(target=log_handler)
+    log_thread.daemon = True
+    log_thread.start()
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+
+        if (localtask.status != operating_status):
+            localtask.status = 239
+            jsreq.change_to_task(localtask, token)
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+        elif True:
+            t1 = threading.Thread(target=open_service_request_accepted_process, args=([localtask]))
+            t1.start()
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        # #если никакие обработчики не подошли - отправляем обратно в очередь
+        # bot.proceed_status(proceed_to[0],localtask)
+        # print("Заказ возвращен в очередь\n")
+        # print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "my/api/v1/auth/token/login/")
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist_dbsynce = jsreq.requestGetList(token, config.API_URL + "/dbsynce/api/orders/")
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_service_request_accepted)

+ 178 - 0
handlers/open_service_request_assigned.py

@@ -0,0 +1,178 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import json
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_service_request_assigned"
+
+operating_status = '212'
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+drivers = ["799999999998@ej.sharix-app.org"]
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["open_service_request_booked@ej.sharix-app.org", "open_service_request_pending@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_service_request_accepted@ej.sharix-app.org",
+              "open_service_request_declined@ej.sharix-app.org", "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+def log_handler():
+    while True:
+        with open(f'{botname}.txt', 'a') as log_file:
+            log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {botname} is still running...\n")
+        time.sleep(3600)
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+    if (str(user).split("/")[0]) in listen_to:
+        print('order_handler')
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrder(text)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_service_request_assigned_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и отправлен в очередь\n")
+
+
+def wait_for_answer(localtask):
+    order = localtask
+    driver = drivers[0]
+    send_message(order, driver)
+    # Здесь можно реализовать логику выбора водителя
+    while True:
+        start_time = time.time()
+        if time.time() + 400 - start_time > 300:  ##Логика временная
+            if len(answers) > 0:
+                answer = answers.pop(0)
+                if answer.answer == 'ACCEPT':
+                    localtask.status = '221'
+                    jsreq.change_to_task(localtask, token)
+                    bot.proceed_status(proceed_to[1], localtask)
+                    bot.bot_log(botname + " " + str(datetime.now()) + f" Заказ отправлен на {proceed_to[1]}\n")
+                elif answer.answer == 'DECLINE':
+                    localtask.status = '229'
+                    localtask.provider = None
+                    jsreq.change_to_task(localtask, token)
+                    bot.proceed_status(proceed_to[2], localtask)
+                    bot.bot_log(botname + " " + str(datetime.now()) + f" Заказ отправлен на {proceed_to[2]}\n")
+                else:
+                    bot.bot_log(botname + " " + str(datetime.now()) + f"Ошибка ответа\n")
+                break
+            else:
+                print("Ожидание ответа...")
+                time.sleep(3)
+        else:
+            localtask.status = '229'
+            localtask.provider = None
+            jsreq.change_to_task(localtask, token)
+            bot.proceed_status(proceed_to[2], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + f" Заказ отправлен на {proceed_to[2]}\n")
+            break
+
+
+def open_service_request_assigned_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+    order = localtask
+    if order.provider != None:
+        wait_thread = threading.Thread(target=wait_for_answer, args=(localtask,))
+        wait_thread.start()
+
+
+def message_answer(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+    if (str(user).split("/")[0]) in drivers:
+        print('answer_handler')
+        if text is not None:
+            answerObj = jsreq.to_answer(text)
+            answers.append(answerObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший ответ успешно добавлен в очередь обработки\n")
+
+
+def send_message(order, driver):
+    order = json.dumps(order.__dict__)
+    bot.send_notification(driver, order)
+
+
+def open_service_request_assigned():
+    log_thread = threading.Thread(target=log_handler)
+    log_thread.daemon = True
+    log_thread.start()
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        if (localtask.status != operating_status):
+            localtask.status = '239'
+            jsreq.change_to_task(localtask, token)
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+        else:
+            bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+            t1 = threading.Thread(target=open_service_request_assigned_process, args=([localtask]))
+            t1.start()
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        # t1=threading.Thread(target=open_service_request_assigned_process, args=(localtask))
+        # t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        # bot.proceed_status(proceed_to[0],localtask)
+        # print("Заказ возвращен в очередь\n")
+        # print(tasklist)
+
+
+# Авторизация и запуск бота
+
+answers = []
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "my/api/v1/auth/token/login/")
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist_dbsynce = jsreq.requestGetList(token, config.API_URL + "/dbsynce/api/orders/")
+
+bot = JabberBot(JID, PASSWORD, PORT)
+bot.register_handler('message', message_handler)
+bot.register_handler('message', message_answer)
+bot.start(open_service_request_assigned)
+
+# Добавить функцию поток для ожидания получения заказа.

+ 221 - 0
handlers/open_service_request_booked.py

@@ -0,0 +1,221 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import requests
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+
+def log_handler():
+    while True:
+        with open('log.txt', 'a') as log_file:
+            log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - Function is still running...\n")
+        time.sleep(3600)
+
+
+botname = "open_service_request_booked"
+
+operating_status = '211'
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["799999999990@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = ["open_service_request_assigned@ej.sharix-app.org", "open_service_request_pending@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+def log_handler():
+    while True:
+        with open(f'{botname}.txt', 'a') as log_file:
+            log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {botname} is still running...\n")
+        time.sleep(3600)
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+    if (str(user).split("/")[0]) in listen_to:
+        # print (str(user).split("/")[0])
+        if text is not None:
+            try:
+                orderObj = jsreq.jsonToOrder(text)
+                tasklist.append(orderObj)
+                bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+            except:
+                bot.proceed_status(proceed_to[-1], text)
+                bot.bot_log(
+                    botname + " " + str(datetime.now()) + " " + "Заказ успешно обработан и отправлен на assigned\n")
+
+
+def open_service_request_booked_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и возвращен в очередь\n")
+
+
+def open_service_request_booked_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    if not localtask.provider:
+        answer, provider, service = set_provider(localtask.id)
+        # localtask.service =service.id
+        localtask.service = service['id']
+        if set_provider(localtask.id):
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Водитель успешно установлен\n")
+        else:
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "'Ошибка водитель не был установлен'\n")
+        localtask.provider = provider
+    current_time = datetime.now()
+
+    # if localtask.asap or (current_time - datetime.fromisoformat(localtask.time_start_predicted) < timedelta(hours=3)):
+    if localtask.asap:
+        localtask.status = '212'
+        print(jsreq.change_to_task(localtask, token))
+        bot.proceed_status(proceed_to[0], localtask)
+        bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ успешно обработан и отправлен на assigned\n")
+    else:
+        localtask.status = '220'
+        print(jsreq.change_to_task(localtask, token))
+        bot.proceed_status(proceed_to[1], localtask)
+        bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ успешно обработан и отправлен на pending\n")
+
+        # Проверка срочности заказа
+        # if order.asap:
+        #     #Заглушка назначение исполнителя системой
+        #     if set_provider(order.ticket, order.provider) == "success":
+        #         bot.proceed_status(proceed_to[0], localtask)
+        #     else:
+        #         bot.bot_log(botname+" "+str(datetime.now())+" "+"Ошибка назначения исполнителя\n")
+        # else:
+        #         localtask.status = 220
+        #         bot.proceed_status(proceed_to[0], localtask)
+        #         print(localtask)
+        # bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ успешно обработан и отправлен на assigned\n")
+        # Проверка срочности заказа
+
+
+def get_balance(client):
+    headers = {'Authorization': f'Token {token}'}
+    # Передаем id пользователя и получаем его баланс
+    response = requests.get(config.API_URL + f"/api/example/{client}", headers=headers)
+    print(response.json())
+    ordertext = response.json()
+
+    if not ordertext:
+        print("Empty array")
+    else:
+        print(ordertext[0], "PROCESSING")
+        try:
+            balance = ordertext[0].get('balance')
+            return balance
+        except Exception as ex:
+            print(ex)
+
+
+# set provider?
+def choose_provider(auth_token, geo):
+    providers = requests.get(config.API_URL + "/dbsynce/api/provider/", headers=auth_token)
+    provider = providers.json()[0]['id']
+    return provider
+
+
+def set_provider(localtask_id):
+    token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "my/api/v1/auth/token/login/")
+    headers = {'Authorization': f'Token {token}'}
+    provider = choose_provider(headers, 'geoposition')
+    # NOTE:BUG:ERROR:FIXME: модель сервис не должна была содержать поле id_provider
+    # service = requests.get(config.API_URL+f"/dbsynce/api/service/?id_provider={provider}", headers=headers)
+    service = service.json()[0]
+    data = {'provider': int(provider)}
+    # print(data)
+    # print(str(config.API_URL+f"/dbsynce/api/orders/{localtask_id}/"))
+    response = requests.patch(config.API_URL + f"/dbsynce/api/orders/{localtask_id}/", headers=headers, json=data)
+    return response, provider, service
+
+    # if not ordertext:
+    #     print("Empty array")
+    # else:
+    #     print(ordertext[0], "PROCESSING")
+    #     try:
+    #         message = ordertext[0].get('message')
+    #         return message
+    #     except Exception as ex:
+    #         print(ex)
+
+
+def open_service_request_booked():
+    log_thread = threading.Thread(target=log_handler)
+    log_thread.daemon = True
+    log_thread.start()
+
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        if (str(localtask.status) != str(operating_status)):
+            # bot.proceed_status(proceed_to[-1],localtask) #временная проверка отправки
+            print(localtask)
+            localtask.status = '239'
+            jsreq.change_to_task(localtask, token)
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+        else:
+            bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+            t1 = threading.Thread(target=open_service_request_booked_process, args=([localtask]))
+            t1.start()
+        # elif (localtask.provider==T):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        # bot.proceed_status(proceed_to[0],localtask)
+        # print("Заказ возвращен в очередь\n")
+        # print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# #надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "my/api/v1/auth/token/login/")
+# #ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist_dbsynce = jsreq.requestGetList(token,
+                                        config.API_URL + "/dbsynce/api/orders/")  ###Должна быть проверка между двумя
+
+# # print (len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_service_request_booked)
+
+# print(set_provider('localtask'))

+ 173 - 0
handlers/open_service_request_booked_v2.py

@@ -0,0 +1,173 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import requests
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_service_request_booked"
+
+operating_status = 211
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["9090@ej.sharix-app.org", "test@ej.sharix-app.org", "open_template_bot@ej.sharix-app.org",
+             "799999999990@ej.shaix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = ["open_service_request_assigned@ej.sharix-app.org", "open_service_request_pending@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+    print(text)
+    print(user)
+    print(f'This is text{text} and this is\n\n{user}')
+    # print (str(user).split("/")[0])
+    # print('good')
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_service_request_booked_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и возвращен в очередь\n")
+
+
+def open_service_request_booked_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    order = jsreq.jsonToOrder(localtask)
+    # Пока заглушка
+    balance = get_balance(order.client)
+
+    price = order.real_price
+
+    if balance > price:
+        # Заказ на основного водителя?
+        if order.provider:
+            bot.proceed_status(proceed_to[1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ успешно обработан\n")
+        else:
+            # Проверка срочности заказа
+            if order.asap:
+                # Заглушка назначение исполнителя системой
+                if set_provider(order.ticket, order.provider) == "success":
+                    bot.proceed_status(proceed_to[0], localtask)
+                else:
+                    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Ошибка назначения исполнителя\n")
+            else:
+                bot.proceed_status(proceed_to[1], localtask)
+
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ успешно обработан\n")
+    else:
+        # Заглушка получения оплаты от клиента
+        pass
+
+
+def get_balance(client):
+    headers = {'Authorization': f'Token {token}'}
+    # Передаем id пользователя и получаем его баланс
+    response = requests.get(config.API_URL + f"/api/example/{client}", headers=headers)
+    print(response.json())
+    ordertext = response.json()
+
+    if not ordertext:
+        print("Empty array")
+    else:
+        print(ordertext[0], "PROCESSING")
+        try:
+            balance = ordertext[0].get('balance')
+            return balance
+        except Exception as ex:
+            print(ex)
+
+
+def set_provider(ticket, provider):
+    headers = {'Authorization': f'Token {token}'}
+    data = {'ticket': ticket,
+            'provider': provider}
+    response = requests.post(config.API_URL + f"/api/example/set-provider", headers=headers, data=data)
+    print(response.json())
+    ordertext = response.json()
+
+    if not ordertext:
+        print("Empty array")
+    else:
+        print(ordertext[0], "PROCESSING")
+        try:
+            message = ordertext[0].get('message')
+            return message
+        except Exception as ex:
+            print(ex)
+
+
+def open_service_request_booked():
+    # while (len(tasklist)):
+    #     localtask=tasklist.pop(0)
+    bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+    print("EACH TASKLIST", tasklist)
+
+    if (localtask.status != operating_status):
+        bot.proceed_status(proceed_to[-1], localtask)
+        bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+        # continue
+
+    t1 = threading.Thread(target=open_service_request_booked_process, args=(localtask))
+    t1.start()
+
+    # если никакие обработчики не подошли - отправляем обратно в очередь
+    bot.proceed_status(proceed_to[0], localtask)
+    print("Заказ возвращен в очередь\n")
+    print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/base/auth/token/login/")
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist = jsreq.requestGetList(token, config.API_URL + "/webservice/api/webservice/")
+
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_service_request_booked)

+ 130 - 0
handlers/open_service_request_closed.py

@@ -0,0 +1,130 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import requests
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_service_request_booked"
+##############################
+# operating_status='211'
+# JID=botname+"@"+config.JSERVER
+# PORT=config.PORT
+
+# PASSWORD=hashlib.md5((botname+config.PASSWORD).encode('utf-8')).hexdigest()
+
+
+###################
+botname = "open_service_request_closed"
+
+operating_status = 239
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "my/api/v1/auth/token/login/")
+headers = {'Authorization': f'Token {token}'}
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["799999999990@ej.sharix-app.org", "test@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_st_request_new@ej.sharix-app.org", "open_service_request_closed@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+def log_handler():
+    while True:
+        with open(f'{botname}.txt', 'a') as log_file:
+            log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {botname} is still running...\n")
+        time.sleep(3600)
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+    if (str(user).split("/")[0]) in listen_to:
+        if text is not None:
+            orderObj = jsreq.jsonToOrder(text)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_service_request_closed_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и отправлен в очередь\n")
+
+
+def open_service_request_closed_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+    response = requests.delete(config.API_URL + f"/dbsynce/api/orders/{localtask.id}/", headers=headers)
+    text = (config.API_URL + f"dbsynce/api/orders/{localtask.id}/")
+    if response:
+        bot.proceed_status(proceed_to[2], localtask)
+        bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ удален\n")
+    else:
+        bot.proceed_status(proceed_to[-1], localtask)
+        bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+
+
+def open_service_request_closed():
+    log_thread = threading.Thread(target=log_handler)
+    log_thread.daemon = True
+    log_thread.start()
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        # if (localtask.status!=operating_status):
+        #     bot.proceed_status(proceed_to[-1],localtask)
+        #     bot.bot_log(botname+" "+str(datetime.now())+" "+"Заказ не по адресу, перенаправляем на форсмажор\n")
+        #     continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        if (localtask.status in ("239", "211", "212", "220", "221", "222", "231", "238", "229")):
+            t1 = threading.Thread(target=open_service_request_closed_process, args=([localtask]))
+            t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "my/api/v1/auth/token/login/")
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist_dbsynce = jsreq.requestGetList(token, config.API_URL + "/dbsynce/api/orders/")
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_service_request_closed)

+ 141 - 0
handlers/open_service_request_declined.py

@@ -0,0 +1,141 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_service_request_declined"
+
+operating_status = 229
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+users = ["799999999990@ej.sharix-app.org"]
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["test@ej.sharix-app.org", "799999999990@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_service_request_cancelled@ej.sharix-app.org",
+              "open_service_request_booked@ej.sharix-app.org", "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+def log_handler():
+    while True:
+        with open(f'{botname}.txt', 'a') as log_file:
+            log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {botname} is still running...\n")
+        time.sleep(3600)
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrder(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_service_request_declined_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и отправлен в очередь\n")
+
+
+def open_service_request_declined_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    order = jsreq.jsonToOrder(localtask)
+
+    # Заглушка с счетчиком
+
+    # Заказ может быть выполнен другим
+    if True:
+        bot.proceed_status(proceed_to[1], localtask)
+        bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ отправлен\n")
+    else:
+        # Заглушка. Сброс пометки что заказ на основного водителя
+        bot.proceed_status(proceed_to[2], localtask)
+        bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ отправлен\n")
+
+
+def send_message():
+    pass
+
+
+def create_ticket():
+    pass
+
+
+def open_service_request_declined():
+    log_thread = threading.Thread(target=log_handler)
+    log_thread.daemon = True
+    log_thread.start()
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+        if (localtask.status != operating_status):
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_service_request_declined_process, args=(localtask))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "my/api/v1/auth/token/login/")
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist_dbsynce = jsreq.requestGetList(token, config.API_URL + "/dbsynce/api/orders/")
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_service_request_declined)

+ 150 - 0
handlers/open_service_request_done.py

@@ -0,0 +1,150 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_service_request_done"
+
+operating_status = '241'
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+users = ["799999999990@ej.sharix-app.org"]
+
+drivers = ["799999999998@ej.sharix-app.org"]
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["open_service_request_process@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_st_request_new@ej.sharix-app.org", "open_service_request_closed@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+statuses = ['DONE', 'WONTFIX', 'DUBLICATE']
+
+
+def log_handler():
+    while True:
+        with open(f'{botname}.txt', 'a') as log_file:
+            log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {botname} is still running...\n")
+        time.sleep(3600)
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrder(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_service_request_done_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и отправлен в очередь\n")
+
+
+def open_service_request_done_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    order = jsreq.jsonToOrder(localtask)
+    status = order.status
+
+    # Заглушка + Оплата
+    create_ticket(localtask)
+    # отправка формы
+    send_message()
+
+    # Заглушка с таймером
+
+    bot.proceed_status(proceed_to[2], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ отправлен\n")
+
+
+# Заглушка
+def send_message(localtask):
+    pass
+
+
+def create_ticket(localtask):
+    bot.proceed_status(proceed_to[1], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ отправлен\n")
+    pass
+
+
+def open_service_request_done():
+    log_thread = threading.Thread(target=log_handler)
+    log_thread.daemon = True
+    log_thread.start()
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+
+        if (localtask.status != operating_status):
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_service_request_done_process, args=(localtask))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "my/api/v1/auth/token/login/")
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist_dbsynce = jsreq.requestGetList(token, config.API_URL + "/dbsynce/api/orders/")
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_service_request_done)

+ 131 - 0
handlers/open_service_request_forcemajeure.py

@@ -0,0 +1,131 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_service_request_forcemajeure"
+
+operating_status = 239
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["test@ej.sharix-app.org", "open_template_bot@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_st_request_new@ej.sharix-app.org", "open_service_request_declined@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+statuses = ['DONE', 'WONTFIX', 'DUBLICATE']
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_service_request_forcemajeure_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и отправлен в очередь\n")
+
+
+def open_service_request_forcemajeure_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    order = jsreq.jsonToOrder(localtask)
+    status = order.status
+
+    # Заглушка
+    create_ticket(localtask)
+    # ???
+    if order.status in statuses:
+        order.status = status
+    else:
+        bot.proceed_status(proceed_to[0], localtask)
+        bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ отправлен\n")
+
+
+def create_ticket(localtask):
+    bot.proceed_status(proceed_to[1], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ отправлен\n")
+    pass
+
+
+def open_service_request_forcemajeure():
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+
+        if (localtask.status != operating_status):
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_service_request_forcemajeure_process, args=(localtask))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/auth/token/login/")
+
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist_dbsynce = jsreq.requestGetList(token, config.API_URL + "/tickets/api/tickets/?list_id=10")
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_service_request_forcemajeure)

+ 140 - 0
handlers/open_service_request_pending.py

@@ -0,0 +1,140 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_service_request_pending"
+
+operating_status = '220'
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["open_service_request_booked@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_service_request_assigned@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org", "799999999998@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    # print (str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        # print(text)
+        # print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrder(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_service_request_pending_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и отправлен в очередь\n")
+
+
+def open_service_request_pending_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    order = jsreq.jsonToOrder(localtask)
+
+    # Заглушка. Может ли что-то пойти не так
+    if True:
+        if order.time_start_predicted < time.time():
+            bot.proceed_status(proceed_to[0], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и отправлен в очередь\n")
+            return
+        # Заглушка активная ли стадия заказа
+        elif order.status == "active":
+            localtask.status = 212
+            jsreq.change_to_task(localtask, token)
+            bot.proceed_status(proceed_to[1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ отправлен\n")
+        # else:
+        #     bot.proceed_status(proceed_to[2],localtask)
+        #     bot.bot_log(botname+" "+str(datetime.now())+" "+"Заказ отправлен\n")
+        #     # Заглушка на получение ответа
+        #     pass
+    # else:
+    #     bot.proceed_status(proceed_to[1],localtask)
+    #     bot.bot_log(botname+" "+str(datetime.now())+" "+"Заказ отправлен\n")
+
+
+def send_message():
+    pass
+
+
+def open_service_request_pending():
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        # print("EACH TASKLIST", tasklist)
+
+        if (localtask.status != operating_status):
+            localtask.status = 239
+            jsreq.change_to_task(localtask, token)
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_service_request_pending_process, args=([localtask]))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        # print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "my/api/v1/auth/token/login/")
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist_dbsynce = jsreq.requestGetList(token, config.API_URL + "/dbsynce/api/orders/")
+# print (len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_service_request_pending)
+
+# Получение сообщения от водителя

+ 133 - 0
handlers/open_service_request_preforcemajeure.py

@@ -0,0 +1,133 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_service_request_preforcemajeure"
+
+operating_status = 239
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["test@ej.sharix-app.org", "open_template_bot@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_st_request_new@ej.sharix-app.org", "open_service_request_declined@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+statuses = ['DONE', 'WONTFIX', 'DUBLICATE']
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_service_request_preforcemajeure_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и отправлен в очередь\n")
+
+
+def open_service_request_preforcemajeure_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    order = jsreq.jsonToOrder(localtask)
+    status = order.status
+
+    # Заглушка
+    create_ticket(localtask)
+    # ???
+    if order.status in statuses:
+        order.status = status
+    else:
+
+        # Заглушка с таймером
+        bot.proceed_status(proceed_to[0], localtask)
+        bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ отправлен\n")
+
+
+def create_ticket(localtask):
+    bot.proceed_status(proceed_to[1], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ отправлен\n")
+    pass
+
+
+def open_service_request_preforcemajeure():
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+
+        if (localtask.status != operating_status):
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_service_request_preforcemajeure_process, args=(localtask))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/auth/token/login/")
+
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist = jsreq.requestGetList(token, config.API_URL + "/tickets/api/tickets/?list_id=10")
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_service_request_preforcemajeure)

+ 120 - 0
handlers/open_service_request_prestart.py

@@ -0,0 +1,120 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_service_request_prestart"
+
+operating_status = 222
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["test@ej.sharix-app.org", "open_template_bot@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_service_request_preforcemajeure@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_service_request_prestart_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и отправлен в очередь\n")
+
+
+def open_service_request_prestart_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    order = jsreq.jsonToOrder(localtask)
+
+    if order.asap:
+        bot.proceed_status(proceed_to[1], localtask)
+        bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ отправлен\n")
+    else:
+        bot.proceed_status(proceed_to[0], localtask)
+        bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ отправлен\n")
+
+
+def open_service_request_prestart():
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+
+        if (localtask.status != operating_status):
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_service_request_prestart_process, args=(localtask))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/auth/token/login/")
+
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist = jsreq.requestGetList(token, config.API_URL + "/tickets/api/tickets/?list_id=10")
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_service_request_prestart)

+ 179 - 0
handlers/open_service_request_process.py

@@ -0,0 +1,179 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_service_request_process"
+
+operating_status = '231'
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+drivers = ["799999999998@ej.sharix-app.org"]
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["open_service_request_accepted@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_service_request_done@ej.sharix-app.org",
+              "open_service_request_preforcemajeure@ej.sharix-app.org",
+              "open_service_request_declined@ej.sharix-app.org", "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+def log_handler():
+    while True:
+        with open(f'{botname}.txt', 'a') as log_file:
+            log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {botname} is still running...\n")
+        time.sleep(3600)
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+    if (str(user).split("/")[0]) in listen_to:
+        if text is not None:
+            orderObj = jsreq.jsonToOrder(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def message_answer(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+    if (str(user).split("/")[0]) in drivers:
+        print('answer_handler')
+        if text is not None:
+            answerObj = jsreq.to_answer(text)
+            answers.append(answerObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший ответ успешно добавлен в очередь обработки\n")
+
+
+def open_service_request_process_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и отправлен в очередь\n")
+
+
+def wait_for_answer(localtask):
+    order = localtask
+    # Здесь можно реализовать логику выбора водителя
+    while True:
+        if len(answers) > 0:
+            answer = answers.pop(0)
+            if answer.answer == 'Complete':
+                localtask.status = '241'
+                jsreq.change_to_task(localtask, token)
+                bot.proceed_status(proceed_to[1], localtask)
+                bot.bot_log(botname + " " + str(datetime.now()) + f" Заказ отправлен на {proceed_to[1]}\n")
+            break
+        else:
+            print("Ожидание ответа...")
+            time.sleep(30)
+
+
+def open_service_request_assigned_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+    order = localtask
+    if order.provider != None:
+        wait_thread = threading.Thread(target=wait_for_answer, args=(localtask,))
+        wait_thread.start()
+
+
+def open_service_request_process_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+    order = localtask
+    wait_thread = threading.Thread(target=wait_for_answer, args=(localtask,))  # ожидание выполнения заказа
+    wait_thread.start()
+
+    # Заглушка проверка баланса
+    # if check_balance() >= order.real_price:
+    # if True:
+    #     # Заглушка. Расчетное время прибытия на следующую точку превышаетзапланированное на Х
+    #     if True:
+    #         bot.proceed_status(proceed_to[1],localtask)
+    #         bot.bot_log(botname+" "+str(datetime.now())+" "+"Заказ отправлен\n")
+    #     else:
+    #         bot.proceed_status(proceed_to[0],localtask)
+    #         bot.bot_log(botname+" "+str(datetime.now())+" "+"Заказ подождал и отправлен в очередь\n")
+    # else:
+    #     # Оплата
+
+    #     bot.proceed_status(proceed_to[1],localtask)
+    #     bot.bot_log(botname+" "+str(datetime.now())+" "+"Заказ отправлен\n")
+
+    #     pass
+
+
+def check_balance():
+    pass
+
+
+def open_service_request_process():
+    log_thread = threading.Thread(target=log_handler)
+    log_thread.daemon = True
+    log_thread.start()
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        if (localtask.status != operating_status):
+            localtask.status = '239'
+            jsreq.change_to_task(localtask, token)
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_service_request_process_process, args=[localtask])
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        # bot.proceed_status(proceed_to[0],localtask)
+        # print("Заказ возвращен в очередь\n")
+        # print(tasklist)
+
+
+# Авторизация и запуск бота
+
+answers = []
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "my/api/v1/auth/token/login/")
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist_dbsynce = jsreq.requestGetList(token, config.API_URL + "/dbsynce/api/orders/")
+
+bot = JabberBot(JID, PASSWORD, PORT)
+bot.register_handler('message', message_handler)
+bot.register_handler('message', message_answer)
+bot.start(open_service_request_process)

+ 129 - 0
handlers/open_st_request_assigned.py

@@ -0,0 +1,129 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_st_request_assigned"
+
+operating_status = 121
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["test@ej.sharix-app.org", "open_template_bot@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_st_request_wontfix@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_st_request_assigned_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и возвращен в очередь\n")
+
+
+def open_st_request_assigned_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    order = jsreq.jsonToOrder(localtask)
+
+    # Проверяем наличие маркера обработчика
+    if order.marker:
+        # Вызываем алгоритм обработки в соответствии с маркером
+        process_with_handler(order)
+    else:
+        # Заглушка Если таймер неактивен, отправляем в st_request_wontfix
+        if True:
+            bot.proceed_status(proceed_to[1], localtask)
+
+
+# Пока не уверен
+def process_with_handler(order):
+    # Алгоритм назначения исполнителя
+    # ...
+    return True
+
+
+def open_st_request_assigned():
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+
+        if (localtask.status != operating_status):
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_st_request_assigned_process, args=(localtask))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/auth/token/login/")
+
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist = jsreq.requestGetList(token, config.API_URL + "/tickets/api/tickets/?list_id=10")
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_st_request_assigned)

+ 130 - 0
handlers/open_st_request_done.py

@@ -0,0 +1,130 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_st_request_done"
+
+operating_status = 149
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["test@ej.sharix-app.org", "open_template_bot@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_st_request_closed@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_st_request_done_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и возвращен в очередь\n")
+
+
+def open_st_request_done_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    order = jsreq.jsonToOrder(localtask)
+    idle_value = idle_value - 1
+
+    if idle_value < 1:
+        bot.proceed_status(proceed_to[1], localtask)
+    else:
+        push_notifications(order)
+        open_st_request_done_wait(100, localtask)
+    # Затычка
+    if True:
+        open_st_request_done_process(localtask)
+
+
+# Пока не уверен
+def push_notifications(order):
+    # Отправка уведомлений
+    # ...
+    return True
+
+
+def open_st_request_done():
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+
+        if (localtask.status != operating_status):
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_st_request_done_process, args=(localtask))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/auth/token/login/")
+
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist = jsreq.requestGetList(token, config.API_URL + "/tickets/api/tickets/?list_id=10")
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_st_request_done)

+ 130 - 0
handlers/open_st_request_dublicate.py

@@ -0,0 +1,130 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_st_request_dublicate"
+
+operating_status = 149
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["test@ej.sharix-app.org", "open_template_bot@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_st_request_closed@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_st_request_dublicate_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и возвращен в очередь\n")
+
+
+def open_st_request_dublicate_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    order = jsreq.jsonToOrder(localtask)
+    idle_value = idle_value - 1
+
+    if idle_value < 1:
+        bot.proceed_status(proceed_to[1], localtask)
+    else:
+        push_notifications(order)
+        open_st_request_dublicate_wait(100, localtask)
+    # Затычка
+    if True:
+        open_st_request_dublicate_process(localtask)
+
+
+# Пока не уверен
+def push_notifications(order):
+    # Отправка уведомлений
+    # ...
+    return True
+
+
+def open_st_request_dublicate():
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+
+        if (localtask.status != operating_status):
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_st_request_dublicate_process, args=(localtask))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/auth/token/login/")
+
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist = jsreq.requestGetList(token, config.API_URL + "/tickets/api/tickets/?list_id=10")
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_st_request_dublicate)

+ 129 - 0
handlers/open_st_request_in_process.py

@@ -0,0 +1,129 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_st_request_in_process"
+
+operating_status = 131
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["test@ej.sharix-app.org", "open_template_bot@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_st_request_wontfix@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_st_request_in_process_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и возвращен в очередь\n")
+
+
+def open_st_request_in_process_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    order = jsreq.jsonToOrder(localtask)
+
+    # Проверяем наличие маркера обработчика
+    if order.marker:
+        # Вызываем алгоритм обработки в соответствии с маркером
+        process_with_handler(order)
+    else:
+        # Заглушка Если таймер неактивен, отправляем в st_request_wontfix
+        if True:
+            bot.proceed_status(proceed_to[1], localtask)
+
+
+# Пока не уверен
+def process_with_handler(order):
+    # Алгоритм назначения исполнителя
+    # ...
+    return True
+
+
+def open_st_request_in_process():
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+
+        if (localtask.status != operating_status):
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_st_request_in_process_process, args=(localtask))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/auth/token/login/")
+
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist = jsreq.requestGetList(token, config.API_URL + "/tickets/api/tickets/?list_id=10")
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_st_request_in_process)

+ 148 - 0
handlers/open_st_request_new.py

@@ -0,0 +1,148 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_st_request_new"
+
+operating_status = 111
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["test@ej.sharix-app.org", "open_template_bot@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_st_request_assigned@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_service_request_booked_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и возвращен в очередь\n")
+
+
+def open_stequest_new_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    order = jsreq.jsonToOrder(localtask)
+
+    if order.provider:
+        st_request_assigned(order)
+    else:
+        # Что такое маркер обработчика?
+        if not order.marker:
+            add_marker(order)
+            assign_executor(localtask)
+
+        if assign_executor(order):
+            st_request_assigned(localtask)
+        else:
+            # Проверка таймера
+            if True:
+                if assign_executor(order):
+                    st_request_assigned(localtask)
+            else:
+                add_marker(order)
+                assign_executor(order)
+
+
+def st_request_assigned(localtask):
+    bot.proceed_status(proceed_to[1], localtask)
+
+
+# Пока не уверен
+def assign_executor(order):
+    # Алгоритм назначения исполнителя
+    # ...
+    return True
+
+
+def add_marker(order):
+    # 
+    pass
+
+
+def open_service_request_booked():
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+
+        if (localtask.status != operating_status):
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_stequest_new_process, args=(localtask))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/auth/token/login/")
+
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist = jsreq.requestGetList(token, config.API_URL + "/tickets/api/tickets/?list_id=10")
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_service_request_booked)

+ 148 - 0
handlers/open_st_request_reopened.py

@@ -0,0 +1,148 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_st_request_reopened"
+
+operating_status = 110
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["test@ej.sharix-app.org", "open_template_bot@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_st_request_assigned@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_stequest_reopened_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и возвращен в очередь\n")
+
+
+def open_stequest_reopened_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    order = jsreq.jsonToOrder(localtask)
+
+    if order.provider:
+        st_request_assigned(order)
+    else:
+        # Что такое маркер обработчика?
+        if not order.marker:
+            add_marker(order)
+            assign_executor(localtask)
+
+        if assign_executor(order):
+            st_request_assigned(localtask)
+        else:
+            # Проверка таймера
+            if True:
+                if assign_executor(order):
+                    st_request_assigned(localtask)
+            else:
+                add_marker(order)
+                assign_executor(order)
+
+
+def st_request_assigned(localtask):
+    bot.proceed_status(proceed_to[1], localtask)
+
+
+# Пока не уверен
+def assign_executor(order):
+    # Алгоритм назначения исполнителя
+    # ...
+    return True
+
+
+def add_marker(order):
+    # 
+    pass
+
+
+def open_stequest_reopened():
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+
+        if (localtask.status != operating_status):
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_stequest_reopened_process, args=(localtask))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/auth/token/login/")
+
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist = jsreq.requestGetList(token, config.API_URL + "/tickets/api/tickets/?list_id=10")
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_stequest_reopened)

+ 134 - 0
handlers/open_st_request_wontfix.py

@@ -0,0 +1,134 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "open_st_request_wontfix"
+
+operating_status = 149
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["test@ej.sharix-app.org", "open_template_bot@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = [botname, "open_st_request_closed@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_st_request_wontfix_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и возвращен в очередь\n")
+
+
+def open_st_request_wontfix_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    order = jsreq.jsonToOrder(localtask)
+    idle_value = idle_value - 1
+
+    if idle_value < 1:
+        st_request_wontfix(localtask)
+    else:
+        push_notifications(order)
+        open_st_request_wontfix_wait(100, localtask)
+    # Затычка
+    if True:
+        open_st_request_wontfix_process(localtask)
+
+
+def st_request_wontfix(localtask):
+    bot.proceed_status(proceed_to[1], localtask)
+
+
+# Пока не уверен
+def push_notifications(order):
+    # Отправка уведомлений
+    # ...
+    return True
+
+
+def open_st_request_wontfix():
+    while (len(tasklist)):
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+
+        if (localtask.status != operating_status):
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        # if (localtask.title!="10"):
+        #     t1=threading.Thread(target=open_service_request_booked_wait, args=(5,localtask))
+        #     t1.start()
+
+        # if (localtask.title=="101"):
+        #     t1=threading.Thread(target=open_service_request_booked_process, args=(10,localtask))
+        #     t1.start()
+
+        t1 = threading.Thread(target=open_st_request_wontfix_process, args=(localtask))
+        t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/auth/token/login/")
+
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist = jsreq.requestGetList(token, config.API_URL + "/tickets/api/tickets/?list_id=10")
+print(len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_st_request_wontfix)

+ 202 - 0
handlers/open_student_handler.py

@@ -0,0 +1,202 @@
+import requests
+import xmpp
+from xmpp import cli
+import config
+from BotClass import JabberBot
+import json
+#раскомментировать, когда перейдем на разные пароли
+import hashlib
+from datetime import datetime, timedelta
+
+import time
+import threading
+
+#test
+import jsonAndRequest as jsreq
+
+global tasklist
+
+botname="open_student_handler"
+
+operating_status=000
+JID=botname+"@"+config.JSERVER
+PORT=config.PORT
+
+PASSWORD=hashlib.md5((botname+config.PASSWORD).encode('utf-8')).hexdigest()
+
+print(JID, PASSWORD)
+
+#таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to=["open_student_handler@ej.sharix-app.org", "open_template_bot@ej.sharix-app.org"]
+
+#тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to=[botname, "open_st_request_assigned@ej.sharix-app.org", "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+#максимальное значение попыток обработать Тикет
+idle_value=10
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()#текст сообщения боту
+    user = mess.getFrom()#отправитель сообщения
+   
+    print (str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            ticketObj = jsreq.jsonToTicket(text)
+            print (ticketObj)
+            tasklist.append(ticketObj)
+            bot.bot_log(str(datetime.now())+" Поступивший Тикет успешно добавлен в очередь обработки\n")
+
+def open_student_handler_wait(period,localtask):
+    bot.bot_log(botname+" "+str(datetime.now())+" "+"Тикет ожидает\n")
+    time.sleep(period)
+    
+    #ВАЖНО! Надо скорее всего через API редактировать Тикет, иначе возможна потеря данных
+    localtask.title=localtask.title+"1"
+
+    #обязательно данный обработчик должен заканчиваться передачей Тикета куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0],localtask)
+    bot.bot_log(botname+" "+str(datetime.now())+" "+"Тикет подождал и возвращен в очередь\n")
+
+def open_student_handler_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет в обработчике\n")
+
+    ticket = jsreq.jsonToTicket(localtask)
+    
+    if ticket.status == "Accepted":
+        all_systems_registered = True
+        
+        if all_systems_registered:
+            user = ticket.created_by
+            if register_user_in_group():
+                send_successful_registration_notification(ticket)
+            else:
+                all_systems_registered = False
+                continue
+        
+        # Проверяем, прошла ли неделя с момента создания заявки
+        if datetime.now() - ticket.created_at >= timedelta(weeks=1):
+            # Если неделя прошла и не все галочки стоят, отправляем уведомление о частичной регистрации
+            if not all_systems_registered:
+                send_partial_registration_notification(ticket)
+            # Закрываем заявку
+            close_ticket(ticket)
+        
+        # Если все галочки стоят, отправляем уведомление об успешной регистрации во всех системах
+        if all_systems_registered():
+            send_all_systems_success_notification(ticket)
+
+    elif ticket.status == "Declined":
+        # Отправляем уведомление о том, что заявка отклонена
+        send_declined_notification(ticket):
+        # Удаляем запись в таблице Practice
+        remove_from_practice(ticket):
+            
+        # Заявка уходит в архив через неделю
+        if datetime.now() - ticket.created_at >= timedelta(weeks=1):
+            archive_ticket(ticket)
+
+    print(ticket)
+
+def register_user_in_group(user_id):
+    url = config.url+f"api/v1/platform/sharix-users/{user_id}/"
+    
+    payload = {
+        "groups": [101]
+    }
+    
+    headers = {
+        "Content-Type": "application/json",
+    }
+    
+    try:
+        response = requests.put(url, data=json.dumps(payload), headers=headers)
+        
+        if response.status_code == 200:
+            print("Группа успешно добавлена пользователю.")
+            return True
+        else:
+            print(f"Ошибка: {response.status_code} - {response.text}")
+            return False
+    
+    except requests.exceptions.RequestException as e:
+        print(f"Ошибка запроса: {e}")
+        return False
+
+
+def send_all_systems_success_notification(ticket):
+    
+def send_successful_registration_notification(ticket):
+
+def send_partial_registration_notification(ticket):
+    
+def send_declined_notification(ticket):
+    
+    
+def close_ticket(ticket):
+
+def archive_ticket(ticket):
+    
+def remove_from_practice(ticket):
+    url = config.url+f"/{ticket.id}/"
+    
+    headers = {
+        "Content-Type": "application/json",
+    }
+    
+    try:
+        response = requests.delete(url, headers=headers)
+        
+        if response.status_code == 204:
+            print(f"Тикет с ID {ticket.id} успешно удалён.")
+        else:
+            print(f"Ошибка: {response.status_code} - {response.text}")
+    
+    except requests.exceptions.RequestException as e:
+        print(f"Ошибка запроса: {e}")
+
+
+def open_student_handler_assigned(localtask):
+    bot.proceed_status(proceed_to[1],localtask)
+
+
+def open_student_handler_booked():
+    while (len(tasklist)):
+        localtask=tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " "+ "Тикет в очереди на обработке\n")
+        print("EACH TASKLIST", tasklist)
+
+        if (localtask.status!=operating_status):
+            bot.proceed_status(proceed_to[-1],localtask)
+            bot.bot_log(botname+" "+str(datetime.now())+" "+"Тикет не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        t1=threading.Thread(target=oopen_student_handler_process, args=(localtask))
+        t1.start()
+
+        bot.proceed_status(proceed_to[0],localtask)
+        print("Тикет возвращен в очередь\n")
+        print(tasklist)
+
+#Авторизация и запуск бота
+
+#пустой список Тикетов
+tasklist = []
+
+#надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL+"/auth/token/login/")
+
+#ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist=jsreq.requestGetList(token, config.API_URL+"/tickets/api/ticket_list/1303")
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_student_handler_booked)
+
+
+

+ 123 - 0
handlers/open_template_bot.py

@@ -0,0 +1,123 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+# В этом файле содержится только то, что запускает конкретный обработчик
+
+# botname="open_st_request_assigned"
+botname = "open_template_bot"
+operating_status = 210
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+# раскомментировать, когда перейдем на разные пароли
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["test@ej.sharix-app.org", "open_template_bot@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = ["open_template_bot@ej.sharix-app.org", "test@ej.sharix-app.org", "test1@ej.sharix-app.org",
+              "open_service_request_forcemajeure@ej.sharix-app.org"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+def message_handler(conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+    # user = mess.getNode()#только jid
+
+    # нужна проверка, данный обработчик вообще должен от данного отправителя получать сообщения или нет. Подсказка ниже
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            bot.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+def open_bot_template_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает\n")
+    time.sleep(period)
+
+    # ВАЖНО! Надо скорее всего через API редактировать заказ, иначе возможна потеря данных
+    localtask.title = localtask.title + "1"
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ подождал и возвращен в очередь\n")
+
+
+def open_bot_template_process(localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ в обработчике\n")
+
+    # ВАЖНО! Надо через API редактировать заказ, иначе возможна потеря данных
+    # localtask.title +=1
+
+    bot.proceed_status(proceed_to[1], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ успешно обработан\n")
+
+
+def open_bot_template():
+    # print("Тут описывается работа со списком задач в данном статусе")
+    while (len(tasklist)):
+        # for i in range(len(tasklist)):
+        # проверяем элемент tasklist[i]
+        # print (i, len(tasklist))
+        localtask = tasklist.pop(0)
+        bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Заказ в очереди на обработке\n")
+        # bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + str(i) + " " + "Заказ в очереди на обработке\n")
+        # print ("EACH TASKLIST", tasklist[i])
+        # localtask=tasklist.pop(i)
+
+        # если боту почему-то пришла не его заявка - это явно ошибка движения процессов и отдаем в форсмажор - этот обработчик указывать стоит всегда последним
+        if (localtask.status != operating_status):
+            bot.proceed_status(proceed_to[-1], localtask)
+            bot.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ не по адресу, перенаправляем на форсмажор\n")
+            continue
+
+        if (localtask.title != "10"):
+            t1 = threading.Thread(target=open_bot_template_wait, args=(5, localtask))
+            t1.start()
+
+        if (localtask.title == "101"):
+            t1 = threading.Thread(target=open_bot_template_process, args=(10, localtask))
+            t1.start()
+
+        # если никакие обработчики не подошли - отправляем обратно в очередь
+        bot.proceed_status(proceed_to[0], localtask)
+        print("Заказ возвращен в очередь\n")
+        print(tasklist)
+
+
+# Авторизация и запуск бота
+
+# пустой список заказов
+tasklist = []
+
+# надо инициализировать tasklist при запуске из API
+token = jsreq.requestGetToken(botname, PASSWORD, config.API_URL + "/base/auth/token/login/")
+# ВАЖНО! Надо еще фильтровать список по статусу обработки заявки
+tasklist = jsreq.requestGetList(token, config.API_URL + "/webservice/api/webservice/")
+
+print(JID, PASSWORD, PORT)
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.register_handler('message', message_handler)
+bot.start(open_bot_template)

+ 21 - 0
handlers/order_functions.py

@@ -0,0 +1,21 @@
+# раскомментировать, когда перейдем на разные пароли
+
+# test
+
+global tasklist
+
+
+def send_message(order):
+    task_apply = {
+        'driver_id': None,
+        'apply': False,
+        'task_id': order.id
+    }
+    print(order.id)
+
+    bot.proceed_status('driver_jabber', task_apply)
+
+
+def find_jabber_acc():
+    pass
+# поиск пользователя в джаббер для далнейшей отправки

+ 14 - 0
handlers/requirements.txt

@@ -0,0 +1,14 @@
+aiodns==3.2.0
+certifi==2022.12.7
+cffi==1.17.1
+charset-normalizer==3.1.0
+idna==3.4
+pyasn1==0.6.1
+pyasn1_modules==0.4.1
+pycares==4.5.0
+pycparser==2.22
+requests==2.29.0
+six==1.16.0
+slixmpp==1.9.1
+urllib3==1.26.15
+xmpppy==0.7.1

+ 86 - 0
handlers/st_request_in_process.py

@@ -0,0 +1,86 @@
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+import jsonAndRequest as jsreq
+
+global ticketlist
+
+botname = "st_request_wontfix"
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+listen_to = ["st_request_wontfix@ej.sharix-app.org"]
+proceed_to = ["numbers"]
+
+# Новые параметры
+INFINITE_TIMEOUT = -1  # Бесконечный таймаут
+DEFAULT_REMINDER_INTERVAL = 30 * 60  # 30 минут в секундах
+MAX_REMINDERS = 3  # Максимальное количество напоминаний
+
+
+def send_reminder(user, ticket):
+    message = f"Напоминание: необходимо принять решение по тикету {ticket.id}"
+    # Здесь должен быть код для отправки сообщения пользователю
+    print(f"Отправлено напоминание пользователю {user} о тикете {ticket.id}")
+
+
+def send_wontfix_notification(user, ticket):
+    message = f"Уведомление: тикет {ticket.id} был отмечен как WONTFIX из-за отсутствия действий"
+    # Здесь должен быть код для отправки сообщения пользователю
+    print(f"Отправлено уведомление пользователю {user} о WONTFIX для тикета {ticket.id}")
+
+
+def process_in_progress_ticket(ticket, timeout, reminder_interval):
+    start_time = datetime.now()
+    reminders_sent = 0
+
+    while True:
+        current_time = datetime.now()
+        time_in_progress = (current_time - start_time).total_seconds()
+
+        if timeout != INFINITE_TIMEOUT and time_in_progress > timeout:
+            # Превышен таймаут, меняем статус на WONTFIX
+            jsreq.requestPatchTicketUser(token, config.API_URL + f"tickets/api/ticket/{ticket.id}/",
+                                         {"status": "WONTFIX"})
+            send_wontfix_notification(ticket.assigned_to, ticket)
+            break
+
+        if time_in_progress >= (reminders_sent + 1) * reminder_interval:
+            send_reminder(ticket.assigned_to, ticket)
+            reminders_sent += 1
+
+            if reminders_sent >= MAX_REMINDERS:
+                # Превышено максимальное количество напоминаний
+                jsreq.requestPatchTicketUser(token, config.API_URL + f"tickets/api/ticket/{ticket.id}/",
+                                             {"status": "WONTFIX"})
+                send_wontfix_notification(ticket.assigned_to, ticket)
+                break
+
+        # Проверяем, не изменился ли статус тикета
+        updated_ticket_list = jsreq.requestGetTicket_user(token, config.API_URL + f"tickets/api/ticket/{ticket.id}/")
+        if updated_ticket_list and updated_ticket_list[0].status != "IN PROCESS":
+            break
+
+        time.sleep(60)  # Проверяем каждую минуту
+
+
+def status_changer():
+    while True:
+        ticketlist = jsreq.requestGetList(token, config.API_URL + "tickets/api/ticket_list/")
+        for ticket in ticketlist:
+            if ticket.status == "IN PROCESS":
+                bot.bot_log(f"{botname} {datetime.now().strftime('%Y-%m-%d')} Тикет {ticket.id} в обработке\n")
+                t1 = threading.Thread(target=process_in_progress_ticket,
+                                      args=(ticket, INFINITE_TIMEOUT, DEFAULT_REMINDER_INTERVAL))
+                t1.start()
+        time.sleep(300)  # Обновляем ticketlist каждые 5 минут
+
+
+# Инициализация и запуск бота
+token = jsreq.requestGetToken(config.API_URL + "api/v1/auth/token/login/")
+bot = JabberBot(JID, PASSWORD, PORT)
+bot.start(status_changer)

+ 10 - 0
handlers/starter.sh

@@ -0,0 +1,10 @@
+#!/bin/bash
+
+python3 open_service_request_booked.py
+python3 open_service_request_assigned.py
+python3 open_service_request_pending.py
+python3 open_service_request_accepted.py
+python3 open_service_request_process.py
+python3 open_service_request_done.py
+
+

+ 99 - 0
handlers/status_changer.py

@@ -0,0 +1,99 @@
+# раскомментировать, когда перейдем на разные пароли
+import hashlib
+import threading
+import time
+from datetime import datetime
+
+import config
+# test
+import jsonAndRequest as jsreq
+from BotClass import JabberBot
+
+global tasklist
+
+botname = "status_changer"
+
+JID = botname + "@" + config.JSERVER
+PORT = config.PORT
+
+PASSWORD = hashlib.md5((botname + config.PASSWORD).encode('utf-8')).hexdigest()
+
+# таким образом хранится список jid, от которых можно получать сообщения этому боту
+listen_to = ["status_changer@ej.sharix-app.org"]
+
+# тут хранится список jid, кому бот может отправлять сообщения в результате обработки заявки
+proceed_to = ["numbers"]
+
+# максимальное значение попыток обработать заказ
+idle_value = 10
+
+
+# обработчик входящих сообщений
+# def message_handler(conn, mess):
+#     text = mess.getBody()#текст сообщения боту
+#     user = mess.getFrom()#отправитель сообщения
+#     if (str(user).split("/")[0]) in listen_to:
+#         # print (str(user).split("/")[0])
+#         if text is not None:
+#             orderObj = jsreq.jsonToOrder(text)
+#             tasklist.append(orderObj)
+#             bot.bot_log(str(datetime.now())+" Поступивший заказ успешно добавлен в очередь обработки\n")
+
+def status_changer_wait(period, localtask):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет ожидает\n")
+    time.sleep(period)
+
+    bot.proceed_status(proceed_to[0], localtask)
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет подождал и возвращен в очередь\n")
+
+
+def status_changer_process(ticket):
+    bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет в обработчике\n")
+    tickets_new = jsreq.requestGetTicket_user(token, config.API_URL + f"tickets/api/ticket_list/{ticket.id}")
+    if ticket.id == 2103:
+        for ticket_new in tickets_new:
+            metaservice_admin(ticket_new, ticket.group)
+    elif ticket.id == '':
+        print('should be soon')  # дополнить по всем айди тикетов
+    # if ticket_new != []:
+    #     print(ticket_new)
+    # api/v1/platform/sharix-users/1/
+
+    # bot.proceed_status(proceed_to[1], localtask)
+    # bot.bot_log(botname + " " + str(datetime.now()) + " " + "Тикет успешно обработан и отправлен на pending\n")
+
+
+def metaservice_admin(ticket_new, group):
+    if ticket_new.status == 141:  # нужны доп проверки
+        answer = jsreq.change_groups(token, config.API_URL + f"api/v1/platform/sharix-users/{ticket_new.created_by}/",
+                                     group)
+        if answer != 200:
+            print(f'Ошибка{answer}')
+    else:
+        print('Статус не ACCESS')
+
+
+def status_changer():
+    while True:
+        ticketlist = jsreq.requestGetList(token, config.API_URL + "tickets/api/ticket_list/")
+        for ticket in ticketlist:
+            bot.bot_log(botname + " " + datetime.now().strftime('%Y-%m-%d') + " " + "Тикет в очереди на обработке\n")
+            t1 = threading.Thread(target=status_changer_process, args=(ticket,))
+            t1.start()
+            t1.join()  # Ожидаем завершения обработки тикета
+        time.sleep(300)  # Обновляем ticketlist каждые 5 минут
+
+
+# Авторизация и запуск бота
+
+# пустой список
+ticketlist = []
+
+token = jsreq.requestGetToken(config.API_URL + "api/v1/auth/token/login/")
+# ticketlist=jsreq.requestGetList(token, config.API_URL+"/dbsynce/api/orders/") ###Должна быть проверка между двумя
+
+# # print (len(tasklist))
+
+bot = JabberBot(JID, PASSWORD, PORT)
+
+bot.start(status_changer)

+ 51 - 0
handlers/status_handlers.py

@@ -0,0 +1,51 @@
+import json
+import time
+# раскомментировать, когда перейдем на разные пароли
+from datetime import datetime
+
+import xmpp
+
+# test
+import jsonAndRequest as jsreq
+
+
+def proceed_status(self, recipient, ticket):
+    # тут могут быть различные проверки дополнительные, а так вообще эта функция нужна для передачи заявки на обработку следующему
+    jsonTicket = json.dumps(ticket.__dict__)
+    self.conn.send(xmpp.Message(recipient, jsonTicket))
+    self.bot_log("Message sent successfully" + " " + recipient + " " + jsonTicket)
+
+
+# обработчик входящих сообщений
+def message_handler(self, conn, mess):
+    text = mess.getBody()  # текст сообщения боту
+    user = mess.getFrom()  # отправитель сообщения
+
+    # проверка на возможность получения сообщений от данного обработчика
+    print(str(user).split("/")[0])
+    if (str(user).split("/")[0]) in listen_to:
+        print(text)
+        print(mess)
+
+        if text is not None:
+            orderObj = jsreq.jsonToOrderTicket(text)
+            print(orderObj)
+            tasklist.append(orderObj)
+            self.bot_log(str(datetime.now()) + " Поступивший заказ успешно добавлен в очередь обработки\n")
+
+
+# TODO - для обработчиков Ticket скорее надо будет функции вынести в отдельную библиотеку, они типовые же
+def pending_wait(self, period, localtask, proceed_to):
+    self.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ ожидает пользовательской реакции\n")
+    time.sleep(period)
+
+    # ВАЖНО! НАДО ВСТАВИТЬ ИЗМЕНЕНИЕ СТАТУСА ЧЕРЕЗ API
+
+    # обязательно данный обработчик должен заканчиваться передачей заказа куда-то на обработку дальше - обратно или другому, иначе оно потеряется
+    self.proceed_status(proceed_to, localtask)
+    self.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ отправлен в очередь " + proceed_to + "\n")
+
+
+def order_close(self, localtask):
+    # тут надо вызов API с удалением
+    self.bot_log(botname + " " + str(datetime.now()) + " " + "Заказ удален\n")

+ 0 - 3
img/Vector.svg

@@ -1,3 +0,0 @@
-<svg width="19" height="20" viewBox="0 0 19 20" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M13.0277 10.7093C13.9637 9.93842 14.6469 8.8813 14.9822 7.68501C15.3176 6.48872 15.2884 5.21276 14.8987 4.03464C14.5091 2.85652 13.7784 1.83483 12.8082 1.11171C11.8381 0.388591 10.6768 0 9.48584 0C8.29491 0 7.13359 0.388591 6.16345 1.11171C5.19331 1.83483 4.46259 2.85652 4.07295 4.03464C3.6833 5.21276 3.65412 6.48872 3.98946 7.68501C4.32479 8.8813 5.00796 9.93842 5.94394 10.7093C4.34013 11.382 2.94075 12.4976 1.89499 13.9374C0.849226 15.3771 0.19628 17.0869 0.00575854 18.8846C-0.00803236 19.0159 0.00300573 19.1487 0.0382423 19.2754C0.0734789 19.4022 0.132224 19.5205 0.211124 19.6235C0.370469 19.8316 0.602234 19.9648 0.855434 19.994C1.10863 20.0231 1.36253 19.9458 1.56126 19.779C1.75999 19.6122 1.88729 19.3695 1.91514 19.1045C2.12478 17.1508 3.01465 15.3465 4.41473 14.0362C5.81482 12.7259 7.62696 12.0016 9.50493 12.0016C11.3829 12.0016 13.1951 12.7259 14.5951 14.0362C15.9952 15.3465 16.8851 17.1508 17.0947 19.1045C17.1207 19.3501 17.2326 19.5769 17.4089 19.7411C17.5852 19.9054 17.8134 19.9955 18.0494 19.994H18.1544C18.4047 19.9638 18.6334 19.8314 18.7908 19.6254C18.9482 19.4195 19.0214 19.1568 18.9946 18.8946C18.8031 17.0918 18.1467 15.3776 17.0955 13.9357C16.0444 12.4937 14.6382 11.3784 13.0277 10.7093V10.7093ZM9.48584 9.99973C8.73056 9.99973 7.99224 9.76527 7.36425 9.326C6.73626 8.88672 6.2468 8.26237 5.95776 7.53189C5.66873 6.8014 5.5931 5.9976 5.74045 5.22212C5.8878 4.44665 6.2515 3.73433 6.78557 3.17524C7.31963 2.61615 8.00007 2.23541 8.74084 2.08115C9.4816 1.9269 10.2494 2.00607 10.9472 2.30865C11.645 2.61122 12.2414 3.12362 12.661 3.78103C13.0806 4.43845 13.3046 5.21137 13.3046 6.00204C13.3046 7.06229 12.9023 8.07912 12.1861 8.82883C11.47 9.57855 10.4986 9.99973 9.48584 9.99973Z" fill="#B30000"/>
-</svg>

+ 0 - 3
img/arrow.svg

@@ -1,3 +0,0 @@
-<svg width="21" height="12" viewBox="0 0 21 12" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M12.0649 11.31L20.5399 2.82C20.6805 2.68056 20.7921 2.51466 20.8683 2.33187C20.9444 2.14908 20.9836 1.95302 20.9836 1.755C20.9836 1.55699 20.9444 1.36093 20.8683 1.17814C20.7921 0.995349 20.6805 0.829448 20.5399 0.690003C20.2589 0.410627 19.8787 0.253815 19.4824 0.253815C19.0862 0.253815 18.706 0.410627 18.4249 0.690003L10.9249 8.115L3.49994 0.690003C3.2189 0.410626 2.83872 0.253814 2.44244 0.253814C2.04617 0.253814 1.66599 0.410626 1.38494 0.690003C1.24321 0.828925 1.13046 0.994592 1.05321 1.17741C0.975967 1.36022 0.935769 1.55654 0.934945 1.755C0.935769 1.95346 0.975967 2.14979 1.05321 2.3326C1.13046 2.51541 1.24321 2.68108 1.38494 2.82L9.85994 11.31C10.0004 11.4623 10.1709 11.5838 10.3606 11.6669C10.5504 11.75 10.7553 11.7929 10.9624 11.7929C11.1696 11.7929 11.3745 11.75 11.5643 11.6669C11.754 11.5838 11.9245 11.4623 12.0649 11.31V11.31Z" fill="#4A4A4A"/>
-</svg>

+ 0 - 4
img/arrows.svg

@@ -1,4 +0,0 @@
-<svg width="58" height="47" viewBox="0 0 58 47" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M55.7341 17.9594L40.2674 2.29144C37.2553 -0.763814 32.3446 -0.763814 29.3325 2.29144C27.8709 3.76815 27.0667 5.73839 27.0667 7.83007C27.0667 9.92174 27.8709 11.892 29.3325 13.3687L39.3317 23.498L29.3325 33.6274C27.8709 35.108 27.0667 37.0743 27.0667 39.166C27.0667 41.2577 27.8709 43.224 29.3325 44.7046C30.7941 46.1853 32.7352 47 34.8 47C36.8648 47 38.8058 46.1853 40.2674 44.7046L55.7341 29.0367C57.1957 27.56 57.9999 25.5897 57.9999 23.498C57.9999 21.4064 57.1957 19.4361 55.7341 17.9594ZM53.0003 26.2674L37.5337 41.9353C36.0682 43.416 33.5317 43.416 32.0662 41.9353C30.5582 40.4077 30.5582 37.9243 32.0662 36.3967L44.7992 23.498L32.0662 10.5994C31.3354 9.85907 30.9333 8.87591 30.9333 7.83007C30.9333 6.78423 31.3354 5.80107 32.0662 5.06076C32.8202 4.29694 33.8101 3.91308 34.8 3.91308C35.7898 3.91308 36.7797 4.29694 37.5337 5.05684L53.0003 20.7248C53.7311 21.469 54.1333 22.4522 54.1333 23.498C54.1333 24.5439 53.7311 25.527 53.0003 26.2674Z" fill="white"/>
-<path d="M28.6675 17.9594L13.2008 2.29144C10.1887 -0.763814 5.278 -0.763814 2.26587 2.29144C0.804267 3.76815 0 5.7384 0 7.83007C0 9.92174 0.804267 11.892 2.26587 13.3687L12.2651 23.498L2.26587 33.6274C0.804267 35.108 0 37.0743 0 39.166C0 41.2577 0.804267 43.224 2.26587 44.7046C3.72747 46.1853 5.66854 47 7.73334 47C9.79814 47 11.7392 46.1853 13.2008 44.7046L28.6675 29.0367C30.1291 27.56 30.9334 25.5897 30.9334 23.498C30.9334 21.4064 30.1291 19.4361 28.6675 17.9594ZM25.9338 26.2674L10.4671 41.9353C9.00161 43.416 6.46507 43.416 4.9996 41.9353C3.4916 40.4077 3.4916 37.9243 4.9996 36.3967L17.7325 23.498L4.9996 10.5994C4.2688 9.85907 3.86667 8.87591 3.86667 7.83007C3.86667 6.78423 4.2688 5.80107 4.9996 5.06076C5.7536 4.29694 6.74347 3.91308 7.73334 3.91308C8.72321 3.91308 9.71307 4.29694 10.4671 5.05684L25.9338 20.7248C26.6646 21.469 27.0667 22.4522 27.0667 23.498C27.0667 24.5439 26.6646 25.527 25.9338 26.2674Z" fill="white"/>
-</svg>

BIN
img/assist.png


BIN
img/drive.png


+ 0 - 6
img/iot.svg

@@ -1,6 +0,0 @@
-<svg width="55" height="54" viewBox="0 0 55 54" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M18.983 0.167969H6.45098C2.97148 0.167969 0.140625 2.93568 0.140625 6.33757V18.5901C0.140625 21.992 2.97148 24.7597 6.45098 24.7597H18.983C22.4625 24.7597 25.2934 21.992 25.2934 18.5901V6.33757C25.2934 2.93568 22.4625 0.167969 18.983 0.167969ZM21.0302 18.5901C21.0302 19.6937 20.1118 20.5916 18.983 20.5916H6.45098C5.32219 20.5916 4.4038 19.6937 4.4038 18.5901V6.33757C4.4038 5.23397 5.32219 4.33606 6.45098 4.33606H18.983C20.1118 4.33606 21.0302 5.23397 21.0302 6.33757V18.5901Z" fill="white"/>
-<path d="M48.3146 0.167969H35.9514C32.4253 0.167969 29.5566 2.97268 29.5566 6.4201V18.5076C29.5566 21.955 32.4253 24.7597 35.9514 24.7597H48.3146C51.8407 24.7597 54.7094 21.955 54.7094 18.5076V6.4201C54.7094 2.97268 51.8407 0.167969 48.3146 0.167969ZM50.4462 18.5076C50.4462 19.6567 49.49 20.5916 48.3146 20.5916H35.9514C34.776 20.5916 33.8198 19.6567 33.8198 18.5076V6.4201C33.8198 5.27096 34.776 4.33606 35.9514 4.33606H48.3146C49.49 4.33606 50.4462 5.27096 50.4462 6.4201V18.5076Z" fill="white"/>
-<path d="M18.983 28.9297H6.45098C2.97148 28.9297 0.140625 31.6974 0.140625 35.0993V47.3518C0.140625 50.7537 2.97148 53.5214 6.45098 53.5214H18.983C22.4625 53.5214 25.2934 50.7537 25.2934 47.3518V35.0993C25.2934 31.6974 22.4625 28.9297 18.983 28.9297ZM21.0302 47.3518C21.0302 48.4554 20.1118 49.3533 18.983 49.3533H6.45098C5.32219 49.3533 4.4038 48.4554 4.4038 47.3518V35.0993C4.4038 33.9957 5.32219 33.0978 6.45098 33.0978H18.983C20.1118 33.0978 21.0302 33.9957 21.0302 35.0993V47.3518Z" fill="white"/>
-<path d="M48.3146 28.9297H35.9514C32.4253 28.9297 29.5566 31.7344 29.5566 35.1818V47.2693C29.5566 50.7167 32.4253 53.5214 35.9514 53.5214H48.3146C51.8407 53.5214 54.7094 50.7167 54.7094 47.2693V35.1818C54.7094 31.7344 51.8407 28.9297 48.3146 28.9297ZM50.4462 47.2693C50.4462 48.4184 49.49 49.3533 48.3146 49.3533H35.9514C34.776 49.3533 33.8198 48.4184 33.8198 47.2693V35.1818C33.8198 34.0327 34.776 33.0978 35.9514 33.0978H48.3146C49.49 33.0978 50.4462 34.0327 50.4462 35.1818V47.2693Z" fill="white"/>
-</svg>

BIN
img/logo.png


File diff suppressed because it is too large
+ 0 - 2
img/logo_open.svg


BIN
img/mc.png


BIN
img/mir.png


BIN
img/paymo.png


File diff suppressed because it is too large
+ 0 - 1
img/people.svg


+ 0 - 3
img/plus.svg

@@ -1,3 +0,0 @@
-<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M22.5 10.5H13.5V1.5C13.5 1.10218 13.342 0.720645 13.0607 0.43934C12.7794 0.158036 12.3978 0 12 0C11.6022 0 11.2206 0.158036 10.9393 0.43934C10.658 0.720645 10.5 1.10218 10.5 1.5V10.5H1.5C1.10218 10.5 0.720645 10.658 0.43934 10.9393C0.158036 11.2206 0 11.6022 0 12C0 12.3978 0.158036 12.7794 0.43934 13.0607C0.720645 13.342 1.10218 13.5 1.5 13.5H10.5V22.5C10.5 22.8978 10.658 23.2794 10.9393 23.5607C11.2206 23.842 11.6022 24 12 24C12.3978 24 12.7794 23.842 13.0607 23.5607C13.342 23.2794 13.5 22.8978 13.5 22.5V13.5H22.5C22.8978 13.5 23.2794 13.342 23.5607 13.0607C23.842 12.7794 24 12.3978 24 12C24 11.6022 23.842 11.2206 23.5607 10.9393C23.2794 10.658 22.8978 10.5 22.5 10.5Z" fill="#4A4A4A"/>
-</svg>

File diff suppressed because it is too large
+ 0 - 1
img/settings.svg


BIN
img/sharix-logo-final-400x-1-5@2x.png


Some files were not shown because too many files changed in this diff