This commit is contained in:
0
src/apps/tdn/__init__.py
Normal file
0
src/apps/tdn/__init__.py
Normal file
15
src/apps/tdn/auth.py
Normal file
15
src/apps/tdn/auth.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
from clients import clients as c
|
||||||
|
from shared.redis import client as cache
|
||||||
|
|
||||||
|
|
||||||
|
async def token():
|
||||||
|
access_token = cache.get('tdn_token')
|
||||||
|
|
||||||
|
if access_token is None:
|
||||||
|
tokens = await c.tdn_api.signin()
|
||||||
|
cache.set('tdn_token', tokens.accessToken, 60)
|
||||||
|
|
||||||
|
return tokens.accessToken
|
||||||
|
|
||||||
|
else:
|
||||||
|
return access_token.decode()
|
||||||
@ -17,4 +17,4 @@ async def login(
|
|||||||
if is_exist is None:
|
if is_exist is None:
|
||||||
raise e.UnauthorizedException
|
raise e.UnauthorizedException
|
||||||
|
|
||||||
return True
|
return is_exist.decode()
|
||||||
|
|||||||
@ -59,7 +59,7 @@ async def get_entries():
|
|||||||
Get list of entries for user by id.
|
Get list of entries for user by id.
|
||||||
"""
|
"""
|
||||||
return await c.vitacore_api.getEntries(
|
return await c.vitacore_api.getEntries(
|
||||||
'b172ddc1-bd94-407f-885f-725193dcc502'
|
'6c7978f0-c573-4ccf-8c6e-f0cd9aceb1e1'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -170,6 +170,24 @@ async def get_pat_flg():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# @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
|
||||||
|
|
||||||
|
|
||||||
@router.post('/measurement', status_code=status.HTTP_202_ACCEPTED)
|
@router.post('/measurement', status_code=status.HTTP_202_ACCEPTED)
|
||||||
async def measurement(
|
async def measurement(
|
||||||
user: Annotated[str, Depends(login)],
|
user: Annotated[str, Depends(login)],
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
from .esia.api import ESIA_API
|
from .esia.api import ESIA_API
|
||||||
|
from .tdn.api import TDN_API
|
||||||
from .vitacore.api import VITACORE_API
|
from .vitacore.api import VITACORE_API
|
||||||
|
|
||||||
|
|
||||||
class ClientsObject:
|
class ClientsObject:
|
||||||
_esia_api = None
|
_esia_api = None
|
||||||
_vitacore_api = None
|
_vitacore_api = None
|
||||||
|
_tdn_api = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def esia_api(self):
|
def esia_api(self):
|
||||||
@ -20,5 +22,12 @@ class ClientsObject:
|
|||||||
|
|
||||||
return self._vitacore_api
|
return self._vitacore_api
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tdn_api(self):
|
||||||
|
if not self._tdn_api:
|
||||||
|
self._tdn_api = TDN_API()
|
||||||
|
|
||||||
|
return self._tdn_api
|
||||||
|
|
||||||
|
|
||||||
clients = ClientsObject()
|
clients = ClientsObject()
|
||||||
|
|||||||
0
src/clients/tdn/__init__.py
Normal file
0
src/clients/tdn/__init__.py
Normal file
106
src/clients/tdn/api.py
Normal file
106
src/clients/tdn/api.py
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
from json import dumps
|
||||||
|
from logging import getLogger
|
||||||
|
from urllib.parse import quote, urlencode
|
||||||
|
|
||||||
|
from fastapi import status as st
|
||||||
|
from httpx import AsyncClient
|
||||||
|
|
||||||
|
from core.config import settings
|
||||||
|
from shared import exceptions as e
|
||||||
|
|
||||||
|
from . import schema as s
|
||||||
|
|
||||||
|
|
||||||
|
class TDN_API(AsyncClient):
|
||||||
|
def __init__(self):
|
||||||
|
self.logger = getLogger(__name__)
|
||||||
|
super().__init__(
|
||||||
|
base_url=settings.TDN_BASE_URL,
|
||||||
|
headers={
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
async def signin(self):
|
||||||
|
data = {
|
||||||
|
'username': settings.TDN_LOGIN,
|
||||||
|
'password': settings.TDN_PASSWORD,
|
||||||
|
}
|
||||||
|
|
||||||
|
res = await self.post('/core/auth/signin', json=data)
|
||||||
|
|
||||||
|
match res.status_code:
|
||||||
|
case st.HTTP_200_OK:
|
||||||
|
return s.SignInModel.model_validate(res.json())
|
||||||
|
case _:
|
||||||
|
self.logger.error(res.json())
|
||||||
|
raise e.UnknownException
|
||||||
|
|
||||||
|
async def patient_search(self, access_token: str, vitaId: str):
|
||||||
|
data = quote(dumps({'vitaId': vitaId}))
|
||||||
|
|
||||||
|
_ = await self.get(
|
||||||
|
'/ddn/patient/search',
|
||||||
|
params={'query': data},
|
||||||
|
headers={'Authorization': f'Bearer {access_token}'},
|
||||||
|
)
|
||||||
|
|
||||||
|
async def observations_search(self, access_token: str, patientUid: str):
|
||||||
|
data = quote(dumps({'where': {'patientUid': patientUid}}))
|
||||||
|
|
||||||
|
res = await self.get(
|
||||||
|
'/ddn/observations/search',
|
||||||
|
params={'query': data},
|
||||||
|
headers={'Authorization': f'Bearer {access_token}'},
|
||||||
|
)
|
||||||
|
|
||||||
|
match res.status_code:
|
||||||
|
case st.HTTP_200_OK:
|
||||||
|
return s.ObservationsModel.model_validate(res.json())
|
||||||
|
case _:
|
||||||
|
self.logger.error(res.json())
|
||||||
|
raise e.UnknownException
|
||||||
|
|
||||||
|
async def observations_measurement_search(
|
||||||
|
self, access_token: str, observationUid: str
|
||||||
|
):
|
||||||
|
# data = urlencode(
|
||||||
|
# dumps(
|
||||||
|
# {
|
||||||
|
# 'where': {'observationUid': observationUid},
|
||||||
|
# 'relations': [
|
||||||
|
# 'measurement',
|
||||||
|
# 'obsrvMtMetrics',
|
||||||
|
# 'obsrvMtMetrics.metric',
|
||||||
|
# ],
|
||||||
|
# }
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
encoded_query = urlencode(
|
||||||
|
{
|
||||||
|
'query': dumps(
|
||||||
|
{
|
||||||
|
'where': {'observationUid': observationUid},
|
||||||
|
'relations': [
|
||||||
|
'measurement',
|
||||||
|
'obsrvMtMetrics',
|
||||||
|
'obsrvMtMetrics.metric',
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
res = await self.get(
|
||||||
|
f'/ddn/observation/obsrv-measurements/search?{encoded_query}',
|
||||||
|
headers={'Authorization': f'Bearer {access_token}'},
|
||||||
|
)
|
||||||
|
|
||||||
|
match res.status_code:
|
||||||
|
case st.HTTP_200_OK:
|
||||||
|
return s.ObservationMeasurementsModel.model_validate(
|
||||||
|
res.json()
|
||||||
|
)
|
||||||
|
case _:
|
||||||
|
self.logger.error(res.json())
|
||||||
|
raise e.UnknownException
|
||||||
80
src/clients/tdn/schema.py
Normal file
80
src/clients/tdn/schema.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class SignInModel(BaseModel):
|
||||||
|
accessToken: str
|
||||||
|
refreshToken: str
|
||||||
|
|
||||||
|
|
||||||
|
class ObservationModel(BaseModel):
|
||||||
|
uid: str
|
||||||
|
createdAt: datetime
|
||||||
|
updatedAt: datetime
|
||||||
|
realmUid: str
|
||||||
|
patientUid: str
|
||||||
|
nosologyUid: str
|
||||||
|
exclusionReasonUid: str | None
|
||||||
|
exclusionComment: str | None
|
||||||
|
exclusionDate: datetime | None
|
||||||
|
employeeUid: str
|
||||||
|
mobileId: str | None
|
||||||
|
|
||||||
|
|
||||||
|
class ObservationsModel(BaseModel):
|
||||||
|
items: list[ObservationModel]
|
||||||
|
total: int
|
||||||
|
|
||||||
|
|
||||||
|
class MeasurementModel(BaseModel):
|
||||||
|
uid: str
|
||||||
|
createdAt: datetime
|
||||||
|
updatedAt: datetime
|
||||||
|
code: str
|
||||||
|
title: str
|
||||||
|
order: int
|
||||||
|
isSelfControl: bool
|
||||||
|
|
||||||
|
|
||||||
|
class MetricModel(BaseModel):
|
||||||
|
uid: str
|
||||||
|
createdAt: datetime
|
||||||
|
updatedAt: datetime
|
||||||
|
code: str
|
||||||
|
title: str
|
||||||
|
order: int
|
||||||
|
shortName: str
|
||||||
|
measureUid: str | None
|
||||||
|
format: str
|
||||||
|
|
||||||
|
|
||||||
|
class ObservationMtMetricModel(BaseModel):
|
||||||
|
uid: str
|
||||||
|
createdAt: datetime
|
||||||
|
updatedAt: datetime
|
||||||
|
obsrvMeasurementUid: str
|
||||||
|
metricUid: str
|
||||||
|
mobileId: str | None
|
||||||
|
metric: MetricModel
|
||||||
|
|
||||||
|
|
||||||
|
class ObservationMeasurementModel(BaseModel):
|
||||||
|
uid: str
|
||||||
|
createdAt: datetime
|
||||||
|
updatedAt: datetime
|
||||||
|
observationUid: str
|
||||||
|
measurementUid: str
|
||||||
|
timeFrequency: int
|
||||||
|
timePeriod: int
|
||||||
|
timePeriodMeasureUid: str
|
||||||
|
timeOfDay: list[str]
|
||||||
|
comment: str | None
|
||||||
|
mobileId: str | None
|
||||||
|
measurement: MeasurementModel
|
||||||
|
obsrvMtMetrics: list[ObservationMtMetricModel]
|
||||||
|
|
||||||
|
|
||||||
|
class ObservationMeasurementsModel(BaseModel):
|
||||||
|
items: list[ObservationMeasurementModel]
|
||||||
|
total: int
|
||||||
@ -266,9 +266,10 @@ class MedExamItemModel(BaseModel):
|
|||||||
title='Наименрование услуги',
|
title='Наименрование услуги',
|
||||||
examples=['Осмотр фельдшером (акушеркой) или врачом акушером'],
|
examples=['Осмотр фельдшером (акушеркой) или врачом акушером'],
|
||||||
)
|
)
|
||||||
SpecialityName: str = Field(
|
SpecialityName: str | None = Field(
|
||||||
title='Специальность',
|
title='Специальность',
|
||||||
examples=['Акушер-гинеколог'],
|
examples=['Акушер-гинеколог'],
|
||||||
|
default=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -360,9 +361,7 @@ class ExaminationModel(BaseModel):
|
|||||||
DateTime: str = Field(
|
DateTime: str = Field(
|
||||||
title='Дата и время создания', examples=['01.08.2025 15:47:15']
|
title='Дата и время создания', examples=['01.08.2025 15:47:15']
|
||||||
)
|
)
|
||||||
Resource: str = Field(
|
Post: str = Field(title='Врач', examples=['Абдуллина Ирина Владимировна'])
|
||||||
title='Врач', examples=['Абдуллина Ирина Владимировна']
|
|
||||||
)
|
|
||||||
Speciality: str = Field(
|
Speciality: str = Field(
|
||||||
title='Специальность врача', examples=['Акушер-гинеколог']
|
title='Специальность врача', examples=['Акушер-гинеколог']
|
||||||
)
|
)
|
||||||
|
|||||||
@ -57,6 +57,11 @@ class Settings(BaseSettings):
|
|||||||
default='https://gist-cws.ezdrav.ru:8899/MP_API'
|
default='https://gist-cws.ezdrav.ru:8899/MP_API'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TDN
|
||||||
|
TDN_BASE_URL: str = Field(default='https://tdn.tatar.ru/api')
|
||||||
|
TDN_LOGIN: str = Field(default='')
|
||||||
|
TDN_PASSWORD: str = Field(default='')
|
||||||
|
|
||||||
@model_validator(mode='after')
|
@model_validator(mode='after')
|
||||||
def celery_env(self):
|
def celery_env(self):
|
||||||
environ['CELERY_BROKER_URL'] = self.REDIS_URL
|
environ['CELERY_BROKER_URL'] = self.REDIS_URL
|
||||||
|
|||||||
Reference in New Issue
Block a user