From 7a7f4f82cbb4cece3e97960c61454c41420abe22 Mon Sep 17 00:00:00 2001 From: Ilya Mukhortov Date: Sun, 9 Mar 2025 10:28:30 +1000 Subject: [PATCH] pass --- Dockerfile | 2 +- appa/admin.py | 22 ++++------------- appa/call_api/api.py | 32 ++++++++++++------------- appa/medicine_api/api.py | 7 +++--- appa/models.py | 12 ++++++---- appa/settings.py | 51 ++++++++++++++++------------------------ appa/tasks.py | 20 +++++++++++++--- requirements.txt | 1 + 8 files changed, 68 insertions(+), 79 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5989d2b..b4fb33c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ RUN apt-get install -y \ nginx \ && rm -rf /var/lib/apt/lists/* -RUN pip install pip==25.0 +RUN pip install pip==25.0.1 WORKDIR /app diff --git a/appa/admin.py b/appa/admin.py index 49103f6..6966b41 100644 --- a/appa/admin.py +++ b/appa/admin.py @@ -1,17 +1,11 @@ -from django.contrib.auth.models import User from django import forms from django.contrib import admin -from django.core.checks import messages -from django.utils import timezone from django.utils.safestring import mark_safe -from django.conf import settings -from constance import config from ace_editor import AceJSONWidget from rangefilter.filters import DateRangeFilterBuilder from .models import * -from .admin_forms import * from .admin_filters import * from .tasks import send_call_request_task, update_call_requests_task @@ -101,19 +95,11 @@ class CallRequestAdmin(admin.ModelAdmin): @admin.action(description='Отправить выбранные записи на обзвон') def send_call_request(self, request, queryset): - if config.CALL_TIME_START <= timezone.now().time() <= config.CALL_TIME_END: - ids = [item.id for item in queryset.filter(request_status=CallRequest.RequestStatus.NOT_SENT)] - if len(ids) > 0: - send_call_request_task.apply_async(args=(ids,)) + ids = [item.id for item in queryset.filter(request_status=CallRequest.RequestStatus.NOT_SENT)] + if len(ids) > 0: + send_call_request_task.apply_async(args=(ids,)) - self.message_user(request, message=f'Записей отправлено на обзвон: {len(ids)}') - else: - self.message_user( - request, - message=f'Время для обзвона регламентируется с ' - f'{settings.CALL_REQUEST_TIME_START} по {settings.CALL_REQUEST_TIME_END}', - level=messages.ERROR - ) + self.message_user(request, message=f'Записей отправлено на обзвон: {len(ids)}') @admin.action(description='Удалить выбранные записи из обзвона') def delete_call_request(self, request, queryset): diff --git a/appa/call_api/api.py b/appa/call_api/api.py index 90da761..4c00616 100644 --- a/appa/call_api/api.py +++ b/appa/call_api/api.py @@ -4,31 +4,26 @@ import json import requests from django.utils import timezone +from django.core.cache import cache from constance import config from appa.models import CallRequest, RequestLog from . import call_status -def auth_request(): - r = requests.post( - config.ENTRYPOINT_AUTH, - data=dict( - username=config.USERNAME, - password=config.PASSWORD, - ) - ) - if r.status_code == 200: - 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() + token = cache.get('ACCESS_TOKEN') + if token is None: + r = requests.post( + config.ENTRYPOINT_AUTH, + data=dict(username=config.USERNAME, password=config.PASSWORD) + ) + if r.status_code == 200: + token = r.json()['accessToken'] + cache.set('ACCESS_TOKEN', token, timeout=300) + cache.set('REFRESH_TOKEN', r.json()['refreshToken'], timeout=300) - return config.ACCESS_TOKEN + return token def delete_call_request(call_request: CallRequest, logging=True): @@ -73,6 +68,9 @@ def get_record(call_request: CallRequest, logging=True): if result['confirmed']: call_request.status = call_request.Status.APPROVED + elif result['call_result_code'] == call_status.STATUS_4: + call_request.status = call_request.Status.TRANSFER + elif result['call_result_code'] == call_status.STATUS_5: call_request.status = call_request.Status.CALLBACK diff --git a/appa/medicine_api/api.py b/appa/medicine_api/api.py index b69d7ed..d00d4aa 100644 --- a/appa/medicine_api/api.py +++ b/appa/medicine_api/api.py @@ -1,4 +1,3 @@ -import datetime import requests from constance import config @@ -43,10 +42,10 @@ def get_bookings(date): def cancel_booking(booking_id): - r = requests.post( - f'{config.MEDICINE_HOST}api/1/booking/{booking_id}/failed/', + requests.delete( + f'{config.MEDICINE_HOST}api/1/booking/{booking_id}/', data={ - 'failed_reason': 'CANCELED' + 'comment': 'Пациент отменил запись по телефону' }, headers={ 'Authorization': f'Token {config.MEDICINE_TOKEN}' diff --git a/appa/models.py b/appa/models.py index 7551c0c..c14e954 100644 --- a/appa/models.py +++ b/appa/models.py @@ -63,6 +63,7 @@ class CallRequest(models.Model): CANCELED = 'CANCELED', 'Прием отменен' CALLBACK = 'CALLBACK', 'Перезвонить' WITHOUT_ANSWER = 'WITHOUT_ANSWER', 'Не дозвонились' + TRANSFER = 'TRANSFER', 'Просьба перенести запись' OTHER = 'OTHER', 'Другая ошибка' STATUS_COLOR = { @@ -71,6 +72,7 @@ class CallRequest(models.Model): Status.CANCELED: '#CD4246', Status.CALLBACK: '#935610', Status.WITHOUT_ANSWER: '#866103', + Status.TRANSFER: '#B83211', Status.OTHER: '#5A701A' } @@ -151,11 +153,6 @@ class CallRequest(models.Model): class RequestLog(models.Model): - class Meta: - verbose_name = 'Запрос' - verbose_name_plural = 'История запросов' - ordering = ('-created',) - request_url = models.CharField(max_length=500, verbose_name='Адрес запроса') request_body = models.TextField(null=True, blank=True, verbose_name='Запрос') request_method = models.CharField(max_length=100, null=True, verbose_name='Тип запроса') @@ -165,6 +162,11 @@ class RequestLog(models.Model): created = models.DateTimeField(auto_now_add=True, editable=False, db_index=True, verbose_name='Дата запроса') + class Meta: + verbose_name = 'Запрос' + verbose_name_plural = 'История запросов' + ordering = ('-created',) + def __str__(self): return self.request_url diff --git a/appa/settings.py b/appa/settings.py index 09a0d01..c1606c8 100644 --- a/appa/settings.py +++ b/appa/settings.py @@ -152,27 +152,9 @@ CONSTANCE_CONFIG = { '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'), '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 - ), - 'CALL_TIME_START': ( - datetime.time(9, 30), - 'Время старта обзвона', - datetime.time - ), - 'CALL_TIME_END': ( - datetime.time(18, 30), - 'Время окончания обзвона', - datetime.time - ), 'MEDICINE_TOKEN': ('', 'Токен', 'char'), 'MEDICINE_HOST': ('http://medicine-app/', 'Хост', 'char'), @@ -181,18 +163,12 @@ CONSTANCE_CONFIG = { CONSTANCE_CONFIG_FIELDSETS = ( ('API', ( 'IS_ENABLED', - 'CALL_TIME_START', - 'CALL_TIME_END', - 'SCENARIO_ID', 'USERNAME', 'PASSWORD', 'ENTRYPOINT_AUTH', 'ENTRYPOINT_ADD_RECORDS', 'ENTRYPOINT_DELETE', 'ENTRYPOINT_RECORD', - 'ACCESS_TOKEN', - 'REFRESH_TOKEN', - 'ACCESS_TOKEN_EXPIRED', )), ('МИС', ( 'MEDICINE_HOST', @@ -216,12 +192,17 @@ CELERYBEAT_SCHEDULE = { }, 'check_call_requests_task': { 'task': 'appa.tasks.check_call_requests_task', - 'schedule': crontab(minute='*/5'), + 'schedule': crontab(minute='*/1'), 'options': {'queue': CELERY_DEFAULT_QUEUE} }, - 'send_daily_call_request_task': { - 'task': 'appa.tasks.send_daily_call_request_task', - 'schedule': crontab(hour='10', minute='0'), + #'send_daily_call_request_task': { + # 'task': 'appa.tasks.send_daily_call_request_task', + # 'schedule': crontab(hour='10', minute='0'), + # 'options': {'queue': CELERY_DEFAULT_QUEUE} + #}, + 'cleanup_task': { + 'task': 'appa.tasks.cleanup_task', + 'schedule': crontab(hour='0', minute='0'), 'options': {'queue': CELERY_DEFAULT_QUEUE} }, } @@ -229,13 +210,21 @@ CELERYBEAT_SCHEDULE = { DATE_FORMAT = 'd.m.Y' DATETIME_FORMAT = 'd.m.Y H:i' -CALL_REQUEST_TIME_START = datetime.time(9, 0) -CALL_REQUEST_TIME_END = datetime.time(21, 0) - DATABASE_ROUTERS = [ 'appa.medicine.router.MedicineRouter', ] +REDIS_CACHE_DB = env.str('REDIS_CELERY_DB', '8') +CACHES = { + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_CACHE_DB}", + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + } + } +} + if DEBUG: AUTH_PASSWORD_VALIDATORS = [] SESSION_COOKIE_NAME = 'dev-medicine-call' diff --git a/appa/tasks.py b/appa/tasks.py index 6c0d9b2..8055fcb 100644 --- a/appa/tasks.py +++ b/appa/tasks.py @@ -1,7 +1,8 @@ import pytz import datetime -from constance import config +from django.contrib.sessions.models import Session +from django.utils import timezone from appa.celery import app from appa.models import * from appa.call_api import api as call_api @@ -21,7 +22,10 @@ def send_call_request_task(self, ids=None): ) for call_request in call_requests: - call_api.add_call_request(call_request) + try: + call_api.add_call_request(call_request) + except Exception as e: + print(e) @app.task(bind=True, acks_late=True) @@ -60,6 +64,9 @@ def update_call_requests_task(self): if lpu is None or speciality is None: continue + if not booking['patient']['phone_mobile']: + continue + CallRequest.objects.update_or_create( defaults=dict( date=datetime.datetime.strptime(booking['date_start'].split('T')[0], '%Y-%m-%d').date(), @@ -83,6 +90,13 @@ def update_call_requests_task(self): def check_call_requests_task(self): for call_request in CallRequest.objects.filter( request_status=CallRequest.RequestStatus.SENT, - date=datetime.date.today() + date__in=[datetime.date.today(), datetime.date.today() + datetime.timedelta(days=1)] ): call_api.get_record(call_request) + + +@app.task(bind=True, acks_late=True) +def cleanup_task(self): + tomorrow = timezone.now() + datetime.timedelta(days=1) + RequestLog.objects.filter(created__lte=datetime.datetime.now() - datetime.timedelta(days=3)).delete() + Session.objects.filter(expire_date__lte=tomorrow).delete() diff --git a/requirements.txt b/requirements.txt index 75beffc..d681a90 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,6 +16,7 @@ django-constance==3.1.0 django-environ==0.11.2 django-ninja==1.2.0 django-picklefield==3.2 +django-redis==5.4.0 idna==3.8 kombu==5.4.0 prompt_toolkit==3.0.47