pass
This commit is contained in:
parent
0e3fd06c53
commit
a670fae9eb
12
Dockerfile
12
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 update
|
||||||
RUN apt-get install -y \
|
RUN apt-get install -y \
|
||||||
vim \
|
vim \
|
||||||
supervisor
|
supervisor \
|
||||||
|
nginx \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
RUN pip install pip==24.0
|
RUN pip install pip==25.0
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
ADD requirements.txt ./
|
ADD requirements.txt ./
|
||||||
RUN pip install -r ./requirements.txt
|
RUN pip install -r ./requirements.txt
|
||||||
|
|
||||||
|
FROM python-nginx
|
||||||
|
|
||||||
COPY manage.py wsgi.py ./
|
COPY manage.py wsgi.py ./
|
||||||
|
|
||||||
COPY ./appa/ ./appa/
|
COPY ./appa/ ./appa/
|
||||||
|
|
@ -20,8 +24,6 @@ COPY ./appa/ ./appa/
|
||||||
RUN python manage.py collectstatic --noinput
|
RUN python manage.py collectstatic --noinput
|
||||||
RUN chmod -R 777 /app/django_static
|
RUN chmod -R 777 /app/django_static
|
||||||
|
|
||||||
ADD ./client/build /client
|
|
||||||
|
|
||||||
ADD ./supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
ADD ./supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||||
|
|
||||||
ADD ./entrypoint.sh /entrypoint.sh
|
ADD ./entrypoint.sh /entrypoint.sh
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,8 @@ class CallRequestAdmin(admin.ModelAdmin):
|
||||||
'date',
|
'date',
|
||||||
'get_status',
|
'get_status',
|
||||||
'get_request_status',
|
'get_request_status',
|
||||||
'patient_name',
|
'patient_last_name',
|
||||||
|
'patient_first_name',
|
||||||
'patient_phone',
|
'patient_phone',
|
||||||
'is_active',
|
'is_active',
|
||||||
)
|
)
|
||||||
|
|
@ -31,7 +32,7 @@ class CallRequestAdmin(admin.ModelAdmin):
|
||||||
('date', DateRangeFilterBuilder()),
|
('date', DateRangeFilterBuilder()),
|
||||||
)
|
)
|
||||||
search_fields = (
|
search_fields = (
|
||||||
'patient_name',
|
'patient_last_name',
|
||||||
'patient_phone',
|
'patient_phone',
|
||||||
)
|
)
|
||||||
form = forms.modelform_factory(CallRequest, fields='__all__', widgets={
|
form = forms.modelform_factory(CallRequest, fields='__all__', widgets={
|
||||||
|
|
@ -41,10 +42,9 @@ class CallRequestAdmin(admin.ModelAdmin):
|
||||||
list_editable = ('is_active',)
|
list_editable = ('is_active',)
|
||||||
readonly_fields = (
|
readonly_fields = (
|
||||||
'call_id',
|
'call_id',
|
||||||
'call_data',
|
'call_result',
|
||||||
'request_time',
|
'call_text_log',
|
||||||
'response_status_code',
|
'request_time'
|
||||||
'response_message'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@admin.display(description='Статус приема', ordering='status')
|
@admin.display(description='Статус приема', ordering='status')
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ from django.apps import AppConfig as DjangoAppConfig
|
||||||
class AppaConfig(DjangoAppConfig):
|
class AppaConfig(DjangoAppConfig):
|
||||||
|
|
||||||
name = 'appa'
|
name = 'appa'
|
||||||
verbose_name = 'МТС'
|
verbose_name = 'Обзвон'
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
import appa.receivers
|
import appa.receivers
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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
|
from django.db import migrations, models
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
@ -32,12 +33,26 @@ class Migration(migrations.Migration):
|
||||||
name='CallRequest',
|
name='CallRequest',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('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='Дата')),
|
('date', models.DateField(verbose_name='Дата')),
|
||||||
('patient_id', models.IntegerField(verbose_name='ID пациента')),
|
('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='Номер телефона')),
|
('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='Статус')),
|
('doctor_name', models.CharField(max_length=100, null=True, verbose_name='Врач')),
|
||||||
('data', models.JSONField(default=dict, 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={
|
options={
|
||||||
'verbose_name': 'Запрос на звонок',
|
'verbose_name': 'Запрос на звонок',
|
||||||
|
|
|
||||||
|
|
@ -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
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
@ -12,12 +12,12 @@ class Migration(migrations.Migration):
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='callrequest',
|
model_name='callrequest',
|
||||||
name='is_active',
|
name='call_text_log',
|
||||||
field=models.BooleanField(default=True, verbose_name='Активность'),
|
field=models.TextField(blank=True, editable=False, null=True, verbose_name='Лог'),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='callrequest',
|
model_name='callrequest',
|
||||||
name='data',
|
name='data',
|
||||||
field=models.JSONField(blank=True, default=list, verbose_name='Данные'),
|
field=models.JSONField(blank=True, default=dict, verbose_name='Данные'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
@ -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='Услуга'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -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='Результат'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -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='Статус приема'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
import json
|
import uuid
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from .managers import CallRequestManager
|
from .managers import CallRequestManager
|
||||||
|
|
@ -38,22 +38,28 @@ class CallRequest(models.Model):
|
||||||
RequestStatus.SERVICE_UNAVAILABLE: '#7961DB',
|
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,
|
status = models.CharField(max_length=20, choices=Status.choices, default=Status.PENDING,
|
||||||
verbose_name='Статус приема')
|
verbose_name='Статус приема')
|
||||||
request_status = models.CharField(max_length=20, choices=RequestStatus.choices, default=RequestStatus.NOT_SENT,
|
request_status = models.CharField(max_length=20, choices=RequestStatus.choices, default=RequestStatus.NOT_SENT,
|
||||||
verbose_name='Статус запроса')
|
verbose_name='Статус запроса')
|
||||||
date = models.DateField(verbose_name='Дата')
|
date = models.DateField(verbose_name='Дата')
|
||||||
patient_id = models.IntegerField(verbose_name='ID пациента')
|
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='Номер телефона')
|
patient_phone = models.CharField(max_length=100, verbose_name='Номер телефона')
|
||||||
doctor_name = models.CharField(max_length=100, null=True, 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='Услуга')
|
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='Адрес')
|
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='Активность')
|
is_active = models.BooleanField(default=True, verbose_name='Активность')
|
||||||
|
|
||||||
call_id = models.CharField(max_length=100, null=True, editable=False, verbose_name='ID')
|
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_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)
|
request_time = models.DateTimeField(null=True, editable=False)
|
||||||
response_status_code = models.IntegerField(null=True, editable=False)
|
response_status_code = models.IntegerField(null=True, editable=False)
|
||||||
response_message = models.TextField(null=True, editable=False)
|
response_message = models.TextField(null=True, editable=False)
|
||||||
|
|
@ -68,7 +74,7 @@ class CallRequest(models.Model):
|
||||||
objects = CallRequestManager()
|
objects = CallRequestManager()
|
||||||
|
|
||||||
def __str__(self):
|
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):
|
def get_status_color(self):
|
||||||
return self.STATUS_COLOR.get(self.status)
|
return self.STATUS_COLOR.get(self.status)
|
||||||
|
|
@ -77,6 +83,8 @@ class CallRequest(models.Model):
|
||||||
return self.REQUEST_STATUS_COLOR.get(self.request_status)
|
return self.REQUEST_STATUS_COLOR.get(self.request_status)
|
||||||
|
|
||||||
def reset_request(self):
|
def reset_request(self):
|
||||||
|
self.call_id = None
|
||||||
|
self.call_data = dict()
|
||||||
self.request_status = CallRequest.RequestStatus.NOT_SENT
|
self.request_status = CallRequest.RequestStatus.NOT_SENT
|
||||||
self.request_time = None
|
self.request_time = None
|
||||||
self.response_status_code = None
|
self.response_status_code = None
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -15,16 +15,13 @@ SECRET_KEY = 'django-insecure-13n6^zl86r@=9@!z8gsfv(q6wpggo+$box)^tklnoe9auck-)c
|
||||||
root = environ.Path(__file__) - 2
|
root = environ.Path(__file__) - 2
|
||||||
|
|
||||||
env = environ.Env(
|
env = environ.Env(
|
||||||
DEBUG=(bool, False),
|
|
||||||
LANGUAGE_CODE=(str, 'ru-RU'),
|
LANGUAGE_CODE=(str, 'ru-RU'),
|
||||||
TIME_ZONE=(str, 'Asia/Vladivostok'),
|
TIME_ZONE=(str, 'Asia/Vladivostok'),
|
||||||
USE_TZ=(bool, False),
|
USE_TZ=(bool, False),
|
||||||
USE_I18N=(bool, True),
|
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_HOST = env.str('REDIS_HOST', 'medicine-stack-redis')
|
||||||
REDIS_PORT = env.str('REDIS_PORT', '6379')
|
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_HOST = env.str('POSTGRES_HOST', 'medicine-stack-postgres')
|
||||||
POSTGRES_PORT = env.str('POSTGRES_PORT', '5432')
|
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_USER = env.str('POSTGRES_USER', 'postgres')
|
||||||
POSTGRES_PASSWORD = env.str('POSTGRES_PASSWORD', 'password')
|
POSTGRES_PASSWORD = env.str('POSTGRES_PASSWORD', 'password')
|
||||||
|
|
||||||
|
|
@ -126,13 +123,13 @@ USE_I18N = env.bool('USE_I18N')
|
||||||
|
|
||||||
USE_TZ = env.bool('USE_TZ')
|
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')
|
STATIC_ROOT = os.path.join(BASE_DIR, 'django_static')
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
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'
|
CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend'
|
||||||
|
|
||||||
|
|
@ -150,21 +147,41 @@ CONSTANCE_ADDITIONAL_FIELDS = {
|
||||||
}
|
}
|
||||||
|
|
||||||
CONSTANCE_CONFIG = {
|
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'),
|
'USERNAME': ('', 'Имя пользователя', 'char'),
|
||||||
'PASSWORD': ('', 'Пароль', 'char'),
|
'PASSWORD': ('', 'Пароль', 'char'),
|
||||||
'HOST': ('', 'Хост', 'char'),
|
|
||||||
'IS_ENABLED': (False, 'Активен', bool),
|
'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_TOKEN': ('', 'Токен', 'char'),
|
||||||
'MEDICINE_HOST': ('http://medicine-app/', 'Хост', 'char'),
|
'MEDICINE_HOST': ('http://medicine-app/', 'Хост', 'char'),
|
||||||
}
|
}
|
||||||
|
|
||||||
CONSTANCE_CONFIG_FIELDSETS = (
|
CONSTANCE_CONFIG_FIELDSETS = (
|
||||||
('МТС', (
|
('API', (
|
||||||
'HOST',
|
'HOST',
|
||||||
|
'ENTRYPOINT_AUTH',
|
||||||
|
'ENTRYPOINT_ADD_RECORDS',
|
||||||
|
'ENTRYPOINT_DELETE',
|
||||||
|
'ENTRYPOINT_RECORD',
|
||||||
|
'SCENARIO_ID',
|
||||||
'USERNAME',
|
'USERNAME',
|
||||||
'PASSWORD',
|
'PASSWORD',
|
||||||
'IS_ENABLED',
|
'IS_ENABLED',
|
||||||
|
'ACCESS_TOKEN',
|
||||||
|
'ACCESS_TOKEN_EXPIRED',
|
||||||
|
'REFRESH_TOKEN'
|
||||||
)),
|
)),
|
||||||
('МИС', (
|
('МИС', (
|
||||||
'MEDICINE_HOST',
|
'MEDICINE_HOST',
|
||||||
|
|
@ -191,4 +208,4 @@ CALL_REQUEST_TIME_END = datetime.time(21, 0)
|
||||||
|
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
AUTH_PASSWORD_VALIDATORS = []
|
AUTH_PASSWORD_VALIDATORS = []
|
||||||
SESSION_COOKIE_NAME = 'dev-medicine-mts'
|
SESSION_COOKIE_NAME = 'dev-medicine-call'
|
||||||
|
|
|
||||||
|
|
@ -5,23 +5,24 @@ from constance import config
|
||||||
from appa.celery import app
|
from appa.celery import app
|
||||||
|
|
||||||
from appa.models import *
|
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)
|
@app.task(bind=True, acks_late=True)
|
||||||
def send_call_request_task(self, ids=None):
|
def send_call_request_task(self, ids=None):
|
||||||
tomorrow = datetime.date.today() + datetime.timedelta(days=1)
|
call_requests = CallRequest.objects.filter(is_active=True)
|
||||||
|
|
||||||
call_requests = CallRequest.objects.filter(
|
|
||||||
date=tomorrow,
|
|
||||||
status__in=[
|
|
||||||
CallRequest.Status.PENDING,
|
|
||||||
CallRequest.Status.WITHOUT_ANSWER
|
|
||||||
],
|
|
||||||
is_active=True
|
|
||||||
)
|
|
||||||
if ids and len(ids) > 0:
|
if ids and len(ids) > 0:
|
||||||
call_requests = call_requests.filter(id__in=ids)
|
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:
|
for call_request in call_requests:
|
||||||
add_call_request(call_request)
|
add_call_request(call_request)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
{% extends "admin/base_site.html" %}
|
{% extends "admin/base_site.html" %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
||||||
{% block title %}{{ title }} | МТС{% endblock %}
|
{% block title %}{{ title }} | CALL{% endblock %}
|
||||||
|
|
||||||
{% block branding %}
|
{% block branding %}
|
||||||
<h1 id="site-name">
|
<h1 id="site-name">
|
||||||
<a href="{% url 'admin:index' %}">МТС</a>
|
<a href="{% url 'admin:index' %}">CALL</a>
|
||||||
</h1>
|
</h1>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
|
|
@ -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.views.decorators.csrf import csrf_exempt
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from django.utils.crypto import get_random_string
|
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
|
@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({
|
return JsonResponse({
|
||||||
'request_id': get_random_string(10),
|
'added_records': results
|
||||||
'success': '1'
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
13
appa/urls.py
13
appa/urls.py
|
|
@ -10,17 +10,18 @@ from appa import test_views
|
||||||
admin.site.unregister(Group)
|
admin.site.unregister(Group)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('medicine-mts/admin/', admin.site.urls),
|
path('medicine-call/admin/', admin.site.urls),
|
||||||
path('medicine-mts/api/', api.urls),
|
path('medicine-call/api/', api.urls),
|
||||||
path('medicine-mts/', lambda request: redirect('/medicine-mts/admin/')),
|
path('medicine-call/', lambda request: redirect('/medicine-call/admin/')),
|
||||||
path('admin/', lambda request: redirect('/medicine-mts/admin/')),
|
path('admin/', lambda request: redirect('/medicine-call/admin/')),
|
||||||
path('', lambda request: redirect('/medicine-mts/admin/')),
|
path('', lambda request: redirect('/medicine-call/admin/')),
|
||||||
]
|
]
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
from django.contrib.staticfiles.urls import staticfiles_urlpatterns, static
|
from django.contrib.staticfiles.urls import staticfiles_urlpatterns, static
|
||||||
urlpatterns +=[
|
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_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/add_500_error_view/', test_views.add_500_error_view),
|
||||||
path('medicine-mts/tests/history_view/', test_views.history_view),
|
path('medicine-mts/tests/history_view/', test_views.history_view),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
docker build \
|
||||||
|
--target python-nginx \
|
||||||
|
--file ./Dockerfile \
|
||||||
|
--tag medicine-call-local:latest .
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
docker exec medicine-call-local-server celery -A appa worker -B --loglevel=INFO --concurrency=1
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
docker exec -it medicine-call-local-server bash
|
||||||
|
|
@ -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/
|
||||||
|
|
@ -11,6 +11,7 @@ click-didyoumean==0.3.1
|
||||||
click-plugins==1.1.1
|
click-plugins==1.1.1
|
||||||
click-repl==0.3.0
|
click-repl==0.3.0
|
||||||
Django==3.2
|
Django==3.2
|
||||||
|
django-admin-rangefilter==0.13.2
|
||||||
django-constance==3.1.0
|
django-constance==3.1.0
|
||||||
django-environ==0.11.2
|
django-environ==0.11.2
|
||||||
django-ninja==1.2.0
|
django-ninja==1.2.0
|
||||||
|
|
@ -31,6 +32,7 @@ sqlparse==0.5.1
|
||||||
typing_extensions==4.12.2
|
typing_extensions==4.12.2
|
||||||
tzdata==2024.1
|
tzdata==2024.1
|
||||||
urllib3==2.2.2
|
urllib3==2.2.2
|
||||||
uWSGI==2.0.26
|
uWSGI==2.0.28
|
||||||
vine==5.1.0
|
vine==5.1.0
|
||||||
wcwidth==0.2.13
|
wcwidth==0.2.13
|
||||||
|
wheel==0.43.0
|
||||||
|
|
@ -17,7 +17,7 @@ command=uwsgi
|
||||||
--vacuum
|
--vacuum
|
||||||
--need-app
|
--need-app
|
||||||
--disable-write-exception
|
--disable-write-exception
|
||||||
--static-map /medicine-mts/django_static=/app/django_static
|
--static-map /medicine-call/django_static=/app/django_static
|
||||||
autostart=true
|
autostart=true
|
||||||
autorestart=true
|
autorestart=true
|
||||||
stderr_logfile=/dev/stderr
|
stderr_logfile=/dev/stderr
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue