pass
This commit is contained in:
parent
ea0223e100
commit
54d5007dae
|
|
@ -1,3 +1,4 @@
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
@ -5,13 +6,35 @@ from django.core.checks import messages
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from constance import config
|
||||||
from ace_editor import AceJSONWidget
|
from ace_editor import AceJSONWidget
|
||||||
from rangefilter.filters import DateRangeFilterBuilder
|
from rangefilter.filters import DateRangeFilterBuilder
|
||||||
|
|
||||||
from .models import *
|
from .models import *
|
||||||
from .admin_forms import *
|
from .admin_forms import *
|
||||||
from .admin_filters import *
|
from .admin_filters import *
|
||||||
from .tasks import send_call_request_task
|
from .tasks import send_call_request_task, update_call_requests_task
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(CallMedicalSpeciality)
|
||||||
|
class CallMedicalSpecialityAdmin(admin.ModelAdmin):
|
||||||
|
autocomplete_fields = ['speciality']
|
||||||
|
list_display = ('speciality_name', 'name')
|
||||||
|
search_fields = ('name',)
|
||||||
|
|
||||||
|
@admin.display(description='Специальность')
|
||||||
|
def speciality_name(self, obj):
|
||||||
|
return obj.speciality.name
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(CallLPU)
|
||||||
|
class CallLPUAdmin(admin.ModelAdmin):
|
||||||
|
autocomplete_fields = ['lpu']
|
||||||
|
list_display = ('__str__', 'lpu_short_name', 'name', 'address')
|
||||||
|
|
||||||
|
@admin.display(description='Название')
|
||||||
|
def lpu_short_name(self, obj):
|
||||||
|
return obj.lpu.short_name
|
||||||
|
|
||||||
|
|
||||||
@admin.register(CallRequest)
|
@admin.register(CallRequest)
|
||||||
|
|
@ -23,6 +46,7 @@ class CallRequestAdmin(admin.ModelAdmin):
|
||||||
'patient_last_name',
|
'patient_last_name',
|
||||||
'patient_first_name',
|
'patient_first_name',
|
||||||
'patient_phone',
|
'patient_phone',
|
||||||
|
'service_name',
|
||||||
'is_active',
|
'is_active',
|
||||||
)
|
)
|
||||||
list_filter = (
|
list_filter = (
|
||||||
|
|
@ -38,7 +62,13 @@ class CallRequestAdmin(admin.ModelAdmin):
|
||||||
form = forms.modelform_factory(CallRequest, fields='__all__', widgets={
|
form = forms.modelform_factory(CallRequest, fields='__all__', widgets={
|
||||||
'data': AceJSONWidget()
|
'data': AceJSONWidget()
|
||||||
})
|
})
|
||||||
actions = ['send_call_request']
|
actions = [
|
||||||
|
'send_call_request',
|
||||||
|
'delete_call_request',
|
||||||
|
'set_is_active_false',
|
||||||
|
'set_is_active_true',
|
||||||
|
'update_call_requests'
|
||||||
|
]
|
||||||
list_editable = ('is_active',)
|
list_editable = ('is_active',)
|
||||||
readonly_fields = (
|
readonly_fields = (
|
||||||
'call_id',
|
'call_id',
|
||||||
|
|
@ -71,10 +101,11 @@ class CallRequestAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
@admin.action(description='Отправить выбранные записи на обзвон')
|
@admin.action(description='Отправить выбранные записи на обзвон')
|
||||||
def send_call_request(self, request, queryset):
|
def send_call_request(self, request, queryset):
|
||||||
now = timezone.now()
|
if config.CALL_TIME_START <= timezone.now().time() <= config.CALL_TIME_END:
|
||||||
if settings.CALL_REQUEST_TIME_START <= now.time() <= settings.CALL_REQUEST_TIME_END:
|
ids = [item.id for item in queryset.filter(request_status=CallRequest.RequestStatus.NOT_SENT)]
|
||||||
ids = [item.id for item in queryset]
|
if len(ids) > 0:
|
||||||
send_call_request_task.apply_async(args=(ids,))
|
send_call_request_task.apply_async(args=(ids,))
|
||||||
|
|
||||||
self.message_user(request, message=f'Записей отправлено на обзвон: {len(ids)}')
|
self.message_user(request, message=f'Записей отправлено на обзвон: {len(ids)}')
|
||||||
else:
|
else:
|
||||||
self.message_user(
|
self.message_user(
|
||||||
|
|
@ -84,6 +115,27 @@ class CallRequestAdmin(admin.ModelAdmin):
|
||||||
level=messages.ERROR
|
level=messages.ERROR
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@admin.action(description='Удалить выбранные записи из обзвона')
|
||||||
|
def delete_call_request(self, request, queryset):
|
||||||
|
for call_request in queryset: #.filter(request_status=CallRequest.RequestStatus.SENT):
|
||||||
|
from appa.call_api.api import delete_call_request
|
||||||
|
delete_call_request(call_request)
|
||||||
|
|
||||||
|
@admin.action(description='Установить активность на "False"')
|
||||||
|
def set_is_active_false(self, request, queryset):
|
||||||
|
queryset.update(is_active=False)
|
||||||
|
self.message_user(request, f'Обновлено записей: {queryset.count()}')
|
||||||
|
|
||||||
|
@admin.action(description='Установить активность на "True"')
|
||||||
|
def set_is_active_true(self, request, queryset):
|
||||||
|
queryset.update(is_active=True)
|
||||||
|
self.message_user(request, f'Обновлено записей: {queryset.count()}')
|
||||||
|
|
||||||
|
@admin.action(description='Синхронизировать список запросов на звонки с МИС')
|
||||||
|
def update_call_requests(self, request, queryset):
|
||||||
|
update_call_requests_task.apply_async()
|
||||||
|
self.message_user(request, f'Задача отправлена на выполнение')
|
||||||
|
|
||||||
|
|
||||||
@admin.register(RequestLog)
|
@admin.register(RequestLog)
|
||||||
class RequestLogAdmin(admin.ModelAdmin):
|
class RequestLogAdmin(admin.ModelAdmin):
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ import requests
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from constance import config
|
from constance import config
|
||||||
|
|
||||||
from .models import CallRequest, RequestLog
|
from appa.models import CallRequest, RequestLog
|
||||||
from appa.call_api import call_status
|
from . import call_status
|
||||||
|
|
||||||
|
|
||||||
def auth_request():
|
def auth_request():
|
||||||
|
|
@ -19,7 +19,6 @@ def auth_request():
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if r.status_code == 200:
|
if r.status_code == 200:
|
||||||
print(r.json())
|
|
||||||
config.ACCESS_TOKEN = r.json()['accessToken']
|
config.ACCESS_TOKEN = r.json()['accessToken']
|
||||||
config.REFRESH_TOKEN = r.json()['refreshToken']
|
config.REFRESH_TOKEN = r.json()['refreshToken']
|
||||||
config.ACCESS_TOKEN_EXPIRED = datetime.datetime.now() + datetime.timedelta(minutes=5)
|
config.ACCESS_TOKEN_EXPIRED = datetime.datetime.now() + datetime.timedelta(minutes=5)
|
||||||
|
|
@ -45,6 +44,7 @@ def delete_call_request(call_request: CallRequest, logging=True):
|
||||||
headers={'Authorization': f'Bearer {get_token()}'},
|
headers={'Authorization': f'Bearer {get_token()}'},
|
||||||
hooks=hooks
|
hooks=hooks
|
||||||
)
|
)
|
||||||
|
print(r.status_code)
|
||||||
if r.status_code == 200:
|
if r.status_code == 200:
|
||||||
call_request.reset_request()
|
call_request.reset_request()
|
||||||
|
|
||||||
|
|
@ -65,19 +65,32 @@ def get_record(call_request: CallRequest, logging=True):
|
||||||
)
|
)
|
||||||
if r.status_code == 200:
|
if r.status_code == 200:
|
||||||
result = r.json()
|
result = r.json()
|
||||||
call_request.call_text_log = result['text_log']
|
if result['call_result_code'] != call_status.STATUS_1:
|
||||||
call_request.call_result = result['call_result']
|
call_request.call_text_log = result['text_log']
|
||||||
|
call_request.call_result = result['call_result']
|
||||||
|
|
||||||
if result['confirmed']:
|
if result['call_result_code'] not in [call_status.STATUS_14]:
|
||||||
call_request.status = call_request.Status.APPROVED
|
call_request.request_status = call_request.RequestStatus.COMPLETED
|
||||||
elif result['call_result_code'] in call_status.STATUS_CANCELLED:
|
|
||||||
call_request.status = call_request.Status.CANCELED
|
|
||||||
elif result['call_result_code'] in call_status.STATUS_WITHOUT_ANSWER:
|
|
||||||
call_request.status = call_request.Status.WITHOUT_ANSWER
|
|
||||||
else:
|
|
||||||
call_request.status = call_request.Status.OTHER
|
|
||||||
|
|
||||||
call_request.save()
|
if result['confirmed']:
|
||||||
|
call_request.status = call_request.Status.APPROVED
|
||||||
|
|
||||||
|
elif result['call_result_code'] == call_status.STATUS_5:
|
||||||
|
call_request.status = call_request.Status.CALLBACK
|
||||||
|
|
||||||
|
elif result['call_result_code'] in call_status.STATUS_CANCELLED:
|
||||||
|
call_request.status = call_request.Status.CANCELED
|
||||||
|
|
||||||
|
from appa.medicine_api.api import cancel_booking
|
||||||
|
cancel_booking(call_request.booking_id)
|
||||||
|
|
||||||
|
elif result['call_result_code'] in call_status.STATUS_WITHOUT_ANSWER:
|
||||||
|
call_request.status = call_request.Status.WITHOUT_ANSWER
|
||||||
|
|
||||||
|
else:
|
||||||
|
call_request.status = call_request.Status.OTHER
|
||||||
|
|
||||||
|
call_request.save()
|
||||||
|
|
||||||
|
|
||||||
def add_call_request(call_request: CallRequest, logging=True, delete=False):
|
def add_call_request(call_request: CallRequest, logging=True, delete=False):
|
||||||
|
|
@ -90,10 +103,10 @@ def add_call_request(call_request: CallRequest, logging=True, delete=False):
|
||||||
second_name=call_request.patient_last_name,
|
second_name=call_request.patient_last_name,
|
||||||
middle_name=call_request.patient_middle_name,
|
middle_name=call_request.patient_middle_name,
|
||||||
phone_number=call_request.patient_phone,
|
phone_number=call_request.patient_phone,
|
||||||
receipt_date=call_request.date.strftime('%Y-%m-%d'),
|
receipt_date=call_request.booking_date.strftime('%Y-%m-%d'),
|
||||||
receipt_time=call_request.date.strftime('%H:%M'),
|
receipt_time=call_request.booking_date.strftime('%H:%M'),
|
||||||
doctor_specialisation=call_request.doctor_speciality,
|
doctor_specialisation=call_request.service_name,
|
||||||
doctor_fullname=call_request.doctor_name,
|
note=call_request.organization,
|
||||||
filial=call_request.address,
|
filial=call_request.address,
|
||||||
ext_id=str(call_request.uid)
|
ext_id=str(call_request.uid)
|
||||||
)])
|
)])
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
default_app_config = 'appa.medicine.apps.MedicineConfig'
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
from django.contrib import admin
|
||||||
|
from .models import *
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(MedicalSpeciality)
|
||||||
|
class CallMedicalSpecialityAdmin(admin.ModelAdmin):
|
||||||
|
search_fields = ['code', 'name']
|
||||||
|
list_display = ['code', 'name']
|
||||||
|
|
||||||
|
def has_add_permission(self, request):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def has_delete_permission(self, request, obj=None):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def has_change_permission(self, request, obj=None):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(LPU)
|
||||||
|
class LPUAdmin(admin.ModelAdmin):
|
||||||
|
search_fields = ['full_name']
|
||||||
|
list_display = ['full_name']
|
||||||
|
|
||||||
|
def has_add_permission(self, request):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def has_delete_permission(self, request, obj=None):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def has_change_permission(self, request, obj=None):
|
||||||
|
return False
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class MedicineConfig(AppConfig):
|
||||||
|
|
||||||
|
name = 'appa.medicine'
|
||||||
|
verbose_name = 'Медицина'
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'MedicalSpeciality',
|
||||||
|
'MedicalService',
|
||||||
|
'LPU'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class MedicalService(models.Model):
|
||||||
|
|
||||||
|
code = models.CharField(max_length=32, verbose_name='Код')
|
||||||
|
local_code = models.CharField(max_length=32, null=True, blank=True, verbose_name='Локальный код')
|
||||||
|
name = models.CharField(max_length=1024, db_index=True, verbose_name='Название')
|
||||||
|
is_active = models.BooleanField(default=True, db_index=True, verbose_name='Активность')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'Услуга'
|
||||||
|
verbose_name_plural = 'Услуги'
|
||||||
|
db_table = 'catalog_medicalservice'
|
||||||
|
managed = False
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.local_code:
|
||||||
|
return f'{self.local_code} - {self.code} - {self.name}'
|
||||||
|
else:
|
||||||
|
return f'{self.code} - {self.name}'
|
||||||
|
|
||||||
|
|
||||||
|
class MedicalSpeciality(models.Model):
|
||||||
|
|
||||||
|
id = models.PositiveIntegerField(primary_key=True, verbose_name='id')
|
||||||
|
code = models.IntegerField(verbose_name='Код', unique=True)
|
||||||
|
name = models.CharField(max_length=1024, verbose_name='Название')
|
||||||
|
is_active = models.BooleanField(default=True, verbose_name='Активность')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'Медицинская специальность'
|
||||||
|
verbose_name_plural = 'Медицинские специальности'
|
||||||
|
db_table = 'catalog_medicalspeciality'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '%s (%s)' % (self.name, self.code)
|
||||||
|
|
||||||
|
|
||||||
|
class LPU(models.Model):
|
||||||
|
|
||||||
|
code = models.IntegerField(unique=True, primary_key=True, verbose_name='Код учреждения')
|
||||||
|
full_name = models.CharField(max_length=200, verbose_name='Полное название')
|
||||||
|
short_name = models.CharField(max_length=200, verbose_name='Короткое название')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'ЛПУ'
|
||||||
|
verbose_name_plural = 'ЛПУ'
|
||||||
|
db_table = 'lpu'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{self.full_name} {self.code}'
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
|
||||||
|
from django.db.utils import DEFAULT_DB_ALIAS
|
||||||
|
|
||||||
|
APP_NAME = 'medicine'
|
||||||
|
DATABASE_NAME = 'medicine'
|
||||||
|
|
||||||
|
|
||||||
|
class MedicineRouter:
|
||||||
|
|
||||||
|
def db_for_read(self, model, **hints):
|
||||||
|
if model._meta.app_label in [APP_NAME]:
|
||||||
|
return DATABASE_NAME
|
||||||
|
return DEFAULT_DB_ALIAS
|
||||||
|
|
||||||
|
def db_for_write(self, model, **hints):
|
||||||
|
if model._meta.app_label in [APP_NAME]:
|
||||||
|
return DATABASE_NAME
|
||||||
|
return DEFAULT_DB_ALIAS
|
||||||
|
|
||||||
|
def allow_migrate(self, db, app_label, model_name=None, **hints):
|
||||||
|
if db == DATABASE_NAME:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if app_label == APP_NAME:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def allow_relation(self, obj1, obj2, **hints):
|
||||||
|
app_label_obj1 = obj1.__class__._meta.app_label
|
||||||
|
app_label_obj2 = obj2.__class__._meta.app_label
|
||||||
|
|
||||||
|
if app_label_obj1 == APP_NAME or app_label_obj2 == APP_NAME:
|
||||||
|
return True
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from constance import config
|
||||||
|
|
||||||
|
|
||||||
|
def get_bookings(date):
|
||||||
|
bookings = []
|
||||||
|
limit = 50
|
||||||
|
offset = 0
|
||||||
|
while True:
|
||||||
|
r = requests.get(
|
||||||
|
f'{config.MEDICINE_HOST}api/1/booking/',
|
||||||
|
params={
|
||||||
|
'date_start__date': date.strftime('%d.%m.%Y'),
|
||||||
|
'patient__phone_mobile__isnull': False,
|
||||||
|
'patient__isnull': False,
|
||||||
|
'status': 1,
|
||||||
|
'limit': limit,
|
||||||
|
'offset': offset,
|
||||||
|
},
|
||||||
|
headers={
|
||||||
|
'Authorization': f'Token {config.MEDICINE_TOKEN}'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if r.status_code == 200:
|
||||||
|
response = r.json()
|
||||||
|
for booking in response['results']:
|
||||||
|
detail_request = requests.get(
|
||||||
|
f'{config.MEDICINE_HOST}api/1/booking/{booking["id"]}/',
|
||||||
|
headers = {
|
||||||
|
'Authorization': f'Token {config.MEDICINE_TOKEN}'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
bookings.append(detail_request.json())
|
||||||
|
|
||||||
|
if response['next'] is None:
|
||||||
|
break
|
||||||
|
|
||||||
|
offset += 50
|
||||||
|
|
||||||
|
return bookings
|
||||||
|
|
||||||
|
|
||||||
|
def cancel_booking(booking_id):
|
||||||
|
r = requests.post(
|
||||||
|
f'{config.MEDICINE_HOST}api/1/booking/{booking_id}/failed/',
|
||||||
|
data={
|
||||||
|
'failed_reason': 'CANCELED'
|
||||||
|
},
|
||||||
|
headers={
|
||||||
|
'Authorization': f'Token {config.MEDICINE_TOKEN}'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
# Generated by Django 3.2 on 2025-02-25 18:42
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('medicine', '__first__'),
|
||||||
|
('appa', '0003_callrequest_call_result'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='callrequest',
|
||||||
|
name='booking_id',
|
||||||
|
field=models.PositiveIntegerField(null=True, verbose_name='ID записи на прием'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='callrequest',
|
||||||
|
name='call_result',
|
||||||
|
field=models.CharField(blank=True, editable=False, max_length=100, null=True, verbose_name='Результат'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='callrequest',
|
||||||
|
name='status',
|
||||||
|
field=models.CharField(choices=[('PENDING', 'Обзвон еще не состоялся'), ('APPROVED', 'Прием подтвержден'), ('CANCELED', 'Прием отменен'), ('WITHOUT_ANSWER', 'Не дозвонились'), ('OTHER', 'Другая ошибка')], default='PENDING', max_length=20, verbose_name='Статус приема'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CallMedicalService',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=100, verbose_name='Произношение роботом')),
|
||||||
|
('medical_service', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, to='medicine.medicalservice', verbose_name='Услуга (МИС)')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Услуга',
|
||||||
|
'verbose_name_plural': 'Услуги',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Generated by Django 3.2 on 2025-02-25 18:53
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('medicine', '__first__'),
|
||||||
|
('appa', '0004_auto_20250225_1842'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CallLPU',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=100, verbose_name='Произношение роботом')),
|
||||||
|
('address', models.CharField(blank=True, max_length=200, null=True, verbose_name='Адрес')),
|
||||||
|
('lpu', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, to='medicine.lpu', verbose_name='ЛПУ')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Филиал',
|
||||||
|
'verbose_name_plural': 'Филиалы',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Generated by Django 3.2 on 2025-02-25 20:42
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('appa', '0005_calllpu'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='calllpu',
|
||||||
|
name='address',
|
||||||
|
field=models.TextField(blank=True, max_length=200, null=True, verbose_name='Адрес'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='callrequest',
|
||||||
|
name='address',
|
||||||
|
field=models.CharField(blank=True, max_length=200, null=True, verbose_name='Адрес'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='callrequest',
|
||||||
|
name='doctor_speciality',
|
||||||
|
field=models.CharField(max_length=200, null=True, verbose_name='Специальность врача'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='callrequest',
|
||||||
|
name='service_name',
|
||||||
|
field=models.CharField(blank=True, max_length=200, null=True, verbose_name='Услуга'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 3.2 on 2025-02-26 15:11
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('appa', '0006_auto_20250225_2042'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='callrequest',
|
||||||
|
name='booking_date',
|
||||||
|
field=models.DateTimeField(null=True, verbose_name='Дата и время записи на прием'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 3.2 on 2025-02-27 15:04
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('appa', '0007_callrequest_booking_date'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='callrequest',
|
||||||
|
name='organization',
|
||||||
|
field=models.CharField(blank=True, max_length=200, null=True, verbose_name='Организация'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='calllpu',
|
||||||
|
name='address',
|
||||||
|
field=models.TextField(blank=True, max_length=200, null=True, verbose_name='Адрес для произношения роботом'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Generated by Django 3.2 on 2025-03-01 20:28
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('medicine', '__first__'),
|
||||||
|
('appa', '0008_auto_20250227_1504'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='callrequest',
|
||||||
|
name='request_status',
|
||||||
|
field=models.CharField(choices=[('PENDING', 'Не отправлен'), ('APPROVED', 'Отправлен'), ('ERROR', 'Ошибка'), ('SERVICE_UNAVAILABLE', 'Сервис недоступен'), ('COMPLETED', 'Завершен')], default='PENDING', max_length=20, verbose_name='Статус запроса'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='callrequest',
|
||||||
|
name='status',
|
||||||
|
field=models.CharField(choices=[('PENDING', 'Обзвон еще не состоялся'), ('APPROVED', 'Прием подтвержден'), ('CANCELED', 'Прием отменен'), ('CALLBACK', 'Перезвонить'), ('WITHOUT_ANSWER', 'Не дозвонились'), ('OTHER', 'Другая ошибка')], default='PENDING', max_length=20, verbose_name='Статус приема'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CallMedicalSpeciality',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=100, verbose_name='Произношение роботом')),
|
||||||
|
('speciality', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, to='medicine.medicalspeciality', verbose_name='Специальность (МИС)')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Специальность',
|
||||||
|
'verbose_name_plural': 'Специальности',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Generated by Django 3.2 on 2025-03-02 09:22
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('appa', '0009_auto_20250301_2028'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='callrequest',
|
||||||
|
name='booking_id',
|
||||||
|
field=models.PositiveIntegerField(null=True, unique=True, verbose_name='ID записи на прием'),
|
||||||
|
),
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='callrequest',
|
||||||
|
unique_together=set(),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -5,17 +5,63 @@ from django.db import models
|
||||||
from .managers import CallRequestManager
|
from .managers import CallRequestManager
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
'CallMedicalService',
|
||||||
|
'CallMedicalSpeciality',
|
||||||
|
'CallLPU',
|
||||||
'CallRequest',
|
'CallRequest',
|
||||||
'RequestLog'
|
'RequestLog'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class CallMedicalService(models.Model):
|
||||||
|
|
||||||
|
medical_service = models.ForeignKey('medicine.MedicalService', db_constraint=False, on_delete=models.CASCADE,
|
||||||
|
verbose_name='Услуга (МИС)')
|
||||||
|
name = models.CharField(max_length=100, verbose_name='Произношение роботом')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'Услуга'
|
||||||
|
verbose_name_plural = 'Услуги'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{self.medical_service.name} ← {self.name}'
|
||||||
|
|
||||||
|
|
||||||
|
class CallMedicalSpeciality(models.Model):
|
||||||
|
|
||||||
|
speciality = models.ForeignKey('medicine.MedicalSpeciality', db_constraint=False, on_delete=models.CASCADE,
|
||||||
|
verbose_name='Специальность (МИС)')
|
||||||
|
name = models.CharField(max_length=100, verbose_name='Произношение роботом')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'Специальность'
|
||||||
|
verbose_name_plural = 'Специальности'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{self.name}'
|
||||||
|
|
||||||
|
|
||||||
|
class CallLPU(models.Model):
|
||||||
|
|
||||||
|
lpu = models.ForeignKey('medicine.LPU', db_constraint=False, on_delete=models.CASCADE, verbose_name='ЛПУ')
|
||||||
|
name = models.CharField(max_length=100, verbose_name='Произношение роботом')
|
||||||
|
address = models.TextField(max_length=200, null=True, blank=True, verbose_name='Адрес для произношения роботом')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'Филиал'
|
||||||
|
verbose_name_plural = 'Филиалы'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.lpu.full_name
|
||||||
|
|
||||||
|
|
||||||
class CallRequest(models.Model):
|
class CallRequest(models.Model):
|
||||||
|
|
||||||
class Status(models.TextChoices):
|
class Status(models.TextChoices):
|
||||||
PENDING = 'PENDING', 'Обзвон еще не состоялся'
|
PENDING = 'PENDING', 'Обзвон еще не состоялся'
|
||||||
APPROVED = 'APPROVED', 'Прием подтвержден'
|
APPROVED = 'APPROVED', 'Прием подтвержден'
|
||||||
CANCELED = 'CANCELED', 'Прием отменен'
|
CANCELED = 'CANCELED', 'Прием отменен'
|
||||||
|
CALLBACK = 'CALLBACK', 'Перезвонить'
|
||||||
WITHOUT_ANSWER = 'WITHOUT_ANSWER', 'Не дозвонились'
|
WITHOUT_ANSWER = 'WITHOUT_ANSWER', 'Не дозвонились'
|
||||||
OTHER = 'OTHER', 'Другая ошибка'
|
OTHER = 'OTHER', 'Другая ошибка'
|
||||||
|
|
||||||
|
|
@ -23,7 +69,9 @@ class CallRequest(models.Model):
|
||||||
Status.PENDING: '#2D72D2',
|
Status.PENDING: '#2D72D2',
|
||||||
Status.APPROVED: '#238551',
|
Status.APPROVED: '#238551',
|
||||||
Status.CANCELED: '#CD4246',
|
Status.CANCELED: '#CD4246',
|
||||||
|
Status.CALLBACK: '#935610',
|
||||||
Status.WITHOUT_ANSWER: '#866103',
|
Status.WITHOUT_ANSWER: '#866103',
|
||||||
|
Status.OTHER: '#5A701A'
|
||||||
}
|
}
|
||||||
|
|
||||||
class RequestStatus(models.TextChoices):
|
class RequestStatus(models.TextChoices):
|
||||||
|
|
@ -31,12 +79,14 @@ class CallRequest(models.Model):
|
||||||
SENT = 'APPROVED', 'Отправлен'
|
SENT = 'APPROVED', 'Отправлен'
|
||||||
ERROR = 'ERROR', 'Ошибка'
|
ERROR = 'ERROR', 'Ошибка'
|
||||||
SERVICE_UNAVAILABLE = 'SERVICE_UNAVAILABLE', 'Сервис недоступен'
|
SERVICE_UNAVAILABLE = 'SERVICE_UNAVAILABLE', 'Сервис недоступен'
|
||||||
|
COMPLETED = 'COMPLETED', 'Завершен'
|
||||||
|
|
||||||
REQUEST_STATUS_COLOR = {
|
REQUEST_STATUS_COLOR = {
|
||||||
RequestStatus.NOT_SENT: '#2D72D2',
|
RequestStatus.NOT_SENT: '#2D72D2',
|
||||||
RequestStatus.SENT: '#238551',
|
RequestStatus.SENT: '#238551',
|
||||||
RequestStatus.ERROR: '#CD4246',
|
RequestStatus.ERROR: '#CD4246',
|
||||||
RequestStatus.SERVICE_UNAVAILABLE: '#7961DB',
|
RequestStatus.SERVICE_UNAVAILABLE: '#7961DB',
|
||||||
|
RequestStatus.COMPLETED: '#147EB3',
|
||||||
}
|
}
|
||||||
|
|
||||||
uid = models.UUIDField(unique=True, default=uuid.uuid4, editable=False)
|
uid = models.UUIDField(unique=True, default=uuid.uuid4, editable=False)
|
||||||
|
|
@ -45,16 +95,18 @@ class CallRequest(models.Model):
|
||||||
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='Дата')
|
||||||
booking_id = models.PositiveIntegerField(null=True, verbose_name='ID записи на прием')
|
booking_id = models.PositiveIntegerField(unique=True, null=True, verbose_name='ID записи на прием')
|
||||||
|
booking_date = models.DateTimeField(null=True, verbose_name='Дата и время записи на прием')
|
||||||
patient_id = models.IntegerField(verbose_name='ID пациента')
|
patient_id = models.IntegerField(verbose_name='ID пациента')
|
||||||
patient_first_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_last_name = models.CharField(max_length=200, verbose_name='Фамилия')
|
||||||
patient_middle_name = models.CharField(max_length=200, null=True, blank=True, 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='Специальность врача')
|
doctor_speciality = models.CharField(max_length=200, null=True, verbose_name='Специальность врача')
|
||||||
service_name = models.CharField(max_length=100, null=True, blank=True, verbose_name='Услуга')
|
service_name = models.CharField(max_length=200, null=True, blank=True, verbose_name='Услуга')
|
||||||
address = models.CharField(max_length=100, null=True, blank=True, verbose_name='Адрес')
|
organization = models.CharField(max_length=200, null=True, blank=True, verbose_name='Организация')
|
||||||
|
address = models.CharField(max_length=200, null=True, blank=True, verbose_name='Адрес')
|
||||||
data = models.JSONField(default=dict, 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='Активность')
|
||||||
|
|
||||||
|
|
@ -69,9 +121,6 @@ class CallRequest(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = 'Запрос на звонок'
|
verbose_name = 'Запрос на звонок'
|
||||||
verbose_name_plural = 'Запросы на звонки'
|
verbose_name_plural = 'Запросы на звонки'
|
||||||
unique_together = (
|
|
||||||
('date', 'patient_id'),
|
|
||||||
)
|
|
||||||
|
|
||||||
objects = CallRequestManager()
|
objects = CallRequestManager()
|
||||||
|
|
||||||
|
|
@ -88,6 +137,7 @@ class CallRequest(models.Model):
|
||||||
self.call_id = None
|
self.call_id = None
|
||||||
self.call_data = dict()
|
self.call_data = dict()
|
||||||
self.request_status = CallRequest.RequestStatus.NOT_SENT
|
self.request_status = CallRequest.RequestStatus.NOT_SENT
|
||||||
|
self.status = CallRequest.Status.PENDING
|
||||||
self.request_time = None
|
self.request_time = None
|
||||||
self.response_status_code = None
|
self.response_status_code = None
|
||||||
self.response_message = None
|
self.response_message = None
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ INSTALLED_APPS = [
|
||||||
'rangefilter',
|
'rangefilter',
|
||||||
|
|
||||||
'appa',
|
'appa',
|
||||||
|
'appa.medicine',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
|
@ -92,7 +93,7 @@ DATABASES = {
|
||||||
},
|
},
|
||||||
'medicine': {
|
'medicine': {
|
||||||
'ENGINE': 'django.db.backends.postgresql',
|
'ENGINE': 'django.db.backends.postgresql',
|
||||||
'NAME': 'medicine',
|
'NAME': env.str('POSTGRES_MEDICINE_DB', 'medicine'),
|
||||||
'USER': POSTGRES_USER,
|
'USER': POSTGRES_USER,
|
||||||
'PASSWORD': POSTGRES_PASSWORD,
|
'PASSWORD': POSTGRES_PASSWORD,
|
||||||
'HOST': POSTGRES_HOST,
|
'HOST': POSTGRES_HOST,
|
||||||
|
|
@ -143,11 +144,10 @@ CONSTANCE_ADDITIONAL_FIELDS = {
|
||||||
'widget': 'django.forms.TextInput',
|
'widget': 'django.forms.TextInput',
|
||||||
'widget_kwargs': dict(attrs={'size': 60}),
|
'widget_kwargs': dict(attrs={'size': 60}),
|
||||||
'required': False
|
'required': False
|
||||||
}],
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
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_ADD_RECORDS': ('https://amniss-ai.ru/api/v.2/records/{scenarioId}', 'Адрес для добавления записей', 'char'),
|
||||||
'ENTRYPOINT_AUTH': ('https://amniss-ai.ru/api/auth', 'Адрес для авторизации', 'char'),
|
'ENTRYPOINT_AUTH': ('https://amniss-ai.ru/api/auth', 'Адрес для авторизации', 'char'),
|
||||||
'ENTRYPOINT_DELETE': ('https://amniss-ai.ru/api/v.1/records/delete/%s', 'Адрес для удаления', 'char'),
|
'ENTRYPOINT_DELETE': ('https://amniss-ai.ru/api/v.1/records/delete/%s', 'Адрес для удаления', 'char'),
|
||||||
|
|
@ -163,6 +163,16 @@ CONSTANCE_CONFIG = {
|
||||||
'Access token expired',
|
'Access token expired',
|
||||||
datetime.datetime
|
datetime.datetime
|
||||||
),
|
),
|
||||||
|
'CALL_TIME_START': (
|
||||||
|
datetime.time(9, 30),
|
||||||
|
'Время старта обзвона',
|
||||||
|
datetime.time
|
||||||
|
),
|
||||||
|
'CALL_TIME_END': (
|
||||||
|
datetime.time(18, 30),
|
||||||
|
'Время окончания обзвона',
|
||||||
|
datetime.time
|
||||||
|
),
|
||||||
|
|
||||||
'MEDICINE_TOKEN': ('', 'Токен', 'char'),
|
'MEDICINE_TOKEN': ('', 'Токен', 'char'),
|
||||||
'MEDICINE_HOST': ('http://medicine-app/', 'Хост', 'char'),
|
'MEDICINE_HOST': ('http://medicine-app/', 'Хост', 'char'),
|
||||||
|
|
@ -170,18 +180,19 @@ CONSTANCE_CONFIG = {
|
||||||
|
|
||||||
CONSTANCE_CONFIG_FIELDSETS = (
|
CONSTANCE_CONFIG_FIELDSETS = (
|
||||||
('API', (
|
('API', (
|
||||||
'HOST',
|
'IS_ENABLED',
|
||||||
|
'CALL_TIME_START',
|
||||||
|
'CALL_TIME_END',
|
||||||
|
'SCENARIO_ID',
|
||||||
|
'USERNAME',
|
||||||
|
'PASSWORD',
|
||||||
'ENTRYPOINT_AUTH',
|
'ENTRYPOINT_AUTH',
|
||||||
'ENTRYPOINT_ADD_RECORDS',
|
'ENTRYPOINT_ADD_RECORDS',
|
||||||
'ENTRYPOINT_DELETE',
|
'ENTRYPOINT_DELETE',
|
||||||
'ENTRYPOINT_RECORD',
|
'ENTRYPOINT_RECORD',
|
||||||
'SCENARIO_ID',
|
|
||||||
'USERNAME',
|
|
||||||
'PASSWORD',
|
|
||||||
'IS_ENABLED',
|
|
||||||
'ACCESS_TOKEN',
|
'ACCESS_TOKEN',
|
||||||
|
'REFRESH_TOKEN',
|
||||||
'ACCESS_TOKEN_EXPIRED',
|
'ACCESS_TOKEN_EXPIRED',
|
||||||
'REFRESH_TOKEN'
|
|
||||||
)),
|
)),
|
||||||
('МИС', (
|
('МИС', (
|
||||||
'MEDICINE_HOST',
|
'MEDICINE_HOST',
|
||||||
|
|
@ -191,13 +202,23 @@ CONSTANCE_CONFIG_FIELDSETS = (
|
||||||
|
|
||||||
REQUEST_TIMEOUT = 5
|
REQUEST_TIMEOUT = 5
|
||||||
|
|
||||||
REDIS_CELERY_DB = env.str('REDIS_CELERY_DB', '3')
|
REDIS_CELERY_DB = env.str('REDIS_CELERY_DB', '7')
|
||||||
BROKER_URL = f'redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_CELERY_DB}'
|
BROKER_URL = f'redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_CELERY_DB}'
|
||||||
CELERY_DEFAULT_QUEUE = 'default'
|
CELERY_DEFAULT_QUEUE = 'default'
|
||||||
CELERY_ENABLE_UTC = True
|
CELERY_ENABLE_UTC = True
|
||||||
CELERY_IGNORE_RESULT = True
|
CELERY_IGNORE_RESULT = True
|
||||||
|
|
||||||
CELERYBEAT_SCHEDULE = {
|
CELERYBEAT_SCHEDULE = {
|
||||||
|
'update_call_requests_task': {
|
||||||
|
'task': 'appa.tasks.update_call_requests_task',
|
||||||
|
'schedule': crontab(hour='23', minute='0'),
|
||||||
|
'options': {'queue': CELERY_DEFAULT_QUEUE}
|
||||||
|
},
|
||||||
|
'check_call_requests_task': {
|
||||||
|
'task': 'appa.tasks.check_call_requests_task',
|
||||||
|
'schedule': crontab(minute='*/1'),
|
||||||
|
'options': {'queue': CELERY_DEFAULT_QUEUE}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DATE_FORMAT = 'd.m.Y'
|
DATE_FORMAT = 'd.m.Y'
|
||||||
|
|
@ -206,6 +227,10 @@ DATETIME_FORMAT = 'd.m.Y H:i'
|
||||||
CALL_REQUEST_TIME_START = datetime.time(9, 0)
|
CALL_REQUEST_TIME_START = datetime.time(9, 0)
|
||||||
CALL_REQUEST_TIME_END = datetime.time(21, 0)
|
CALL_REQUEST_TIME_END = datetime.time(21, 0)
|
||||||
|
|
||||||
|
DATABASE_ROUTERS = [
|
||||||
|
'appa.medicine.router.MedicineRouter',
|
||||||
|
]
|
||||||
|
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
AUTH_PASSWORD_VALIDATORS = []
|
AUTH_PASSWORD_VALIDATORS = []
|
||||||
SESSION_COOKIE_NAME = 'dev-medicine-call'
|
SESSION_COOKIE_NAME = 'dev-medicine-call'
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
|
import pytz
|
||||||
import datetime
|
import datetime
|
||||||
import requests
|
|
||||||
from constance import config
|
from constance import config
|
||||||
|
|
||||||
from appa.celery import app
|
from appa.celery import app
|
||||||
from appa.models import *
|
from appa.models import *
|
||||||
from appa.call_api import add_call_request
|
from appa.call_api import api as call_api
|
||||||
|
from appa.medicine_api import api as medicine_api
|
||||||
|
|
||||||
|
|
||||||
@app.task(bind=True, acks_late=True)
|
@app.task(bind=True, acks_late=True)
|
||||||
|
|
@ -24,49 +25,54 @@ def send_call_request_task(self, ids=None):
|
||||||
)
|
)
|
||||||
|
|
||||||
for call_request in call_requests:
|
for call_request in call_requests:
|
||||||
add_call_request(call_request)
|
call_api.add_call_request(call_request)
|
||||||
|
|
||||||
|
|
||||||
@app.task(bind=True, acks_late=True)
|
@app.task(bind=True, acks_late=True)
|
||||||
def update_call_requests(self):
|
def update_call_requests_task(self):
|
||||||
for add_days in [1, 2]:
|
call_lpu = {call_lpu.lpu_id: call_lpu for call_lpu in CallLPU.objects.all()}
|
||||||
booking_date = datetime.date.today() + datetime.timedelta(days=add_days)
|
call_specialities = {medical_speciality.speciality_id: medical_speciality
|
||||||
CallRequest.objects.filter(date=booking_date).delete()
|
for medical_speciality in CallMedicalSpeciality.objects.all()}
|
||||||
|
|
||||||
for page in range(1):
|
now = datetime.datetime.now().astimezone(pytz.timezone('Asia/Vladivostok'))
|
||||||
r = requests.get(
|
bookings = medicine_api.get_bookings(now.date() + datetime.timedelta(days=1))
|
||||||
f'{config.MEDICINE_HOST}api/1/booking/',
|
for booking in bookings:
|
||||||
params={
|
lpu = None
|
||||||
'date_start__date': booking_date.strftime('%d.%m.%Y'),
|
speciality = None
|
||||||
'patient__phone_mobile__isnull': False,
|
if booking['lpu']['code'] in call_lpu:
|
||||||
'patient__isnull': False,
|
lpu = call_lpu[booking['lpu']['code']]
|
||||||
'page': page,
|
|
||||||
'status': 1,
|
|
||||||
'limit': 50
|
|
||||||
},
|
|
||||||
headers={
|
|
||||||
'Authorization': f'Token {config.MEDICINE_TOKEN}'
|
|
||||||
}
|
|
||||||
)
|
|
||||||
if r.status_code == 200:
|
|
||||||
response = r.json()
|
|
||||||
results = response['results']
|
|
||||||
for booking in results:
|
|
||||||
CallRequest.objects.update_or_create(
|
|
||||||
defaults={
|
|
||||||
'date': booking['date'],
|
|
||||||
'patient_id': booking['patient']['id'],
|
|
||||||
'patient_first_name': booking['patient']['first_name'],
|
|
||||||
'patient_last_name': booking['patient']['last_name'],
|
|
||||||
'patient_middle_name': booking['patient']['middle_name'],
|
|
||||||
'patient_phone': '7' + booking['patient']['phone_mobile'],
|
|
||||||
'doctor_name': '',
|
|
||||||
'doctor_speciality': '',
|
|
||||||
'service_name': '',
|
|
||||||
'address': ''
|
|
||||||
},
|
|
||||||
booking_id=booking['id'],
|
|
||||||
)
|
|
||||||
|
|
||||||
if response['next'] is None:
|
if booking['user'] is None:
|
||||||
break
|
continue
|
||||||
|
|
||||||
|
if booking['user']['doctor']['speciality'] in call_specialities:
|
||||||
|
speciality = call_specialities[booking['user']['doctor']['speciality']]
|
||||||
|
|
||||||
|
if lpu is None or speciality is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
CallRequest.objects.update_or_create(
|
||||||
|
defaults=dict(
|
||||||
|
date=datetime.datetime.strptime(booking['date_start'].split('T')[0], '%Y-%m-%d').date(),
|
||||||
|
booking_date=booking['date_start'],
|
||||||
|
patient_id=booking['patient']['id'],
|
||||||
|
patient_first_name=booking['patient']['first_name'],
|
||||||
|
patient_last_name=booking['patient']['last_name'],
|
||||||
|
patient_middle_name=booking['patient']['middle_name'],
|
||||||
|
patient_phone='7' + booking['patient']['phone_mobile'],
|
||||||
|
doctor_name=booking['user']['display'],
|
||||||
|
doctor_speciality=booking['user']['doctor']['speciality_display'],
|
||||||
|
service_name=speciality.name,
|
||||||
|
organization=lpu.name,
|
||||||
|
address=lpu.address,
|
||||||
|
),
|
||||||
|
booking_id=booking['id'],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.task(bind=True, acks_late=True)
|
||||||
|
def check_call_requests_task(self):
|
||||||
|
for call_request in CallRequest.objects.filter(
|
||||||
|
request_status=CallRequest.RequestStatus.SENT
|
||||||
|
):
|
||||||
|
call_api.get_record(call_request)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{% extends "admin/change_form.html" %}
|
||||||
|
|
||||||
|
{% block extrahead %}
|
||||||
|
{{ block.super }}
|
||||||
|
<style>
|
||||||
|
.field-medical_service .related-widget-wrapper select {
|
||||||
|
width: 600px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{% extends "admin/change_form.html" %}
|
||||||
|
|
||||||
|
{% block extrahead %}
|
||||||
|
{{ block.super }}
|
||||||
|
<style>
|
||||||
|
.field-speciality .related-widget-wrapper select {
|
||||||
|
width: 600px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
5
build.sh
5
build.sh
|
|
@ -2,6 +2,5 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
(cd client && npm run build)
|
docker build --platform=linux/amd64 --tag docker.med-logic.ru/medicine-call:latest .
|
||||||
docker build --tag docker.med-logic.ru/medicine-damask:latest .
|
docker push docker.med-logic.ru/medicine-call:latest
|
||||||
docker push docker.med-logic.ru/medicine-damask:latest
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ docker run --rm \
|
||||||
--master \
|
--master \
|
||||||
--py-autoreload 1 \
|
--py-autoreload 1 \
|
||||||
--disable-write-exception \
|
--disable-write-exception \
|
||||||
|
--disable-logging \
|
||||||
--buffer-size 32768 \
|
--buffer-size 32768 \
|
||||||
--http-timeout 30 \
|
--http-timeout 30 \
|
||||||
--check-static /app/
|
--check-static /app/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue