From a670fae9eb1b4801f0d97f9c5903b437a64ade75 Mon Sep 17 00:00:00 2001 From: Ilya Mukhortov Date: Wed, 12 Feb 2025 21:17:07 +1000 Subject: [PATCH] pass --- Dockerfile | 12 +- appa/admin.py | 12 +- appa/apps.py | 2 +- appa/call_api.py | 131 ++++++++++++++++++ appa/management/commands/send_to_api.py | 20 +++ appa/migrations/0001_initial.py | 23 ++- ...908_1121.py => 0002_auto_20250211_2157.py} | 8 +- appa/migrations/0003_auto_20241103_1105.py | 53 ------- .../0003_callrequest_call_result.py | 18 +++ appa/migrations/0004_auto_20241103_1122.py | 28 ---- appa/models.py | 16 ++- appa/mts_api.py | 58 -------- appa/settings.py | 37 +++-- appa/tasks.py | 23 +-- appa/templates/admin/base_site.html | 4 +- appa/test_views.py | 22 ++- appa/urls.py | 13 +- build-local.sh | 8 ++ local-celery.sh | 5 + local-enter.sh | 5 + local-server.sh | 26 ++++ requirements.txt | 6 +- supervisord.conf | 2 +- 23 files changed, 334 insertions(+), 198 deletions(-) create mode 100644 appa/call_api.py create mode 100644 appa/management/commands/send_to_api.py rename appa/migrations/{0002_auto_20240908_1121.py => 0002_auto_20250211_2157.py} (61%) delete mode 100644 appa/migrations/0003_auto_20241103_1105.py create mode 100644 appa/migrations/0003_callrequest_call_result.py delete mode 100644 appa/migrations/0004_auto_20241103_1122.py delete mode 100644 appa/mts_api.py create mode 100755 build-local.sh create mode 100755 local-celery.sh create mode 100755 local-enter.sh create mode 100755 local-server.sh diff --git a/Dockerfile b/Dockerfile index b1a062d..5989d2b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,18 +1,22 @@ -FROM python:3.12.2 +FROM python:3.12.2 AS python-nginx RUN apt-get update RUN apt-get install -y \ vim \ - supervisor + supervisor \ + nginx \ +&& rm -rf /var/lib/apt/lists/* -RUN pip install pip==24.0 +RUN pip install pip==25.0 WORKDIR /app ADD requirements.txt ./ RUN pip install -r ./requirements.txt +FROM python-nginx + COPY manage.py wsgi.py ./ COPY ./appa/ ./appa/ @@ -20,8 +24,6 @@ COPY ./appa/ ./appa/ RUN python manage.py collectstatic --noinput RUN chmod -R 777 /app/django_static -ADD ./client/build /client - ADD ./supervisord.conf /etc/supervisor/conf.d/supervisord.conf ADD ./entrypoint.sh /entrypoint.sh diff --git a/appa/admin.py b/appa/admin.py index 64c2898..6d189f0 100644 --- a/appa/admin.py +++ b/appa/admin.py @@ -20,7 +20,8 @@ class CallRequestAdmin(admin.ModelAdmin): 'date', 'get_status', 'get_request_status', - 'patient_name', + 'patient_last_name', + 'patient_first_name', 'patient_phone', 'is_active', ) @@ -31,7 +32,7 @@ class CallRequestAdmin(admin.ModelAdmin): ('date', DateRangeFilterBuilder()), ) search_fields = ( - 'patient_name', + 'patient_last_name', 'patient_phone', ) form = forms.modelform_factory(CallRequest, fields='__all__', widgets={ @@ -41,10 +42,9 @@ class CallRequestAdmin(admin.ModelAdmin): list_editable = ('is_active',) readonly_fields = ( 'call_id', - 'call_data', - 'request_time', - 'response_status_code', - 'response_message' + 'call_result', + 'call_text_log', + 'request_time' ) @admin.display(description='Статус приема', ordering='status') diff --git a/appa/apps.py b/appa/apps.py index 789059c..4ec40c4 100644 --- a/appa/apps.py +++ b/appa/apps.py @@ -5,7 +5,7 @@ from django.apps import AppConfig as DjangoAppConfig class AppaConfig(DjangoAppConfig): name = 'appa' - verbose_name = 'МТС' + verbose_name = 'Обзвон' def ready(self): import appa.receivers diff --git a/appa/call_api.py b/appa/call_api.py new file mode 100644 index 0000000..dd9306b --- /dev/null +++ b/appa/call_api.py @@ -0,0 +1,131 @@ + +import datetime +import json + +import requests +from django.utils import timezone +from constance import config + +from .models import CallRequest, RequestLog + + +def auth_request(): + r = requests.post( + config.ENTRYPOINT_AUTH, + data=dict( + username=config.USERNAME, + password=config.PASSWORD, + ) + ) + if r.status_code == 200: + print(r.json()) + config.ACCESS_TOKEN = r.json()['accessToken'] + config.REFRESH_TOKEN = r.json()['refreshToken'] + config.ACCESS_TOKEN_EXPIRED = datetime.datetime.now() + datetime.timedelta(minutes=5) + + +def get_token(): + if not config.ACCESS_TOKEN or config.ACCESS_TOKEN_EXPIRED <= timezone.now(): + auth_request() + + return config.ACCESS_TOKEN + + +def delete_call_request(call_request: CallRequest, logging=True): + hooks = None + if logging: + log = RequestLog( + request_url=config.ENTRYPOINT_DELETE % (call_request.call_id,), + ) + hooks = {'response': log.response_hook} + + r = requests.post( + config.ENTRYPOINT_DELETE % (call_request.call_id,), + headers={'Authorization': f'Bearer {get_token()}'}, + hooks=hooks + ) + if r.status_code == 200: + call_request.reset_request() + + +def get_record(call_request: CallRequest, logging=True): + if call_request.call_id: + hooks = None + if logging: + log = RequestLog( + request_url=config.ENTRYPOINT_RECORD % (call_request.call_id,), + ) + hooks = {'response': log.response_hook} + + r = requests.get( + config.ENTRYPOINT_RECORD % (call_request.call_id,), + headers={'Authorization': f'Bearer {get_token()}'}, + hooks=hooks + ) + if r.status_code == 200: + result = r.json() + call_request.call_text_log = result['text_log'] + call_request.call_result = result['call_result'] + + if result['confirmed']: + call_request.status = call_request.Status.APPROVED + elif result['call_result_code'] in [3]: + call_request.status = call_request.Status.CANCELED + + call_request.save() + + +def add_call_request(call_request: CallRequest, logging=True, delete=False): + if call_request.request_status == call_request.RequestStatus.SENT: + if delete: + delete_call_request(call_request) + + data = dict(records=[dict( + first_name=call_request.patient_first_name, + second_name=call_request.patient_last_name, + middle_name=call_request.patient_middle_name, + phone_number=call_request.patient_phone, + receipt_date=call_request.date.strftime('%Y-%m-%d'), + receipt_time=call_request.date.strftime('%H:%M'), + doctor_specialisation=call_request.doctor_speciality, + doctor_fullname=call_request.doctor_name, + filial=call_request.address, + ext_id=str(call_request.uid) + )]) + + hooks = None + if logging: + log = RequestLog( + request_url=config.ENTRYPOINT_ADD_RECORDS, + request_body=json.dumps(data, ensure_ascii=False, indent=4), + ) + hooks = {'response': log.response_hook} + + r = requests.post( + config.ENTRYPOINT_ADD_RECORDS, + headers={'Authorization': f'Bearer {get_token()}'}, + json=data, + hooks=hooks + ) + call_request.response_status_code = r.status_code + call_request.request_time = timezone.now() + + if r.status_code == 200: + record = r.json()['added_records'][0] + call_request.call_id = record['id'] + call_request.request_status = CallRequest.RequestStatus.SENT + + elif r.status_code == 400: + call_request.request_status = CallRequest.RequestStatus.ERROR + + call_request.save(update_fields=( + 'call_id', + 'request_status', + 'request_time', + 'response_status_code', + 'response_message', + )) + + +def call_history(date_from: datetime.date, date_to: datetime.date): + pass diff --git a/appa/management/commands/send_to_api.py b/appa/management/commands/send_to_api.py new file mode 100644 index 0000000..f3a5a5a --- /dev/null +++ b/appa/management/commands/send_to_api.py @@ -0,0 +1,20 @@ +import datetime +import os + +from constance import config +from django.core.management.base import BaseCommand +from appa.call_api import add_call_request, delete_call_request, get_record +from appa.models import CallRequest + + + +class Command(BaseCommand): + + def handle(self, *args, **options): + config.ACCESS_TOKEN_EXPIRED = datetime.datetime.now() - datetime.timedelta(days=1) + call_requests = CallRequest.objects.filter(id__in=[2]) + for call_request in call_requests: + #add_call_request(call_request) + get_record(call_request) + + #delete_call_request(call_request) diff --git a/appa/migrations/0001_initial.py b/appa/migrations/0001_initial.py index 044fa6f..a51a28b 100644 --- a/appa/migrations/0001_initial.py +++ b/appa/migrations/0001_initial.py @@ -1,6 +1,7 @@ -# Generated by Django 3.2 on 2024-09-05 19:30 +# Generated by Django 3.2 on 2025-02-09 10:07 from django.db import migrations, models +import uuid class Migration(migrations.Migration): @@ -32,12 +33,26 @@ class Migration(migrations.Migration): name='CallRequest', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('status', models.CharField(choices=[('PENDING', 'Обзвон еще не состоялся'), ('APPROVED', 'Прием подтвержден'), ('CANCELED', 'Прием отменен'), ('WITHOUT_ANSWER', 'Не дозвонились')], default='PENDING', max_length=20, verbose_name='Статус приема')), + ('request_status', models.CharField(choices=[('PENDING', 'Не отправлен'), ('APPROVED', 'Отправлен'), ('ERROR', 'Ошибка'), ('SERVICE_UNAVAILABLE', 'Сервис недоступен')], default='PENDING', max_length=20, verbose_name='Статус запроса')), ('date', models.DateField(verbose_name='Дата')), ('patient_id', models.IntegerField(verbose_name='ID пациента')), - ('patient_name', models.CharField(max_length=200, verbose_name='ФИО пациента')), + ('patient_first_name', models.CharField(max_length=200, verbose_name='Имя')), + ('patient_last_name', models.CharField(max_length=200, verbose_name='Фамилия')), + ('patient_middle_name', models.CharField(blank=True, max_length=200, null=True, verbose_name='Отчество')), ('patient_phone', models.CharField(max_length=100, verbose_name='Номер телефона')), - ('status', models.CharField(choices=[('PENDING', 'Обзвон еще не состоялся'), ('APPROVED', 'Прием подтвержден'), ('CANCELED', 'Прием отменен'), ('WITHOUT_ANSWER', 'Не дозвонились'), ('SERVICE_UNAVAILABLE', 'Сервис недоступен')], default='PENDING', max_length=20, verbose_name='Статус')), - ('data', models.JSONField(default=dict, verbose_name='Данные')), + ('doctor_name', models.CharField(max_length=100, null=True, verbose_name='Врач')), + ('doctor_speciality', models.CharField(max_length=100, null=True, verbose_name='Специальность врача')), + ('service_name', models.CharField(blank=True, max_length=100, null=True, verbose_name='Услуга')), + ('address', models.CharField(blank=True, max_length=100, null=True, verbose_name='Адрес')), + ('data', models.JSONField(blank=True, default=list, verbose_name='Данные')), + ('is_active', models.BooleanField(default=True, verbose_name='Активность')), + ('call_id', models.CharField(editable=False, max_length=100, null=True, verbose_name='ID')), + ('call_data', models.JSONField(blank=True, default=dict, editable=False)), + ('request_time', models.DateTimeField(editable=False, null=True)), + ('response_status_code', models.IntegerField(editable=False, null=True)), + ('response_message', models.TextField(editable=False, null=True)), ], options={ 'verbose_name': 'Запрос на звонок', diff --git a/appa/migrations/0002_auto_20240908_1121.py b/appa/migrations/0002_auto_20250211_2157.py similarity index 61% rename from appa/migrations/0002_auto_20240908_1121.py rename to appa/migrations/0002_auto_20250211_2157.py index ac06dd5..a352719 100644 --- a/appa/migrations/0002_auto_20240908_1121.py +++ b/appa/migrations/0002_auto_20250211_2157.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2 on 2024-09-08 11:21 +# Generated by Django 3.2 on 2025-02-11 21:57 from django.db import migrations, models @@ -12,12 +12,12 @@ class Migration(migrations.Migration): operations = [ migrations.AddField( model_name='callrequest', - name='is_active', - field=models.BooleanField(default=True, verbose_name='Активность'), + name='call_text_log', + field=models.TextField(blank=True, editable=False, null=True, verbose_name='Лог'), ), migrations.AlterField( model_name='callrequest', name='data', - field=models.JSONField(blank=True, default=list, verbose_name='Данные'), + field=models.JSONField(blank=True, default=dict, verbose_name='Данные'), ), ] diff --git a/appa/migrations/0003_auto_20241103_1105.py b/appa/migrations/0003_auto_20241103_1105.py deleted file mode 100644 index fb55389..0000000 --- a/appa/migrations/0003_auto_20241103_1105.py +++ /dev/null @@ -1,53 +0,0 @@ -# Generated by Django 3.2 on 2024-11-03 11:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('appa', '0002_auto_20240908_1121'), - ] - - operations = [ - migrations.AddField( - model_name='callrequest', - name='address', - field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Адрес'), - ), - migrations.AddField( - model_name='callrequest', - name='call_data', - field=models.JSONField(blank=True, default=dict, editable=False), - ), - migrations.AddField( - model_name='callrequest', - name='call_id', - field=models.CharField(editable=False, max_length=100, null=True, verbose_name='ID вызова'), - ), - migrations.AddField( - model_name='callrequest', - name='doctor_name', - field=models.CharField(max_length=100, null=True, verbose_name='Врач'), - ), - migrations.AddField( - model_name='callrequest', - name='request_time', - field=models.DateTimeField(editable=False, null=True), - ), - migrations.AddField( - model_name='callrequest', - name='response_message', - field=models.TextField(editable=False, null=True), - ), - migrations.AddField( - model_name='callrequest', - name='response_status_code', - field=models.IntegerField(editable=False, null=True), - ), - migrations.AddField( - model_name='callrequest', - name='service_name', - field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Услуга'), - ), - ] diff --git a/appa/migrations/0003_callrequest_call_result.py b/appa/migrations/0003_callrequest_call_result.py new file mode 100644 index 0000000..454a12d --- /dev/null +++ b/appa/migrations/0003_callrequest_call_result.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2 on 2025-02-11 21:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('appa', '0002_auto_20250211_2157'), + ] + + operations = [ + migrations.AddField( + model_name='callrequest', + name='call_result', + field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Результат'), + ), + ] diff --git a/appa/migrations/0004_auto_20241103_1122.py b/appa/migrations/0004_auto_20241103_1122.py deleted file mode 100644 index ff633fa..0000000 --- a/appa/migrations/0004_auto_20241103_1122.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 3.2 on 2024-11-03 11:22 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('appa', '0003_auto_20241103_1105'), - ] - - operations = [ - migrations.AddField( - model_name='callrequest', - name='request_status', - field=models.CharField(choices=[('PENDING', 'Запрос не отправлен'), ('APPROVED', 'Запрос отправлен'), ('ERROR', 'Ошибка'), ('SERVICE_UNAVAILABLE', 'Сервис недоступен')], default='PENDING', max_length=20, verbose_name='Статус запроса'), - ), - migrations.AlterField( - model_name='callrequest', - name='call_id', - field=models.CharField(editable=False, max_length=100, null=True, verbose_name='ID'), - ), - migrations.AlterField( - model_name='callrequest', - name='status', - field=models.CharField(choices=[('PENDING', 'Обзвон еще не состоялся'), ('APPROVED', 'Прием подтвержден'), ('CANCELED', 'Прием отменен'), ('WITHOUT_ANSWER', 'Не дозвонились')], default='PENDING', max_length=20, verbose_name='Статус приема'), - ), - ] diff --git a/appa/models.py b/appa/models.py index 0d1014d..d73fb27 100644 --- a/appa/models.py +++ b/appa/models.py @@ -1,5 +1,5 @@ -import json +import uuid from django.db import models from .managers import CallRequestManager @@ -38,22 +38,28 @@ class CallRequest(models.Model): RequestStatus.SERVICE_UNAVAILABLE: '#7961DB', } + uid = models.UUIDField(unique=True, default=uuid.uuid4, editable=False) status = models.CharField(max_length=20, choices=Status.choices, default=Status.PENDING, verbose_name='Статус приема') request_status = models.CharField(max_length=20, choices=RequestStatus.choices, default=RequestStatus.NOT_SENT, verbose_name='Статус запроса') date = models.DateField(verbose_name='Дата') patient_id = models.IntegerField(verbose_name='ID пациента') - patient_name = models.CharField(max_length=200, verbose_name='ФИО пациента') + patient_first_name = models.CharField(max_length=200, verbose_name='Имя') + patient_last_name = models.CharField(max_length=200, verbose_name='Фамилия') + patient_middle_name = models.CharField(max_length=200, null=True, blank=True, verbose_name='Отчество') patient_phone = models.CharField(max_length=100, verbose_name='Номер телефона') doctor_name = models.CharField(max_length=100, null=True, verbose_name='Врач') + doctor_speciality = models.CharField(max_length=100, null=True, verbose_name='Специальность врача') service_name = models.CharField(max_length=100, null=True, blank=True, verbose_name='Услуга') address = models.CharField(max_length=100, null=True, blank=True, verbose_name='Адрес') - data = models.JSONField(default=list, blank=True, verbose_name='Данные') + data = models.JSONField(default=dict, blank=True, verbose_name='Данные') is_active = models.BooleanField(default=True, verbose_name='Активность') call_id = models.CharField(max_length=100, null=True, editable=False, verbose_name='ID') call_data = models.JSONField(default=dict, blank=True, editable=False) + call_text_log = models.TextField(null=True, blank=True, editable=False, verbose_name='Лог') + call_result = models.CharField(max_length=100, null=True, editable=False, blank=True, verbose_name='Результат') request_time = models.DateTimeField(null=True, editable=False) response_status_code = models.IntegerField(null=True, editable=False) response_message = models.TextField(null=True, editable=False) @@ -68,7 +74,7 @@ class CallRequest(models.Model): objects = CallRequestManager() def __str__(self): - return f"{self.date.strftime('%d.%m.%Y')} / {self.patient_name}" + return f"{self.date.strftime('%d.%m.%Y')} / {self.patient_last_name}" def get_status_color(self): return self.STATUS_COLOR.get(self.status) @@ -77,6 +83,8 @@ class CallRequest(models.Model): return self.REQUEST_STATUS_COLOR.get(self.request_status) def reset_request(self): + self.call_id = None + self.call_data = dict() self.request_status = CallRequest.RequestStatus.NOT_SENT self.request_time = None self.response_status_code = None diff --git a/appa/mts_api.py b/appa/mts_api.py deleted file mode 100644 index f43f684..0000000 --- a/appa/mts_api.py +++ /dev/null @@ -1,58 +0,0 @@ - -import datetime -import json - -import requests -from django.utils import timezone -from constance import config - -from .models import CallRequest, RequestLog - - -def add_call_request(call_request: CallRequest, logging=True): - call_request.reset_request() - - data = dict( - number_b=call_request.patient_phone, - name=call_request.patient_name, - date=call_request.date.strftime('%Y-%m-%d'), - time=call_request.date.strftime('%H:%M'), - doctor=call_request.doctor_name, - address=call_request.address, - ) - - hooks = None - if logging: - log = RequestLog( - request_url=config.HOST, - request_body=json.dumps(data, ensure_ascii=False, indent=4), - ) - hooks = {'response': log.response_hook} - - r = requests.post( - config.HOST, - auth=(config.USERNAME, config.PASSWORD), - json=data, - hooks=hooks - ) - call_request.response_status_code = r.status_code - call_request.request_time = timezone.now() - if r.status_code == 200: - call_request.call_id = r.json()['request_id'] - call_request.request_status = CallRequest.RequestStatus.SENT - elif r.status_code == 400: - call_request.call_id = r.json()['request_id'] - call_request.response_message = r.json()['error'] - call_request.request_status = CallRequest.RequestStatus.ERROR - - call_request.save(update_fields=( - 'call_id', - 'request_status', - 'request_time', - 'response_status_code', - 'response_message', - )) - - -def call_history(date_from: datetime.date, date_to: datetime.date): - pass diff --git a/appa/settings.py b/appa/settings.py index b04a5e2..3ba5521 100644 --- a/appa/settings.py +++ b/appa/settings.py @@ -15,16 +15,13 @@ SECRET_KEY = 'django-insecure-13n6^zl86r@=9@!z8gsfv(q6wpggo+$box)^tklnoe9auck-)c root = environ.Path(__file__) - 2 env = environ.Env( - DEBUG=(bool, False), LANGUAGE_CODE=(str, 'ru-RU'), TIME_ZONE=(str, 'Asia/Vladivostok'), USE_TZ=(bool, False), USE_I18N=(bool, True), - CORS_ORIGIN_WHITELIST=(list, []), - AUTH_CONVERT_PASSWORD_TO_LOWER_CASE=(bool, False) ) -DEBUG = env('DEBUG', False) +DEBUG = env.bool('DEBUG', False) REDIS_HOST = env.str('REDIS_HOST', 'medicine-stack-redis') REDIS_PORT = env.str('REDIS_PORT', '6379') @@ -32,7 +29,7 @@ REDIS_DB = env.str('REDIS_DB', 1) POSTGRES_HOST = env.str('POSTGRES_HOST', 'medicine-stack-postgres') POSTGRES_PORT = env.str('POSTGRES_PORT', '5432') -POSTGRES_DB = env.str('POSTGRES_DB', 'medicine_mts') +POSTGRES_DB = env.str('POSTGRES_DB', 'medicine_call') POSTGRES_USER = env.str('POSTGRES_USER', 'postgres') POSTGRES_PASSWORD = env.str('POSTGRES_PASSWORD', 'password') @@ -126,13 +123,13 @@ USE_I18N = env.bool('USE_I18N') USE_TZ = env.bool('USE_TZ') -STATIC_URL = '/medicine-mts/django_static/' +STATIC_URL = '/medicine-call/django_static/' STATIC_ROOT = os.path.join(BASE_DIR, 'django_static') DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' -SESSION_COOKIE_NAME = env.str('SESSION_COOKIE_NAME', 'medicine-mts') +SESSION_COOKIE_NAME = env.str('SESSION_COOKIE_NAME', 'medicine-call') CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend' @@ -150,21 +147,41 @@ CONSTANCE_ADDITIONAL_FIELDS = { } CONSTANCE_CONFIG = { + 'HOST': ('https://amniss-ai.ru/api/v.2/', 'Хост', 'char'), + 'ENTRYPOINT_ADD_RECORDS': ('https://amniss-ai.ru/api/v.2/records/{scenarioId}', 'Адрес для добавления записей', 'char'), + 'ENTRYPOINT_AUTH': ('https://amniss-ai.ru/api/auth', 'Адрес для авторизации', 'char'), + 'ENTRYPOINT_DELETE': ('https://amniss-ai.ru/api/v.1/records/delete/%s', 'Адрес для удаления', 'char'), + 'ENTRYPOINT_RECORD': ('https://amniss-ai.ru/api/v.1/records/%s', 'Адрес записи', 'char'), + 'SCENARIO_ID': ('', 'ID сценария', 'char'), 'USERNAME': ('', 'Имя пользователя', 'char'), 'PASSWORD': ('', 'Пароль', 'char'), - 'HOST': ('', 'Хост', 'char'), 'IS_ENABLED': (False, 'Активен', bool), + 'ACCESS_TOKEN': ('', 'Access token', 'char'), + 'REFRESH_TOKEN': ('', 'Refresh token', 'char'), + 'ACCESS_TOKEN_EXPIRED': ( + datetime.datetime(2025, 1, 1, 0, 0), + 'Access token expired', + datetime.datetime + ), 'MEDICINE_TOKEN': ('', 'Токен', 'char'), 'MEDICINE_HOST': ('http://medicine-app/', 'Хост', 'char'), } CONSTANCE_CONFIG_FIELDSETS = ( - ('МТС', ( + ('API', ( 'HOST', + 'ENTRYPOINT_AUTH', + 'ENTRYPOINT_ADD_RECORDS', + 'ENTRYPOINT_DELETE', + 'ENTRYPOINT_RECORD', + 'SCENARIO_ID', 'USERNAME', 'PASSWORD', 'IS_ENABLED', + 'ACCESS_TOKEN', + 'ACCESS_TOKEN_EXPIRED', + 'REFRESH_TOKEN' )), ('МИС', ( 'MEDICINE_HOST', @@ -191,4 +208,4 @@ CALL_REQUEST_TIME_END = datetime.time(21, 0) if DEBUG: AUTH_PASSWORD_VALIDATORS = [] - SESSION_COOKIE_NAME = 'dev-medicine-mts' + SESSION_COOKIE_NAME = 'dev-medicine-call' diff --git a/appa/tasks.py b/appa/tasks.py index e7c6e5f..f7eaeaa 100644 --- a/appa/tasks.py +++ b/appa/tasks.py @@ -5,23 +5,24 @@ from constance import config from appa.celery import app from appa.models import * -from appa.mts_api import add_call_request +from appa.call_api import add_call_request @app.task(bind=True, acks_late=True) def send_call_request_task(self, ids=None): - tomorrow = datetime.date.today() + datetime.timedelta(days=1) - - call_requests = CallRequest.objects.filter( - date=tomorrow, - status__in=[ - CallRequest.Status.PENDING, - CallRequest.Status.WITHOUT_ANSWER - ], - is_active=True - ) + call_requests = CallRequest.objects.filter(is_active=True) if ids and len(ids) > 0: call_requests = call_requests.filter(id__in=ids) + else: + tomorrow = datetime.date.today() + datetime.timedelta(days=1) + + call_requests = CallRequest.objects.filter( + date=tomorrow, + status__in=[ + CallRequest.Status.PENDING, + CallRequest.Status.WITHOUT_ANSWER + ] + ) for call_request in call_requests: add_call_request(call_request) diff --git a/appa/templates/admin/base_site.html b/appa/templates/admin/base_site.html index fa0c41e..3f790b1 100644 --- a/appa/templates/admin/base_site.html +++ b/appa/templates/admin/base_site.html @@ -1,10 +1,10 @@ {% extends "admin/base_site.html" %} {% load static %} -{% block title %}{{ title }} | МТС{% endblock %} +{% block title %}{{ title }} | CALL{% endblock %} {% block branding %}

- МТС + CALL

{% endblock %} diff --git a/appa/test_views.py b/appa/test_views.py index 8fe7a11..3ab129a 100644 --- a/appa/test_views.py +++ b/appa/test_views.py @@ -1,14 +1,30 @@ +import json +import random + +from django.utils.crypto import get_random_string from django.views.decorators.csrf import csrf_exempt from django.http import JsonResponse from django.utils.crypto import get_random_string +@csrf_exempt +def auth_view(request): + return JsonResponse({ + 'accessToken': get_random_string(32), + 'refreshToken': get_random_string(32), + }) + @csrf_exempt -def add_success_view(request): +def add_records_view(request): + data = json.loads(request.body) + results = [] + for record in data['records']: + record['id'] = random.randint(1, 10000) + results.append(record) + return JsonResponse({ - 'request_id': get_random_string(10), - 'success': '1' + 'added_records': results }) diff --git a/appa/urls.py b/appa/urls.py index dd11b03..c252f71 100644 --- a/appa/urls.py +++ b/appa/urls.py @@ -10,17 +10,18 @@ from appa import test_views admin.site.unregister(Group) urlpatterns = [ - path('medicine-mts/admin/', admin.site.urls), - path('medicine-mts/api/', api.urls), - path('medicine-mts/', lambda request: redirect('/medicine-mts/admin/')), - path('admin/', lambda request: redirect('/medicine-mts/admin/')), - path('', lambda request: redirect('/medicine-mts/admin/')), + path('medicine-call/admin/', admin.site.urls), + path('medicine-call/api/', api.urls), + path('medicine-call/', lambda request: redirect('/medicine-call/admin/')), + path('admin/', lambda request: redirect('/medicine-call/admin/')), + path('', lambda request: redirect('/medicine-call/admin/')), ] if settings.DEBUG: from django.contrib.staticfiles.urls import staticfiles_urlpatterns, static urlpatterns +=[ - path('medicine-mts/tests/add_success_view/', test_views.add_success_view), + path('medicine-mts/tests/auth/', test_views.auth_view), + path('medicine-mts/tests/add_records/', test_views.add_records_view), path('medicine-mts/tests/add_error_view/', test_views.add_error_view), path('medicine-mts/tests/add_500_error_view/', test_views.add_500_error_view), path('medicine-mts/tests/history_view/', test_views.history_view), diff --git a/build-local.sh b/build-local.sh new file mode 100755 index 0000000..c69eae1 --- /dev/null +++ b/build-local.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -e + +docker build \ + --target python-nginx \ + --file ./Dockerfile \ + --tag medicine-call-local:latest . diff --git a/local-celery.sh b/local-celery.sh new file mode 100755 index 0000000..722b51e --- /dev/null +++ b/local-celery.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +set -e + +docker exec medicine-call-local-server celery -A appa worker -B --loglevel=INFO --concurrency=1 diff --git a/local-enter.sh b/local-enter.sh new file mode 100755 index 0000000..17b0ed2 --- /dev/null +++ b/local-enter.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +set -e + +docker exec -it medicine-call-local-server bash diff --git a/local-server.sh b/local-server.sh new file mode 100755 index 0000000..579777c --- /dev/null +++ b/local-server.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +docker stop medicine-call-local-server +docker rm medicine-call-local-server + +open -n -a "Google Chrome" --args "http://0.0.0.0:9400/admin/" + +docker run --rm \ + --name medicine-call-local-server \ + --network=local-network \ + --volume .:/app \ + --volume medicine-call-local:/app/public \ + --publish 9400:80 \ + --env-file .env \ + medicine-call-local:latest \ + uwsgi \ + --http 0.0.0.0:80 \ + --wsgi-file wsgi.py \ + --workers 2 \ + --threads 2 \ + --master \ + --py-autoreload 1 \ + --disable-write-exception \ + --buffer-size 32768 \ + --http-timeout 30 \ + --check-static /app/ diff --git a/requirements.txt b/requirements.txt index 215c6a7..75beffc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,6 +11,7 @@ click-didyoumean==0.3.1 click-plugins==1.1.1 click-repl==0.3.0 Django==3.2 +django-admin-rangefilter==0.13.2 django-constance==3.1.0 django-environ==0.11.2 django-ninja==1.2.0 @@ -31,6 +32,7 @@ sqlparse==0.5.1 typing_extensions==4.12.2 tzdata==2024.1 urllib3==2.2.2 -uWSGI==2.0.26 +uWSGI==2.0.28 vine==5.1.0 -wcwidth==0.2.13 \ No newline at end of file +wcwidth==0.2.13 +wheel==0.43.0 \ No newline at end of file diff --git a/supervisord.conf b/supervisord.conf index ed310aa..7e54f8a 100644 --- a/supervisord.conf +++ b/supervisord.conf @@ -17,7 +17,7 @@ command=uwsgi --vacuum --need-app --disable-write-exception - --static-map /medicine-mts/django_static=/app/django_static + --static-map /medicine-call/django_static=/app/django_static autostart=true autorestart=true stderr_logfile=/dev/stderr