release 1.1

This commit is contained in:
2026-02-22 09:42:44 +03:00
parent be6cfe2284
commit 651631b3c7
35 changed files with 944 additions and 278 deletions
+231 -71
View File
@@ -1,5 +1,6 @@
from pathlib import Path
from fastapi import APIRouter, Depends, HTTPException
from api.medods import findPatientByPhone
from api.n3health import resend, revoke, sendForSigning
from db.schemas.documents import Document
from db.schemas.patients import Patient
@@ -37,9 +38,13 @@ async def pre_singing(
signature["expiration"] = practitioner.data.get("expired_at")[:10]
daysRemainingControl = 0
deliveryType = None
settings = await Settings.getSettings()
if settings.success:
daysRemainingControl = settings.data.get("expirationAlert", 0)
deliveryData = settings.data.get("deliveryType", {})
deliveryType = [k for k, v in deliveryData.items() if v]
multipleSending = settings.data.get("multipleSending", False)
inProgress = []
complete = []
@@ -75,6 +80,8 @@ async def pre_singing(
"inProgress": inProgress,
"complete": complete,
"daysRemainingControl": daysRemainingControl,
"deliveryType": deliveryType,
"multipleSending": multipleSending,
}
return exitData
@@ -85,8 +92,9 @@ async def singing(
):
def correctData(data):
data["practitioner"]["userIdLpu"] = str(data["practitioner"]["userIdLpu"])
for patient in data["patients"]:
patient["idPatientMis"] = str(patient["idPatientMis"])
data["patient"]["idPatientMis"] = str(data["patient"]["idPatientMis"])
for recipient in data.get("recipients", []):
recipient["idPatientMis"] = str(recipient["idPatientMis"])
return data
logger.info(f"📥 Получен запрос на /singing")
@@ -110,57 +118,109 @@ async def singing(
return {"status": "ERROR", "message": "Сотрудник не найден"}
esiaAuth = practitioner.data.get("esiaAuth", False)
userIdLpu = practitioner.data.get("userIdLpu", 0)
body["practitioner"]["snils"] = practitioner.data.get("snils")
if not esiaAuth:
body["practitioner"]["mrProxyNumber"] = practitioner.data.get("attorney")
patients = body.get("patients", [])
if len(patients) == 0:
patient = body.get("patient", None)
if not patient:
logger.error("Данные пациента не получены, пациент не найден")
return {
"status": "ERROR",
"message": "Данные пациента не получены, пациент не найден",
}
idPatientMis = patient.get("idPatientMis", None)
patientsData = []
if not idPatientMis:
logger.error("Не указан идентификатор пациента")
return {"status": "ERROR", "message": "Не указан идентификатор пациента"}
patientDB = await Patient.getPatientByIdPatientMis(idPatientMis, isCheck=True)
if not patientDB.success:
patientData = {
"idPatientMis": idPatientMis,
"familyName": patient.get("familyName", "N/A"),
"givenName": patient.get("givenName", "N/A"),
"middleName": patient.get("middleName", "N/A"),
"birthDate": patient.get("birthDate", "N/A"),
"sex": patient.get("sex", "N/A"),
}
newPatient = await Patient.addPatient(**patientData)
if not newPatient.success:
return {
"status": "ERROR",
"message": "Не удалось создать пациента",
}
patientData = newPatient.data.toDict()
else:
patientData = patientDB.data
for patient in patients:
idPatientMis = patient.get("idPatientMis", None)
if not idPatientMis:
recipients = body.pop("recipients", [])
recipientsData = []
recipientsIds = []
for recipient in recipients:
idRecipientMis = recipient.get("idPatientMis", None)
if not idRecipientMis:
logger.error("Не указан идентификатор пациента")
return {
"status": "ERROR",
"message": "Не указан идентификатор пациента",
}
patientDB = await Patient.getPatientByIdPatientMis(idPatientMis, isCheck=True)
if not patientDB.success:
patientData = {
"idPatientMis": idPatientMis,
"familyName": patient.get("familyName", "N/A"),
"givenName": patient.get("givenName", "N/A"),
"middleName": patient.get("middleName", "N/A"),
"birthDate": patient.get("birthDate", "N/A"),
"sex": patient.get("sex", "N/A"),
recipientDB = await Patient.getPatientByIdPatientMis(
idRecipientMis, isCheck=True
)
if not recipientDB.success:
recipientData = {
"idPatientMis": idRecipientMis,
"familyName": recipient.get("surname", "N/A"),
"givenName": recipient.get("name", "N/A"),
"middleName": recipient.get("secondName", "N/A"),
"birthDate": recipient.get("birthDate", "N/A"),
"sex": recipient.get("sex", "N/A"),
}
newPatient = await Patient.addPatient(**patientData)
if not newPatient.success:
newRecipient = await Patient.addPatient(**recipientData)
if not newRecipient.success:
return {
"status": "ERROR",
"message": newPatient.message,
"message": newRecipient.message,
}
patientsData.append(newPatient.data.toDict())
recipientsData.append(newRecipient.data.toDict())
recipientsIds.append(newRecipient.data.idPatientMis)
else:
patientsData.append(patientDB.data)
logger.info(recipientDB.data)
recipientsData.append(recipientDB.data)
recipientsIds.append(recipientDB.data.get("idPatientMis"))
recipient["documentDto"] = [
{
"docN": recipient.pop("snils"),
"docS": "",
"documentName": "СНИЛС",
"idDocumentType": 223,
"providerName": "ПФР",
}
]
recipient["telecom"] = [
{
"system": "Telephone",
"value": f'+{recipient.pop("phone")}',
}
]
body["recipients"] = recipients
# Логируем информацию о документах
logger.info(f"👨‍⚕️ Медработник: {practitioner.data.get("name")}")
logger.info(f"👤 Пациент: {patientData.get('name')}")
logger.info(
f"👥 Пациенты ({len(patientsData)}): {', '.join([f'{p.get('name')}' for p in patientsData])}"
f"👥 Получатели ({len(recipientsData)}): {', '.join([f'{p.get('name')}' for p in recipientsData])}"
)
logger.info(f"📄 Документов для обработки: {len(docs)}")
logger.info(f"🔐 ЕСИА: {esiaAuth}")
try:
# Конвертируем документы в PDF
conversion_result = convert_docs_to_pdfs(docs, patientsData)
# logger.info(conversion_result)
conversion_result = convert_docs_to_pdfs(docs, idPatientMis)
if conversion_result.get("status", "") != "SUCCESS":
return {
@@ -168,7 +228,9 @@ async def singing(
"message": "Не удалось сохранить документы",
}
newSinging = await Signing.addSigning(userIdLpu, idPatientMis)
newSinging = await Signing.addSigning(
userIdLpu, idPatientMis, body["deliveryType"], recipientsIds
)
if not newSinging:
return {
"status": "ERROR",
@@ -176,37 +238,41 @@ async def singing(
}
logger.info(f"🔐 Подписание добавлено: {newSinging.id}")
pdfFiles = conversion_result.get("files", {})
pdfFiles = conversion_result.get("files", [])
body["medDocument"] = {
"esiaAuth": esiaAuth,
"attachments": [],
}
body["files"] = []
for key in pdfFiles:
pdfFile = pdfFiles[key]
for doc in pdfFile:
for doc in pdfFiles:
for idPatient in [idPatientMis, *recipientsIds]:
newDocument = await Document.addDocument(
singingId=newSinging.id, idPatientMis=key, **doc
singingId=newSinging.id, idPatientMis=str(idPatient), **doc
)
if not newDocument:
logger.error(
f"Не удалось добавить документ для получателя {idPatient}"
)
return {
"status": "ERROR",
"message": "Не удалось добавить документ",
}
logger.info(f"📄 Документ добавлен: {newDocument.id}")
partName = f'file{len(body["medDocument"]["attachments"])}'
body["medDocument"]["attachments"].append(
{
"partName": partName,
}
)
body["files"].append(
{
"field": partName,
"path": Path(doc["storagePath"]),
"content_type": "application/pdf",
}
logger.debug(
f"📄 Документ добавлен: {newDocument.id} для получателя {idPatient}"
)
partName = f'file{len(body["medDocument"]["attachments"])}'
body["medDocument"]["attachments"].append(
{
"partName": partName,
}
)
body["files"].append(
{
"field": partName,
"path": Path(doc["storagePath"]),
"content_type": "application/pdf",
}
)
if esiaAuth:
partName = f'file{len(body["medDocument"]["attachments"])}'
@@ -234,7 +300,7 @@ async def singing(
newSinging.trackingId = signingResult.get("trackingId", "")
await newSinging.save()
logger.info(
logger.debug(
f"🔐 Подписание обновлено: {newSinging.id}. Добавлен Трек-номер подписания"
)
@@ -242,10 +308,9 @@ async def singing(
logger.info(f"✅ Обработка завершена!")
# Возвращаем ответ
response = {
"status": "SUCCESS",
"message": f"Документы успешно обработаны. Трек-номер подписания: {newSinging.trackingId}",
"message": "Документы успешно обработаны.",
}
return response
@@ -274,6 +339,16 @@ async def statuses(
result = await Signing.getFilteredSingings(userIdLpu, filters)
singingsData = result.data
for singingData in singingsData:
documents = singingData.pop("documents", [])
uniqueDocs = []
uniquePaths = []
for doc in documents:
if doc.get("storagePath") not in uniquePaths:
uniquePaths.append(doc.get("storagePath"))
uniqueDocs.append(doc)
singingData["documents"] = uniqueDocs
return singingsData
@@ -290,7 +365,7 @@ async def documents(
logger.error("Не отправлен idPatientMis")
return {"status": "ERROR", "message": "Не отправлен idPatientMis"}
idPatientMis = body.get("idPatientMis")
idPatientMis = str(body.get("idPatientMis"))
singingData = await Signing.getSigningsByIdPatientMis(idPatientMis)
@@ -308,7 +383,38 @@ async def documents(
for s in singingData.data:
s["practitioner"] = practitioners[s.get("userIdLpu")]
responseData = {"status": "SUCCESS", "data": singingData.data}
for singing in singingData.data:
statusesData = [
{d.get("idPatientMis"): d.get("patient", {}).get("name")}
for d in singing.get("statuses", [])
if d.get("idPatientMis")
]
idMatchName = {}
for statusData in statusesData:
for idPatientMisStatus, name in statusData.items():
if idPatientMisStatus in idMatchName:
continue
idMatchName[idPatientMisStatus] = name
documents = singing.pop("documents")
uniqueDocs = []
for doc in documents:
docOwner = doc.get("storagePath").split("/")[-2:-1][0]
isOwn = docOwner == idPatientMis
if str(doc.get("idPatientMis")) == idPatientMis:
if not isOwn:
ownerName = idMatchName[docOwner]
doc["title"] = (
f"{doc.get('title')} (Пациент: {idMatchName[docOwner]})"
)
uniqueDocs.append(doc)
singing["documents"] = uniqueDocs
settings = await Settings.getSettings(False)
data = {"deliveryType": settings.data.deliveryType, "singings": singingData.data}
responseData = {"status": "SUCCESS", "data": data}
return responseData
@@ -335,6 +441,7 @@ async def revoke_post(
reqData: dict = Depends(requestDict),
):
logger.info(f"📥 Получен запрос на /revoke")
trackingId = reqData.get("body", {}).get("trackingId", None)
if not trackingId:
return {"status": "ERROR", "message": "Документ не найден"}
@@ -359,35 +466,25 @@ async def resend_post(
reqData: dict = Depends(requestDict),
):
logger.info(f"📥 Получен запрос на /resend")
trackingId = reqData.get("body", {}).get("trackingId", None)
idPatientMis = reqData.get("body", {}).get("idPatientMis", None)
deliveryType = reqData.get("body", {}).get("deliveryType", None)
errorResponse = {"status": "ERROR", "message": "Повторная отправка не удалось"}
if not trackingId or not idPatientMis:
logger.error("Не отправлен trackingId или idPatientMis")
logger.error(f"trackingId: {trackingId}, idPatientMis: {idPatientMis}")
if not trackingId or not idPatientMis or not deliveryType:
logger.error("Не отправлен trackingId или idPatientMis или deliveryType")
logger.error(
f"trackingId: {trackingId}, idPatientMis: {idPatientMis}, deliveryType: {deliveryType}"
)
return errorResponse
resendResult = await resend(trackingId, idPatientMis)
resendResult = await resend(trackingId, idPatientMis, deliveryType)
if not resendResult or not resendResult.get("status", ""):
if not resendResult or not resendResult.get("success", False):
logger.error(resendResult)
return errorResponse
newTrackingId = resendResult.get("tracking_id", "")
singingId = reqData.get("body", {}).get("id", "")
if not newTrackingId or not singingId:
logger.error("Не отправлен trackingId или id")
logger.error(f"trackingId: {newTrackingId}, id: {singingId}")
return errorResponse
singing = await Signing.getSigningById(singingId)
if not singing.success:
logger.error(singing.message)
return errorResponse
await singing.data.edit(trackingId=newTrackingId)
logger.info("✅ Повторная отправка успешна")
return {"status": "SUCCESS", "message": resendResult.get("message", "")}
@@ -399,7 +496,70 @@ async def advanced_search_post(
):
logger.info(f"📥 Получен запрос на /advanced-search")
result = await Signing.getFilteredSingings(
"", reqData.get("body", {}).get("filters", {})
)
filters = reqData.get("body", {}).get("filters", {})
result = await Signing.getFilteredSingings("", filters)
for singingData in result.data:
documents = singingData.pop("documents", [])
uniqueDocs = []
uniquePaths = []
for doc in documents:
if doc.get("storagePath") not in uniquePaths:
uniquePaths.append(doc.get("storagePath"))
uniqueDocs.append(doc)
singingData["documents"] = uniqueDocs
return {"status": "SUCCESS", "data": result.data}
@router.post("/search-recipients", summary="search-recipients")
async def search_recipients_post(
reqData: dict = Depends(requestDict),
):
logger.info(f"📥 Получен запрос на /search-recipients")
phoneNumber = "".join(
filter(str.isdigit, reqData.get("body", {}).get("phone", ""))
)[-10:]
idPatientMis = str(reqData.get("body", {}).get("idPatientMis", ""))
settings = await Settings.getSettings(False)
if not settings.success:
logger.error(settings.error)
return {"status": "error", "message": settings.error}
settings = settings.data
try:
patientsDB = await findPatientByPhone(
settings.medodsApiHost,
settings.medodsApiPort,
settings.medodsApiIdentity,
settings.medodsApiSecretKey,
f"7{phoneNumber}",
)
if not patientsDB.success or patientsDB.data.get("totalItems") == 0:
logger.error("Пациент не найден")
return {"status": "error", "data": []}
patients = patientsDB.data.get("data", [])
result = [
{
"idPatientMis": str(patient.get("id")),
"name": patient.get("name"),
"surname": patient.get("surname"),
"secondName": patient.get("secondName"),
"birthDate": patient.get("birthdate"),
"sex": patient.get("sex"),
"snils": patient.get("snils"),
"phone": patient.get("phone"),
}
for patient in patients
if str(patient.get("id")) != idPatientMis
]
return {
"status": "ok",
"data": result,
}
except Exception as e:
logger.error(e)
return {
"status": "error",
"data": [],
}