Патч
All checks were successful
Build And Push / publish (push) Successful in 5m5s

This commit is contained in:
2025-11-11 12:58:58 +03:00
parent b602b75234
commit cf1324633d
9 changed files with 82 additions and 45 deletions

View File

@ -29,6 +29,7 @@ dependencies = [
"pydantic-extra-types==2.10.5", "pydantic-extra-types==2.10.5",
"semver==3.0.4", "semver==3.0.4",
"pyjwt==2.10.1", "pyjwt==2.10.1",
"python-multipart==0.0.20",
# CLI # CLI
"typer-slim==0.16.1", "typer-slim==0.16.1",
] ]

View File

View File

View File

@ -0,0 +1,15 @@
from logging import getLogger
from fastapi import APIRouter
logger = getLogger(__name__)
router = APIRouter(
prefix='/remd',
tags=[
'REMD',
],
)
@router.get('/callback')
async def callback(): ...

View File

@ -3,7 +3,7 @@ from json import dumps
from logging import getLogger from logging import getLogger
from typing import Annotated from typing import Annotated
from fastapi import APIRouter, Body, Depends, status from fastapi import APIRouter, Body, Depends, UploadFile, status
from apps.tdn.auth import token from apps.tdn.auth import token
from apps.users.auth import login from apps.users.auth import login
@ -91,7 +91,7 @@ async def get_routes_list(user: Annotated[User, Depends(login)]):
@router.get('/getHospExaminations') @router.get('/getHospExaminations')
async def get_hosp_examinations( async def get_hosp_examinations(
user: Annotated[User, Depends(login)], examId: str user: Annotated[User, Depends(login)], examId: str | None = None
): ):
""" """
Get list of hospital examinations. Get list of hospital examinations.
@ -178,37 +178,6 @@ async def aemd(user: Annotated[User, Depends(login)]):
) )
# @router.post('/measurement', status_code=status.HTTP_202_ACCEPTED)
# async def measurement(tdn_access_token: Annotated[str, Depends(token)]):
# patientId = '6debe050-b57e-442b-9b0e-8d304ca382b0'
# observations = await c.tdn_api.observations_search(
# tdn_access_token, patientId
# )
# if observations.total == 0:
# raise e.NotFoundException(detail='No observations found')
# observation = observations.items[-1]
# observation_measurements = await
# c.tdn_api.observations_measurement_search(
# tdn_access_token, observation.uid
# )
# return observation_measurements
# created = created_at.strftime('%Y-%m-%d %H:%M:%S')
# data = {
# 'ad': ad,
# 'sd': sd,
# 'pulse': pulse,
# 'created_at': created,
# 'comment': comment,
# 'status': status,
# }
# cache_key = f'tdn:measurement:{user.id}:{created}'
# cache.set(cache_key, dumps(data))
@router.post('/measurement', status_code=status.HTTP_202_ACCEPTED) @router.post('/measurement', status_code=status.HTTP_202_ACCEPTED)
async def measurement( async def measurement(
tdn_access_token: Annotated[str, Depends(token)], tdn_access_token: Annotated[str, Depends(token)],
@ -217,7 +186,9 @@ async def measurement(
sd: Annotated[int, Body()], sd: Annotated[int, Body()],
pulse: Annotated[int, Body()], pulse: Annotated[int, Body()],
comment: Annotated[str, Body()], comment: Annotated[str, Body()],
status: Annotated[str, Body()], status: Annotated[int, Body(ge=1, le=3)],
serial_number: Annotated[str, Body()],
ekg: UploadFile,
): ):
observations = await c.tdn_api.observations_search( observations = await c.tdn_api.observations_search(
tdn_access_token, user.vita_id tdn_access_token, user.vita_id
@ -235,6 +206,7 @@ async def measurement(
dad_measurement = None dad_measurement = None
pulse_measurement = None pulse_measurement = None
health_measurement = None health_measurement = None
health_measurement_created_at = None
observations = observations.items[::-1] observations = observations.items[::-1]
for observation in observations: for observation in observations:
@ -264,8 +236,12 @@ async def measurement(
health_observationUid = measurement.observationUid health_observationUid = measurement.observationUid
for metric in measurement.obsrvMtMetrics: for metric in measurement.obsrvMtMetrics:
if metric.metric.code == 'HEALTH': if metric.metric.code == 'HEALTH' and (
health_measurement_created_at is None
or metric.createdAt > health_measurement_created_at
):
health_measurement = metric.uid health_measurement = metric.uid
health_measurement_created_at = metric.createdAt
if ( if (
not ad_obsrvMeasurementUid not ad_obsrvMeasurementUid
@ -276,6 +252,7 @@ async def measurement(
or not health_obsrvMeasurementUid or not health_obsrvMeasurementUid
or not health_observationUid or not health_observationUid
or not health_measurement or not health_measurement
or not health_measurement_created_at
): ):
ad_obsrvMeasurementUid = None ad_obsrvMeasurementUid = None
sad_measurement = None sad_measurement = None
@ -285,6 +262,7 @@ async def measurement(
health_obsrvMeasurementUid = None health_obsrvMeasurementUid = None
health_observationUid = None health_observationUid = None
health_measurement = None health_measurement = None
health_measurement_created_at = None
else: else:
break break
@ -320,17 +298,17 @@ async def measurement(
# SAD # SAD
await c.tdn_api.create_series_values( await c.tdn_api.create_series_values(
tdn_access_token, ad_series_uid, sad_measurement, nvalue=str(sd) tdn_access_token, ad_series_uid, sad_measurement, nvalue=sd
) )
# DAD # DAD
await c.tdn_api.create_series_values( await c.tdn_api.create_series_values(
tdn_access_token, ad_series_uid, dad_measurement, nvalue=str(ad) tdn_access_token, ad_series_uid, dad_measurement, nvalue=ad
) )
# PULSE # PULSE
await c.tdn_api.create_series_values( await c.tdn_api.create_series_values(
tdn_access_token, ad_series_uid, pulse_measurement, nvalue=str(pulse) tdn_access_token, ad_series_uid, pulse_measurement, nvalue=pulse
) )
health_series = await c.tdn_api.create_series( health_series = await c.tdn_api.create_series(
@ -346,7 +324,16 @@ async def measurement(
tdn_access_token, tdn_access_token,
health_series_uid, health_series_uid,
health_measurement, health_measurement,
svalue=str(comment), nvalue=status,
svalue=comment,
)
# EKG
await c.tdn_api.ekg(
tdn_access_token,
user.vita_id,
serial_number,
ekg,
) )
created = datetime.now(UTC).strftime('%Y-%m-%d %H:%M:%S') created = datetime.now(UTC).strftime('%Y-%m-%d %H:%M:%S')
@ -364,7 +351,9 @@ async def measurement(
@router.get('/measurements') @router.get('/measurements')
async def measurements( async def measurements(
user: Annotated[str, Depends(login)], user: Annotated[User, Depends(login)],
): ):
data = [cache.get(key) for key in cache.keys(f'tdn:measurement:{user}:*')] data = [
cache.get(key) for key in cache.keys(f'tdn:measurement:{user.id}:*')
]
return data return data

View File

@ -3,6 +3,7 @@ from json import dumps
from logging import getLogger from logging import getLogger
from urllib.parse import quote, urlencode from urllib.parse import quote, urlencode
from fastapi import UploadFile
from fastapi import status as st from fastapi import status as st
from httpx import AsyncClient from httpx import AsyncClient
@ -130,11 +131,11 @@ class TDN_API(AsyncClient):
seriesUid: str, seriesUid: str,
obsrvMtMetricUid: str, obsrvMtMetricUid: str,
*, *,
nvalue: str | None = None, nvalue: int | None = None,
fvalue: str | None = None, fvalue: float | None = None,
svalue: str | None = None, svalue: str | None = None,
): ):
data = { data: dict[str, str | int | float] = {
'seriesUid': seriesUid, 'seriesUid': seriesUid,
'obsrvMtMetricUid': obsrvMtMetricUid, 'obsrvMtMetricUid': obsrvMtMetricUid,
} }
@ -160,3 +161,27 @@ class TDN_API(AsyncClient):
case _: case _:
self.logger.error(res.json()) self.logger.error(res.json())
raise e.UnknownException raise e.UnknownException
async def ekg(
self,
access_token: str,
patientUid: str,
serial_number: str,
file: UploadFile,
):
req = await self.post(
'/ddn/observation/series-values/ecg/krb02',
headers={'Authorization': f'Bearer {access_token}'},
files={'ekg': (file.filename, file.file, file.content_type)},
json={
'patientUid': patientUid,
'serialNumber': serial_number,
},
)
match req.status_code:
case st.HTTP_200_OK:
return s.EkgModel.model_validate(req.json())
case _:
self.logger.error(req.json())
raise e.UnknownException

View File

@ -108,3 +108,8 @@ class SeriesValueModel(BaseModel):
filepath: str | None filepath: str | None
mobileId: str | None mobileId: str | None
tisId: str | None tisId: str | None
class EkgModel(BaseModel):
success: bool
# result: ...

View File

@ -199,7 +199,7 @@ class VITACORE_API(AsyncClient):
self.logger.error(req.json()) self.logger.error(req.json())
raise e.UnknownException raise e.UnknownException
async def getHospExaminations(self, patId: str, examId: str): async def getHospExaminations(self, patId: str, examId: str | None = None):
patId = 'b66a85f1-4aaa-4db8-942a-2de44341824e' patId = 'b66a85f1-4aaa-4db8-942a-2de44341824e'
token = await self.get_token() token = await self.get_token()
req = await self.get( req = await self.get(

View File

@ -1,6 +1,7 @@
from fastapi import APIRouter, HTTPException from fastapi import APIRouter, HTTPException
from apps.esia.v1.router import router as esia_router from apps.esia.v1.router import router as esia_router
from apps.remd.v1.router import router as remd_router
from apps.users.v1.router import router as users_router from apps.users.v1.router import router as users_router
from . import get_openapi_schema, get_swagger_html from . import get_openapi_schema, get_swagger_html
@ -9,6 +10,7 @@ router = APIRouter(prefix='/v1')
router.include_router(esia_router) router.include_router(esia_router)
router.include_router(users_router) router.include_router(users_router)
router.include_router(remd_router)
openapi_schema = get_openapi_schema(router) openapi_schema = get_openapi_schema(router)
swagger_ui_html = get_swagger_html(router) swagger_ui_html = get_swagger_html(router)