diff --git a/src/apps/users/v1/router.py b/src/apps/users/v1/router.py index ad57e43..e439984 100644 --- a/src/apps/users/v1/router.py +++ b/src/apps/users/v1/router.py @@ -8,7 +8,8 @@ from fastapi import APIRouter, Body, Depends, status from apps.users.auth import login from apps.users.models import User from clients import clients as c -from clients.vitacore import schema as s +from clients.tmk import schema as ts +from clients.vitacore import schema as vs from shared.redis import client as cache logger = getLogger(__name__) @@ -20,7 +21,7 @@ router = APIRouter( ) -@router.get('/getProfile', response_model=s.ProfileModel) +@router.get('/getProfile', response_model=vs.ProfileModel) async def get_profile(user: Annotated[User, Depends(login)]): """ Get profile of user. @@ -28,7 +29,7 @@ async def get_profile(user: Annotated[User, Depends(login)]): return await c.vitacore_api.getProfile(user.vita_id) -@router.get('/getDepartments', response_model=list[s.OrganizationsModel]) +@router.get('/getDepartments', response_model=list[vs.OrganizationsModel]) async def get_departments(): """ Get list of departments. @@ -36,7 +37,7 @@ async def get_departments(): return await c.vitacore_api.getDepartments() -@router.get('/getWorkers', response_model=s.WorkersModel) +@router.get('/getWorkers', response_model=vs.WorkersModel) async def get_workers( user: Annotated[User, Depends(login)], departmentId: str ): @@ -46,7 +47,7 @@ async def get_workers( return await c.vitacore_api.getWorkers(departmentId) -@router.get('/getSpecs', response_model=s.SpecsV021Model) +@router.get('/getSpecs', response_model=vs.SpecsV021Model) async def get_specs(user: Annotated[User, Depends(login)]): """ Get list of specialties. @@ -54,7 +55,7 @@ async def get_specs(user: Annotated[User, Depends(login)]): return await c.vitacore_api.getSpecsV021() -@router.get('/getEntries', response_model=s.EntriesModel) +@router.get('/getEntries', response_model=vs.EntriesModel) async def get_entries(user: Annotated[User, Depends(login)]): """ Get list of entries for user by id. @@ -155,6 +156,14 @@ async def get_pat_flg(user: Annotated[User, Depends(login)]): return await c.vitacore_api.getPatFLG(user.vita_id) +@router.get('/queue', response_model=list[ts.QueueModel]) +async def queue(_: Annotated[User, Depends(login)]): + """ + Get list of VKS queues. + """ + return await c.tmk_api.getQueue() + + # @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' @@ -206,35 +215,6 @@ async def measurements( return data -@router.get('/test') +@router.get('/aemd/test') async def test_route(): return await c.aemd_api.searchRegistryItem('16247900267') - - -@router.get('/queue') -async def queue(user: Annotated[bool, Depends(login)]): - return [ - { - 'id': 60, - 'guid': '92b3343d-1cb2-47b2-8497-a37e38b6ba24', - 'tmk_date': None, - 'created_at': '2025-04-02 15:21:19.890343', - 'code_mo': '166502', - 'mo_name': 'ГАУЗ "ГКБ№7 ИМ. М.Н.САДЫКОВА"', - 'doctor_spec': '109', - 'doctor_snils': None, - 'patient_name': 'Иванов Петр Федорович', - 'patient_birthday': '1997-03-01', - 'patient_snils': '099-678-666 12', - 'patient_policy': None, - 'patient_phone': '+79123456789', - 'patient_email': None, - 'tmk_status': 1, - 'tmk_status_name': 'Создана', - 'tmk_cancel_reason': None, - 'tmk_cancel_reason_name': None, - 'vks_doctor_link': None, - 'vks_patient_link': None, - 'doctor_spec_name': 'врач-терапевт', - } - ] diff --git a/src/clients/__init__.py b/src/clients/__init__.py index 3e4bd0e..807c1bd 100644 --- a/src/clients/__init__.py +++ b/src/clients/__init__.py @@ -1,6 +1,7 @@ from .aemd.api import AEMD_API from .esia.api import ESIA_API from .tdn.api import TDN_API +from .tmk.api import TMK_API from .vitacore.api import VITACORE_API @@ -8,6 +9,7 @@ class ClientsObject: _esia_api = None _vitacore_api = None _tdn_api = None + _tmk_api = None _aemd_api = None @property @@ -31,6 +33,13 @@ class ClientsObject: return self._tdn_api + @property + def tmk_api(self): + if not self._tmk_api: + self._tmk_api = TMK_API() + + return self._tmk_api + @property def aemd_api(self): if not self._aemd_api: diff --git a/src/clients/tmk/__init__.py b/src/clients/tmk/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/clients/tmk/api.py b/src/clients/tmk/api.py new file mode 100644 index 0000000..5ebf38c --- /dev/null +++ b/src/clients/tmk/api.py @@ -0,0 +1,97 @@ +from datetime import date +from logging import getLogger +from typing import Literal + +from fastapi import status as st +from httpx import AsyncClient + +from core.config import settings +from shared import exceptions as e +from shared.functions import clean_params +from shared.redis import client as cache + +from . import schema as s + + +class TMK_API(AsyncClient): + def __init__(self): + self.logger = getLogger(__name__) + super().__init__( + base_url=settings.TMK_BASE_URL, + ) + + async def get_token(self): + token = cache.get('tmk_token') + + if token is None: + token = await self.login() + cache.set('tmk_token', token, 10800) + + else: + token = token.decode() + + return token + + async def login(self): + req = await self.post( + '/auth', + json={ + 'login': settings.TMK_LOGIN, + 'password': settings.TMK_PASSWORD, + }, + ) + + match req.status_code: + case st.HTTP_200_OK: + return s.AccessTokenModel.model_validate( + req.json() + ).access_token + + case _: + self.logger.error(req.json()) + raise e.UnknownException + + async def getQueue( + self, + code_mo: str | None = None, + doctor_spec: str | None = None, + doctor_snils: str | None = None, + doctor_snils_strict: Literal['y', 'n'] = 'n', + date_begin: date | None = None, + date_end: date | None = None, + patient_snils: str | None = None, + patient_fio: str | None = None, + patient_policy: str | None = None, + patient_phone: str | None = None, + patient_birthdate: date | None = None, + tk_status: str | None = None, + ): + token = await self.get_token() + req = await self.get( + '/getQueue', + headers={'Authorization': f'Bearer {token}'}, + params=clean_params( + { + 'code_mo': code_mo, + 'doctor_spec': doctor_spec, + 'doctor_snils': doctor_snils, + 'doctor_snils_strict': doctor_snils_strict, + 'date_begin': date_begin, + 'date_end': date_end, + 'patient_snils': patient_snils, + 'patient_fio': patient_fio, + 'patient_policy': patient_policy, + 'patient_phone': patient_phone, + 'patient_birthdate': patient_birthdate, + 'tk_status': tk_status, + } + ), + ) + + match req.status_code: + case st.HTTP_200_OK: + return [s.QueueModel.model_validate(i) for i in req.json()] + + case _: + self.logger.error(req.json()) + raise e.UnknownException diff --git a/src/clients/tmk/schema.py b/src/clients/tmk/schema.py new file mode 100644 index 0000000..f91b4d1 --- /dev/null +++ b/src/clients/tmk/schema.py @@ -0,0 +1,31 @@ +from datetime import datetime + +from pydantic import BaseModel + + +class AccessTokenModel(BaseModel): + access_token: str + + +class QueueModel(BaseModel): + id: int + guid: str + created_at: datetime + code_mo: int | None + mo_name: str | None + doctor_spec: str + doctor_snils: str | None + doctor_fio: str | None + patient_name: str | None + patient_birthday: datetime | None + patient_snils: str + patient_policy: str | None + patient_phone: str | None + patient_email: str | None + tmk_status: int + tmk_status_name: str + tmk_cancel_reason: int | None + tmk_cancel_reason_name: str | None + vks_doctor_link: str | None + vks_patient_link: str | None + doctor_spec_name: str | None diff --git a/src/core/config.py b/src/core/config.py index 02f4a7d..55a289b 100644 --- a/src/core/config.py +++ b/src/core/config.py @@ -41,9 +41,6 @@ class Settings(BaseSettings): # Loki Logging LOKI_URL: str | None = Field(default=None) - # Environment - TMK_BASE_URL: str = Field(default='https://tmk-api.tatar.ru/api') - # ESIA ESIA_BASE_URL: str = Field(default='https://esia.gosuslugi.ru') ESIA_CLIENT_ID: str = Field(default='') @@ -70,6 +67,11 @@ class Settings(BaseSettings): TDN_LOGIN: str = Field(default='') TDN_PASSWORD: str = Field(default='') + # TMK + TMK_BASE_URL: str = Field(default='https://tmk-api.tatar.ru/api') + TMK_LOGIN: str = Field(default='admin') + TMK_PASSWORD: str = Field(default='12345') + @model_validator(mode='after') def celery_env(self): environ['CELERY_BROKER_URL'] = self.REDIS_URL diff --git a/src/shared/functions.py b/src/shared/functions.py new file mode 100644 index 0000000..5b27c06 --- /dev/null +++ b/src/shared/functions.py @@ -0,0 +1,5 @@ +from typing import Any + + +def clean_params(data: dict[Any, Any]): + return {k: v for k, v in data.items() if v is not None}