diff --git a/ TODOs b/ TODOs new file mode 100644 index 0000000..2dedbc0 --- /dev/null +++ b/ TODOs @@ -0,0 +1 @@ +Удален requests \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index b0e3b32..97dae95 100644 --- a/requirements.txt +++ b/requirements.txt @@ -34,5 +34,4 @@ tomli==2.0.1 typing_extensions==4.5.0 uvicorn==0.22.0 wheel==0.40.0 -zipp==3.15.0 -requests==2.31.0 \ No newline at end of file +zipp==3.15.0 \ No newline at end of file diff --git a/src/medical_info/db/schemas/__init__.py b/src/medical_info/db/schemas/__init__.py index c8cbafb..3fa05ca 100644 --- a/src/medical_info/db/schemas/__init__.py +++ b/src/medical_info/db/schemas/__init__.py @@ -1,2 +1,3 @@ from .medical_card import * -from .checkup import * \ No newline at end of file +from .checkup import * +from .persons import * \ No newline at end of file diff --git a/src/medical_info/db/schemas/medical_card.py b/src/medical_info/db/schemas/medical_card.py index 722f668..2571f1f 100644 --- a/src/medical_info/db/schemas/medical_card.py +++ b/src/medical_info/db/schemas/medical_card.py @@ -2,17 +2,13 @@ from pydantic import BaseModel from pydantic.types import UUID4, Json from typing import List, Optional, Any from datetime import date, datetime +from .persons import PersonOut -class Person(BaseModel): - first_name: str - last_name: str - patronymic: Optional[str] - birth_date: Optional[date] class MedicalCardResponse(BaseModel): id: UUID4 number: Optional[str] person_id: UUID4 - person: Person + person: PersonOut created_at: Optional[datetime] @@ -27,43 +23,13 @@ class MedicalCardBase(BaseModel): class Config: orm_mode = True -class PersonAddress(BaseModel): - category: str - region: Optional[str] - city: Optional[str] - street: Optional[str] - house: Optional[str] - flat: Optional[str] - -class PersonContact(BaseModel): - category: str - value: str - -class PersonDocument(BaseModel): - category: str - series: str - number: str - issued_by: str - issued_at: Optional[date] - attachments: Optional[List[str]] - -class PersonDetail(BaseModel): - first_name: str - last_name: str - patronymic: Optional[str] - gender: Optional[str] - birth_date: Optional[date] - addresses: Optional[List[PersonAddress]] = [] - contacts: Optional[List[PersonContact]] = [] - documents: Optional[List[PersonDocument]] = [] - photos: Optional[List[str]] = [] class MedicalCardDetail(BaseModel): id: UUID4 number: str created_at: datetime person_id: UUID4 - person: Optional[PersonDetail] + person: Optional[PersonOut] class Config: orm_mode = True @@ -91,5 +57,14 @@ class MedicalCardUpdateRs(BaseModel): number: str created_at: datetime person_id: UUID4 + class Config: + orm_mode = True + +class MedicalCardOut(BaseModel): + id: UUID4 + number: str + created_at: datetime + person_id: UUID4 + person: Optional[PersonOut] class Config: orm_mode = True \ No newline at end of file diff --git a/src/medical_info/db/schemas/persons.py b/src/medical_info/db/schemas/persons.py new file mode 100644 index 0000000..6345a39 --- /dev/null +++ b/src/medical_info/db/schemas/persons.py @@ -0,0 +1,38 @@ +from pydantic import BaseModel +from typing import Optional, List +from datetime import date + +class Address(BaseModel): + category: str + region: str | None + city: str | None + street: str | None + house: str | None + flat: str | None + +class Contact(BaseModel): + category: str + value: str + +class Document(BaseModel): + category: str + series: str + number: str + issued_by: str + issued_at: date | None + attachments: Optional[List[str]] + +class PersonOut(BaseModel): + id: str + first_name: str + last_name: str + patronymic: str | None + gender: str | None + birth_date: date | None + addresses: Optional[List[Address]] = [] + contacts: Optional[List[Contact]] = [] + documents: Optional[List[Document]] = [] + photos: Optional[List[str]] = [] + + + \ No newline at end of file diff --git a/src/medical_info/routers/medical_cards.py b/src/medical_info/routers/medical_cards.py index 9777102..36b48ee 100644 --- a/src/medical_info/routers/medical_cards.py +++ b/src/medical_info/routers/medical_cards.py @@ -3,12 +3,14 @@ from fastapi.routing import APIRouter from typing import List, Optional from pydantic.types import UUID4 from medical_info.db import models, schemas -from medical_info.db.schemas import MedicalCardResponse, MedicalCardCreate, MedicalCardBase,MedicalCardDetail, MedicalCardUpdateRq +from medical_info.db.schemas import ( + MedicalCardOut, + MedicalCardResponse, MedicalCardCreate, MedicalCardBase,MedicalCardDetail, MedicalCardUpdateRq) from medical_info.services import MedicalCardService, get_medical_cards_service router = APIRouter(prefix='/medical_cards') -@router.get('/', response_model=List[MedicalCardResponse]) +@router.get('/', response_model=List[MedicalCardOut]) def list_medical_cards( searchstring: str = '', medical_cards_service: MedicalCardService = Depends(get_medical_cards_service) diff --git a/src/medical_info/services/medical_cards.py b/src/medical_info/services/medical_cards.py index 701aa85..c19063c 100644 --- a/src/medical_info/services/medical_cards.py +++ b/src/medical_info/services/medical_cards.py @@ -1,49 +1,57 @@ from typing import Any, List, Optional from medical_info.db.models import MedicalCard -from medical_info.db.schemas import MedicalCardCreate, MedicalCardBase, MedicalCardResponse, PersonDetail, MedicalCardDetail +from medical_info.db.schemas import ( + PersonOut, + MedicalCardOut, + MedicalCardCreate, MedicalCardBase, MedicalCardResponse, MedicalCardDetail) from medical_info.services.base import BaseService from sqlalchemy.orm import Session from pydantic import parse_obj_as from pydantic.types import UUID4 from medical_info.db import schemas, models -import requests from starlette.exceptions import HTTPException +import os +import httpx class MedicalCardService(BaseService[MedicalCard, MedicalCardCreate, Any]): def __init__(self, db_session: Session): super(MedicalCardService, self).__init__(MedicalCard, db_session) + LOCAL_PERSONAL_INFO_URL = 'http://localhost:8001/persons' + self.PERSONAL_INFO_URL = os.environ.get('ASTRA-PESONAL-INFORMATION') or LOCAL_PERSONAL_INFO_URL - def list(self, searchstring: str) -> Any: - #TODO установи корректные коды ошибки - if searchstring is None or searchstring == '': - raise HTTPException(status_code=404, detail='searchstring is required') + def get_persons(self, searchstring: str) -> List[PersonOut]: - personal_information_host = os.getenv('ASTRA-PESONAL-INFORMATION') - # personal_information_host = 'http://localhost:8001/persons' - #TODO обобщение хоста personal_info - #TODO обработка ошибок ответа сервиса personal_info + try: + response = httpx.get(f'{self.PERSONAL_INFO_URL}/?full_name={searchstring}') + response.raise_for_status() + except httpx.RequestError as exc: + print(f"Ошибка вызова {exc.request.url!r}.") + raise HTTPException(status_code=500, detail=f"Ошибка вызова {exc.request.url!r}.") + except httpx.HTTPStatusError as exc: + print(f"Ошибка {exc.response.status_code} при запросе {exc.request.url!r}.") + raise HTTPException(status_code=exc.response.status_code, detail=f"Ошибка вызова {exc.request.url!r}.") - person_response = requests.get(f'{personal_information_host}/?full_name={searchstring}') + return parse_obj_as(List[schemas.PersonOut], response.json()) - persons = person_response.json() - person_ids = [person['id'] for person in persons] + def list(self, searchstring: str) -> Any: + if searchstring is None or searchstring == '': + raise HTTPException(status_code=409, detail='searchstring is required') + + persons = self.get_persons(searchstring) + person_ids = [person.id for person in persons] if len(person_ids) < 1: return [] - objs = self.db_session.query(models.MedicalCard).filter(models.MedicalCard.person_id.in_(person_ids)).all() - medical_cards = parse_obj_as(List[schemas.MedicalCard], objs) - medical_cards = [medical_card.dict() for medical_card in medical_cards] + medical_card_objs = self.db_session.query(models.MedicalCard).filter(models.MedicalCard.person_id.in_(person_ids)).all() + medical_cards = parse_obj_as(List[MedicalCardOut], medical_card_objs) - - res = list() - for m in medical_cards: - - person = next(filter(lambda person: str(person["id"]) == str(m["person_id"]) , persons), None) - if person is not None: - m['person'] = {**person} - res.append(m) - return res + for mc in medical_cards: + for p in persons: + if str(mc.person_id) == str(p.id): + mc.person = p + + return medical_cards def get(self, id: UUID4) -> Optional[schemas.MedicalCardDetail]: obj: Optional[models.MedicalCard] = self.db_session.get(self.model, id) @@ -51,7 +59,7 @@ class MedicalCardService(BaseService[MedicalCard, MedicalCardCreate, Any]): raise HTTPException(status_code=404, detail='NotFound') personal_information_host = os.getenv('ASTRA-PESONAL-INFORMATION') - # personal_information_host = 'http://localhost:8001/persons' + #personal_information_host = 'http://localhost:8001/persons' #TODO обработка ошибок ответа сервиса personal_info