pass
This commit is contained in:
parent
f8517d0677
commit
7a7f4f82cb
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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}'
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue