Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/new endpoint userdatasource #14

Merged
merged 4 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions api/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from app import config
from app.db import TORTOISE_ORM
from app.routers import auth, entities, entities_raw, entities_std, users
from app.routers import auth, entities_mrg, entities_raw, entities_std, entities

logger.remove()
logger.add(sys.stdout, level=config.LOG_LEVEL)
Expand Down Expand Up @@ -44,9 +44,10 @@

app.include_router(entities_raw.router)
app.include_router(entities_std.router)
app.include_router(entities_mrg.router)
app.include_router(entities.router)
app.include_router(auth.router)
app.include_router(users.router)
# app.include_router(users.router)

register_tortoise(
app,
Expand Down
10 changes: 4 additions & 6 deletions api/app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class RawPatientRecord(Model):
id = fields.UUIDField(pk=True)
patient_cpf = fields.CharField(max_length=11)
data = fields.JSONField()
data_source = fields.ForeignKeyField("app.DataSource", related_name="raw_record_data_source")
creator = fields.ForeignKeyField("app.User", related_name="raw_record_creator", null=False)

created_at = fields.DatetimeField(auto_now_add=True)
updated_at = fields.DatetimeField(auto_now=True)
Expand All @@ -23,7 +23,7 @@ class RawPatientCondition(Model):
id = fields.UUIDField(pk=True)
patient_cpf = fields.CharField(max_length=11)
data = fields.JSONField()
data_source = fields.ForeignKeyField("app.DataSource", related_name="raw_condition_data_source")
creator = fields.ForeignKeyField("app.User", related_name="raw_condition_creator", null=False)

created_at = fields.DatetimeField(auto_now_add=True)
updated_at = fields.DatetimeField(auto_now=True)
Expand All @@ -46,11 +46,10 @@ class StandardizedPatientRecord(Model):
father_name = fields.CharField(max_length=512, null=True)
mother_name = fields.CharField(max_length=512, null=True)
name = fields.CharField(max_length=512)
naturalization = fields.CharField(max_length=32, null=True)
race = fields.CharEnumField(enum_type=RaceEnum)
gender = fields.CharEnumField(enum_type=GenderEnum)
nationality = fields.CharEnumField(enum_type=NationalityEnum)
raw_source = fields.ForeignKeyField("app.RawPatientRecord", related_name="std_record_raw")
raw_source = fields.ForeignKeyField("app.RawPatientRecord", related_name="std_record_raw", null=False)
cns_list = fields.JSONField(null=True)
address_list = fields.JSONField(null=True)
telecom_list = fields.JSONField(null=True)
Expand All @@ -69,7 +68,7 @@ class StandardizedPatientCondition(Model):
clinical_status = fields.CharEnumField(enum_type=ClinicalStatusEnum, max_length=32)
category = fields.CharEnumField(enum_type=CategoryEnum, max_length=32)
date = fields.DatetimeField()
raw_source = fields.ForeignKeyField("app.RawPatientCondition", related_name="std_condition_raw")
raw_source = fields.ForeignKeyField("app.RawPatientCondition", related_name="std_condition_raw", null=False)
created_at = fields.DatetimeField(auto_now_add=True)
updated_at = fields.DatetimeField(auto_now=True)

Expand Down Expand Up @@ -170,7 +169,6 @@ class Patient(Model):
father_name = fields.CharField(max_length=512, null=True)
mother_name = fields.CharField(max_length=512, null=True)
name = fields.CharField(max_length=512)
naturalization = fields.CharField(max_length=512, null=True)
race = fields.ForeignKeyField("app.Race", related_name="patient_race")
gender = fields.ForeignKeyField("app.Gender", related_name="patient_gender")
nationality = fields.ForeignKeyField("app.Nationality", related_name="patient_nationality")
Expand Down
27 changes: 22 additions & 5 deletions api/app/pydantic_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,26 @@ class TelecomModel(BaseModel):
period_end: Optional[date]


class DataSourceModel(BaseModel):
system: str
cnes: str
description: str


class UserRegisterInputModel(BaseModel):
username: str
password: str
email: str
is_superuser: bool
data_source: DataSourceModel


class UserRegisterOutputModel(BaseModel):
username: str
is_superuser: bool
data_source: DataSourceModel


class CnsModel(BaseModel):
value: str
is_main: bool
Expand Down Expand Up @@ -61,12 +81,11 @@ class PatientModel(BaseModel):
patient_cpf: str
deceased: Optional[bool]
deceased_date: Optional[date]
father: Optional[str]
father_name: Optional[str]
gender: str
mother: Optional[str]
mother_name: Optional[str]
name: str
nationality: Optional[str]
naturalization: Optional[str]
protected_person: Optional[bool]
race: Optional[str]
cns_list: List[CnsModel]
Expand All @@ -92,7 +111,6 @@ class CompletePatientModel(BaseModel):
father_name: Optional[str]
mother_name: Optional[str]
nationality: Optional[str]
naturalization: Optional[str]
protected_person: Optional[bool]
race: Optional[str]

Expand Down Expand Up @@ -132,7 +150,6 @@ class StandardizedPatientRecordModel(BaseModel):
mother_name: Optional[str]
name: str
nationality: Optional[str]
naturalization: Optional[str]
protected_person: Optional[bool]
race: Optional[str]
cns_list: Optional[List[CnsModel]]
Expand Down
174 changes: 27 additions & 147 deletions api/app/routers/entities.py
Original file line number Diff line number Diff line change
@@ -1,167 +1,47 @@
# -*- coding: utf-8 -*-
from typing import Annotated

from fastapi import APIRouter, Depends, HTTPException
from fastapi import APIRouter, Depends
from tortoise.contrib.pydantic import pydantic_model_creator

from app.dependencies import get_current_active_user
from app.pydantic_models import PatientModel, PatientConditionListModel, CompletePatientModel
from app.pydantic_models import UserRegisterInputModel, UserRegisterOutputModel
from app.utils import password_hash
from app.models import (
User, Patient, City, Race, Gender, Nationality, Address,
Telecom, PatientCondition, ConditionCode
User, DataSource
)

PatientOutput = pydantic_model_creator(Patient, name="PatientOutput")
PatientConditionOutput = pydantic_model_creator(PatientCondition, name="PatientConditionOutput")
DataSourceInput = pydantic_model_creator(DataSource, name="DataSourceInput", exclude=("id",))
DataSourceOutput = pydantic_model_creator(DataSource, name="DataSourceOutput")


router = APIRouter(prefix="/mrg", tags=["Entidades MRG (Formato Merged/Fundido)"])
router = APIRouter(prefix="/outros", tags=["Outras Entidades"])


@router.put("/patient", response_model=PatientOutput, status_code=200)
async def create_or_update_patient(
@router.post("/user", response_model=UserRegisterOutputModel, status_code=200)
async def create_user(
_: Annotated[User, Depends(get_current_active_user)],
patient: PatientModel,
) -> PatientOutput:
patient_data = patient.dict()

birth_city = await City.get_or_none(
code = patient_data['birth_city'],
state__code = patient_data['birth_state'],
state__country__code = patient_data['birth_country']
user: UserRegisterInputModel,
) -> UserRegisterOutputModel:
user_data = user.dict()
datasource_data = user_data.pop('data_source')

datasource_instance, _ = await DataSource.get_or_create(
system = datasource_data['system'],
cnes = datasource_data['cnes'],
description = datasource_data['description']
)
new_data = {
'patient_cpf' : patient_data.get('patient_cpf'),
'birth_date' : patient_data.get('birth_date'),
'active' : patient_data.get('active'),
'protected_person' : patient_data.get('protected_person'),
'deceased' : patient_data.get('deceased'),
'deceased_date' : patient_data.get('deceased_date'),
'name' : patient_data.get('name'),
'mother_name' : patient_data.get('mother'),
'father_name' : patient_data.get('father'),
'naturalization' : patient_data.get('naturalization'),
'birth_city' : birth_city,
'race' : await Race.get_or_none(slug = patient_data['race']),
'gender' : await Gender.get_or_none(slug = patient_data['gender']),
'nationality' : await Nationality.get_or_none(slug = patient_data['nationality']),
}

patient = await Patient.get_or_none(
patient_cpf = patient_data.get('patient_cpf')
).prefetch_related('address_patient_periods','telecom_patient_periods')

if patient is not None:
await patient.update_from_dict(new_data).save()
else:
patient = await Patient.create(**new_data)

# Reset de Address
for instance in patient.address_patient_periods.related_objects:
await instance.delete()
for address in patient_data.get("address_list"):
address_city = await City.get_or_none(
code = address['city'],
state__code = address['state'],
state__country__code = address['country']
)
address['patient'] = patient
address['city'] = address_city
await Address.create(**address)

# Reset de Telecom
for instance in patient.telecom_patient_periods.related_objects:
await instance.delete()
for telecom in patient_data.get("telecom_list"):
telecom['patient'] = patient
await Telecom.create(**telecom)

return await PatientOutput.from_tortoise_orm(patient)


@router.put("/patientcondition", response_model=list[PatientConditionOutput], status_code=200)
async def create_or_update_patientcondition(
_: Annotated[User, Depends(get_current_active_user)],
patientcondition: PatientConditionListModel,
) -> list[PatientConditionOutput]:
patient_data = patientcondition.dict()

patient = await Patient.get_or_none(
patient_cpf=patient_data.get('patient_cpf')
).prefetch_related('patientconditions')

if patient is None:
raise HTTPException(status_code=400, detail="Patient don't exist")
user_data['password'] = password_hash(user_data['password'])
user_data['data_source'] = datasource_instance

# Reset Patient Conditions
for instance in patient.patientconditions.related_objects:
await instance.delete()

conditions = []
for condition in patient_data.get('conditions'):
condition_code = await ConditionCode.get_or_none(
value=condition.get('code')
)
if condition_code is None:
raise HTTPException(
status_code=400,
detail=f"Condition Code {condition.get('code')} don't exist"
)
condition['patient'] = patient
condition['condition_code'] = condition_code
new_condition = await PatientCondition.create(**condition)
conditions.append(new_condition)

return conditions

@router.get("/patient/{patient_cpf}", response_model=CompletePatientModel)
async def get_patient(
patient_cpf : int,
_: Annotated[User, Depends(get_current_active_user)],
) -> list[CompletePatientModel]:

patient = await Patient.get_or_none(patient_cpf=patient_cpf).prefetch_related(
'race','nationality','gender','cnss',
'birth_city__state__country',
'telecom_patient_periods',
'address_patient_periods__city__state__country',
'patientconditions__condition_code',
user_instance = await User.create(
**user_data
)

address_list = []
for address in patient.address_patient_periods.related_objects:
address_data = dict(address)
address_data['city'] = address.city.code
address_data['state'] = address.city.state.code
address_data['country'] = address.city.state.country.code
address_list.append(address_data)

telecom_list = []
for telecom in patient.telecom_patient_periods.related_objects:
telecom_data = dict(telecom)
telecom_list.append(telecom_data)

condition_list = []
for condition in patient.patientconditions.related_objects:
condition_data = dict(condition)
condition_data['code'] = condition.condition_code.value
condition_list.append(condition_data)

cns_list = []
for cns in patient.cnss.related_objects:
cns_data = dict(cns)
cns_list.append(cns_data)

patient_data = dict(patient)
patient_data['gender'] = patient.gender.slug
patient_data['nationality'] = patient.nationality.slug
patient_data['race'] = patient.race.slug
patient_data['birth_city'] = patient.birth_city.code
patient_data['birth_state'] = patient.birth_city.state.code
patient_data['birth_country'] = patient.birth_city.state.country.code
patient_data['address_list'] = address_list
patient_data['telecom_list'] = telecom_list
patient_data['condition_list'] = condition_list
patient_data['cns_list'] = cns_list
output = {
**dict(user_instance),
'data_source': dict(datasource_instance)
}

return patient_data
return output
Loading
Loading