From 8cf4b94d630dcb577dd1dfa2829441b78580ab75 Mon Sep 17 00:00:00 2001 From: Pedro Nascimento Date: Tue, 16 Jan 2024 13:36:09 -0300 Subject: [PATCH 1/4] feat: implemented new endpoint to user and datasource creation --- api/app/main.py | 5 +- api/app/pydantic_models.py | 20 ++++ api/app/routers/entities.py | 172 +++++--------------------------- api/app/routers/entities_mrg.py | 167 +++++++++++++++++++++++++++++++ 4 files changed, 216 insertions(+), 148 deletions(-) create mode 100644 api/app/routers/entities_mrg.py diff --git a/api/app/main.py b/api/app/main.py index f86525b1..d54ae96b 100644 --- a/api/app/main.py +++ b/api/app/main.py @@ -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, users, entities logger.remove() logger.add(sys.stdout, level=config.LOG_LEVEL) @@ -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, diff --git a/api/app/pydantic_models.py b/api/app/pydantic_models.py index e19d6807..1737fc74 100644 --- a/api/app/pydantic_models.py +++ b/api/app/pydantic_models.py @@ -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 diff --git a/api/app/routers/entities.py b/api/app/routers/entities.py index 64516f1a..84cbe474 100644 --- a/api/app/routers/entities.py +++ b/api/app/routers/entities.py @@ -5,163 +5,43 @@ 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 \ No newline at end of file diff --git a/api/app/routers/entities_mrg.py b/api/app/routers/entities_mrg.py new file mode 100644 index 00000000..64516f1a --- /dev/null +++ b/api/app/routers/entities_mrg.py @@ -0,0 +1,167 @@ +# -*- coding: utf-8 -*- +from typing import Annotated + +from fastapi import APIRouter, Depends, HTTPException +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.models import ( + User, Patient, City, Race, Gender, Nationality, Address, + Telecom, PatientCondition, ConditionCode +) + +PatientOutput = pydantic_model_creator(Patient, name="PatientOutput") +PatientConditionOutput = pydantic_model_creator(PatientCondition, name="PatientConditionOutput") + + +router = APIRouter(prefix="/mrg", tags=["Entidades MRG (Formato Merged/Fundido)"]) + + +@router.put("/patient", response_model=PatientOutput, status_code=200) +async def create_or_update_patient( + _: 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'] + ) + 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") + + # 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', + ) + + 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 + + return patient_data From f206ed49911cc9fa006b084c4c45abdb687b03af Mon Sep 17 00:00:00 2001 From: Pedro Nascimento Date: Tue, 16 Jan 2024 13:59:17 -0300 Subject: [PATCH 2/4] fix: father and mother's name typo --- api/app/models.py | 8 +- api/app/pydantic_models.py | 4 +- api/app/routers/entities_mrg.py | 4 +- api/app/routers/entities_raw.py | 12 +- ...94530_init.py => 0_20240116134526_init.py} | 118 +++++++++--------- 5 files changed, 71 insertions(+), 75 deletions(-) rename api/migrations/app/{0_20240116094530_init.py => 0_20240116134526_init.py} (97%) diff --git a/api/app/models.py b/api/app/models.py index 84f51238..2d5b2c90 100644 --- a/api/app/models.py +++ b/api/app/models.py @@ -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) @@ -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) @@ -50,7 +50,7 @@ class StandardizedPatientRecord(Model): 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) @@ -69,7 +69,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) diff --git a/api/app/pydantic_models.py b/api/app/pydantic_models.py index 1737fc74..92569d51 100644 --- a/api/app/pydantic_models.py +++ b/api/app/pydantic_models.py @@ -81,9 +81,9 @@ 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] diff --git a/api/app/routers/entities_mrg.py b/api/app/routers/entities_mrg.py index 64516f1a..3657bc2f 100644 --- a/api/app/routers/entities_mrg.py +++ b/api/app/routers/entities_mrg.py @@ -38,8 +38,8 @@ async def create_or_update_patient( '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'), + 'mother_name' : patient_data.get('mother_name'), + 'father_name' : patient_data.get('father_name'), 'naturalization' : patient_data.get('naturalization'), 'birth_city' : birth_city, 'race' : await Race.get_or_none(slug = patient_data['race']), diff --git a/api/app/routers/entities_raw.py b/api/app/routers/entities_raw.py index 0e59a88e..f7201333 100644 --- a/api/app/routers/entities_raw.py +++ b/api/app/routers/entities_raw.py @@ -43,9 +43,8 @@ async def get_raw_patientrecords( created_at__lt=end_date )) - user_data_source = await current_user.data_source return await RawPatientRecordOutput.from_queryset(RawPatientRecord.filter( - data_source=user_data_source, + creator=current_user, created_at__gte=start_date, created_at__lt=end_date )) @@ -56,12 +55,11 @@ async def create_raw_patientrecord( current_user: Annotated[User, Depends(get_current_active_user)], record: RawPatientRecordInput, ) -> RawPatientRecordOutput: - user_datasource = await current_user.data_source record_instance = await RawPatientRecord.create( patient_cpf = record.patient_cpf, data = record.data, - data_source = user_datasource + creator = current_user ) return await RawPatientRecordOutput.from_tortoise_orm(record_instance) @@ -78,9 +76,8 @@ async def get_raw_patientconditions( created_at__lt=end_date )) - user_data_source = await current_user.data_source return await RawPatientConditionOutput.from_queryset(RawPatientCondition.filter( - data_source=user_data_source, + creator=current_user, created_at__gte=start_date, created_at__lt=end_date )) @@ -91,11 +88,10 @@ async def create_raw_patientondition( current_user: Annotated[User, Depends(get_current_active_user)], condition: RawPatientConditionInput, ) -> RawPatientConditionOutput: - user_datasource = await current_user.data_source condition_instance = await RawPatientCondition.create( patient_cpf = condition.patient_cpf, data = condition.data, - data_source = user_datasource + creator = current_user ) return await RawPatientConditionOutput.from_tortoise_orm(condition_instance) diff --git a/api/migrations/app/0_20240116094530_init.py b/api/migrations/app/0_20240116134526_init.py similarity index 97% rename from api/migrations/app/0_20240116094530_init.py rename to api/migrations/app/0_20240116134526_init.py index 4ef7cebe..c57837b4 100644 --- a/api/migrations/app/0_20240116094530_init.py +++ b/api/migrations/app/0_20240116134526_init.py @@ -47,64 +47,6 @@ async def upgrade(db: BaseDBAsyncClient) -> str: "name" VARCHAR(512) NOT NULL ); COMMENT ON COLUMN "race"."slug" IS 'BRANCA: branca\nPRETA: preta\nPARDA: parda\nAMARELA: amarela\nINDIGENA: indigena'; -CREATE TABLE IF NOT EXISTS "raw__patientcondition" ( - "id" UUID NOT NULL PRIMARY KEY, - "patient_cpf" VARCHAR(11) NOT NULL, - "data" JSONB NOT NULL, - "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, - "data_source_id" UUID NOT NULL REFERENCES "datasource" ("id") ON DELETE CASCADE -); -CREATE TABLE IF NOT EXISTS "raw__patientrecord" ( - "id" UUID NOT NULL PRIMARY KEY, - "patient_cpf" VARCHAR(11) NOT NULL, - "data" JSONB NOT NULL, - "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, - "data_source_id" UUID NOT NULL REFERENCES "datasource" ("id") ON DELETE CASCADE -); -CREATE TABLE IF NOT EXISTS "std__patientcondition" ( - "id" UUID NOT NULL PRIMARY KEY, - "patient_cpf" VARCHAR(11) NOT NULL, - "cid" VARCHAR(4) NOT NULL, - "ciap" VARCHAR(4), - "clinical_status" VARCHAR(32) NOT NULL, - "category" VARCHAR(32) NOT NULL, - "date" TIMESTAMPTZ NOT NULL, - "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, - "raw_source_id" UUID NOT NULL REFERENCES "raw__patientcondition" ("id") ON DELETE CASCADE -); -COMMENT ON COLUMN "std__patientcondition"."clinical_status" IS 'RESOLVED: resolved\nRESOLVING: resolving\nNOT_RESOLVED: not_resolved'; -COMMENT ON COLUMN "std__patientcondition"."category" IS 'PROBLEM_LIST_ITEM: problem-list-item\nENCOUTER_DIAGNOSIS: encounter-diagnosis'; -CREATE TABLE IF NOT EXISTS "std__patientrecord" ( - "id" UUID NOT NULL PRIMARY KEY, - "patient_cpf" VARCHAR(11) NOT NULL, - "birth_city" VARCHAR(32) NOT NULL, - "birth_state" VARCHAR(32) NOT NULL, - "birth_country" VARCHAR(32) NOT NULL, - "birth_date" DATE NOT NULL, - "active" BOOL DEFAULT True, - "protected_person" BOOL, - "deceased" BOOL DEFAULT False, - "deceased_date" DATE, - "father_name" VARCHAR(512), - "mother_name" VARCHAR(512), - "name" VARCHAR(512) NOT NULL, - "naturalization" VARCHAR(32), - "race" VARCHAR(8) NOT NULL, - "gender" VARCHAR(7) NOT NULL, - "nationality" VARCHAR(1) NOT NULL, - "cns_list" JSONB, - "address_list" JSONB, - "telecom_list" JSONB, - "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, - "raw_source_id" UUID NOT NULL REFERENCES "raw__patientrecord" ("id") ON DELETE CASCADE -); -COMMENT ON COLUMN "std__patientrecord"."race" IS 'BRANCA: branca\nPRETA: preta\nPARDA: parda\nAMARELA: amarela\nINDIGENA: indigena'; -COMMENT ON COLUMN "std__patientrecord"."gender" IS 'MALE: male\nFEMALE: female\nUNKNOWN: unknown'; -COMMENT ON COLUMN "std__patientrecord"."nationality" IS 'BRASILEIRO: B\nESTRANGEIRO: E\nNATURALIZADO: N'; CREATE TABLE IF NOT EXISTS "state" ( "id" UUID NOT NULL PRIMARY KEY, "code" VARCHAR(10) NOT NULL UNIQUE, @@ -184,7 +126,65 @@ async def upgrade(db: BaseDBAsyncClient) -> str: "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, "data_source_id" UUID REFERENCES "datasource" ("id") ON DELETE CASCADE -);""" +); +CREATE TABLE IF NOT EXISTS "raw__patientcondition" ( + "id" UUID NOT NULL PRIMARY KEY, + "patient_cpf" VARCHAR(11) NOT NULL, + "data" JSONB NOT NULL, + "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + "creator_id" UUID NOT NULL REFERENCES "user" ("id") ON DELETE CASCADE +); +CREATE TABLE IF NOT EXISTS "raw__patientrecord" ( + "id" UUID NOT NULL PRIMARY KEY, + "patient_cpf" VARCHAR(11) NOT NULL, + "data" JSONB NOT NULL, + "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + "creator_id" UUID NOT NULL REFERENCES "user" ("id") ON DELETE CASCADE +); +CREATE TABLE IF NOT EXISTS "std__patientcondition" ( + "id" UUID NOT NULL PRIMARY KEY, + "patient_cpf" VARCHAR(11) NOT NULL, + "cid" VARCHAR(4) NOT NULL, + "ciap" VARCHAR(4), + "clinical_status" VARCHAR(32) NOT NULL, + "category" VARCHAR(32) NOT NULL, + "date" TIMESTAMPTZ NOT NULL, + "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + "raw_source_id" UUID NOT NULL REFERENCES "raw__patientcondition" ("id") ON DELETE CASCADE +); +COMMENT ON COLUMN "std__patientcondition"."clinical_status" IS 'RESOLVED: resolved\nRESOLVING: resolving\nNOT_RESOLVED: not_resolved'; +COMMENT ON COLUMN "std__patientcondition"."category" IS 'PROBLEM_LIST_ITEM: problem-list-item\nENCOUTER_DIAGNOSIS: encounter-diagnosis'; +CREATE TABLE IF NOT EXISTS "std__patientrecord" ( + "id" UUID NOT NULL PRIMARY KEY, + "patient_cpf" VARCHAR(11) NOT NULL, + "birth_city" VARCHAR(32) NOT NULL, + "birth_state" VARCHAR(32) NOT NULL, + "birth_country" VARCHAR(32) NOT NULL, + "birth_date" DATE NOT NULL, + "active" BOOL DEFAULT True, + "protected_person" BOOL, + "deceased" BOOL DEFAULT False, + "deceased_date" DATE, + "father_name" VARCHAR(512), + "mother_name" VARCHAR(512), + "name" VARCHAR(512) NOT NULL, + "naturalization" VARCHAR(32), + "race" VARCHAR(8) NOT NULL, + "gender" VARCHAR(7) NOT NULL, + "nationality" VARCHAR(1) NOT NULL, + "cns_list" JSONB, + "address_list" JSONB, + "telecom_list" JSONB, + "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, + "raw_source_id" UUID NOT NULL REFERENCES "raw__patientrecord" ("id") ON DELETE CASCADE +); +COMMENT ON COLUMN "std__patientrecord"."race" IS 'BRANCA: branca\nPRETA: preta\nPARDA: parda\nAMARELA: amarela\nINDIGENA: indigena'; +COMMENT ON COLUMN "std__patientrecord"."gender" IS 'MALE: male\nFEMALE: female\nUNKNOWN: unknown'; +COMMENT ON COLUMN "std__patientrecord"."nationality" IS 'BRASILEIRO: B\nESTRANGEIRO: E\nNATURALIZADO: N';""" async def downgrade(db: BaseDBAsyncClient) -> str: From 390bafd0326cdf53472cf52fed5a0f427687861d Mon Sep 17 00:00:00 2001 From: Pedro Nascimento Date: Tue, 16 Jan 2024 14:02:41 -0300 Subject: [PATCH 3/4] Remove unused import in main.py and fix import in entities.py --- api/app/main.py | 2 +- api/app/routers/entities.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/app/main.py b/api/app/main.py index d54ae96b..cf947187 100644 --- a/api/app/main.py +++ b/api/app/main.py @@ -9,7 +9,7 @@ from app import config from app.db import TORTOISE_ORM -from app.routers import auth, entities_mrg, entities_raw, entities_std, users, entities +from app.routers import auth, entities_mrg, entities_raw, entities_std, entities logger.remove() logger.add(sys.stdout, level=config.LOG_LEVEL) diff --git a/api/app/routers/entities.py b/api/app/routers/entities.py index 84cbe474..f0688fac 100644 --- a/api/app/routers/entities.py +++ b/api/app/routers/entities.py @@ -1,7 +1,7 @@ # -*- 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 e3f329d424031fe46699ba6fc5933c0bbafccd9b Mon Sep 17 00:00:00 2001 From: Pedro Nascimento Date: Tue, 16 Jan 2024 14:32:58 -0300 Subject: [PATCH 4/4] Remove naturalization field from patient models --- api/app/models.py | 2 -- api/app/pydantic_models.py | 3 --- api/app/routers/entities_mrg.py | 1 - .../app/{0_20240116134526_init.py => 0_20240116142415_init.py} | 2 -- api/tests/conftest.py | 1 - api/tests/test_mrg.py | 1 - api/tests/test_std.py | 1 - 7 files changed, 11 deletions(-) rename api/migrations/app/{0_20240116134526_init.py => 0_20240116142415_init.py} (99%) diff --git a/api/app/models.py b/api/app/models.py index 2d5b2c90..0b446cc7 100644 --- a/api/app/models.py +++ b/api/app/models.py @@ -46,7 +46,6 @@ 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) @@ -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") diff --git a/api/app/pydantic_models.py b/api/app/pydantic_models.py index 92569d51..d8ce6297 100644 --- a/api/app/pydantic_models.py +++ b/api/app/pydantic_models.py @@ -86,7 +86,6 @@ class PatientModel(BaseModel): mother_name: Optional[str] name: str nationality: Optional[str] - naturalization: Optional[str] protected_person: Optional[bool] race: Optional[str] cns_list: List[CnsModel] @@ -112,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] @@ -152,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]] diff --git a/api/app/routers/entities_mrg.py b/api/app/routers/entities_mrg.py index 3657bc2f..bd39c2b3 100644 --- a/api/app/routers/entities_mrg.py +++ b/api/app/routers/entities_mrg.py @@ -40,7 +40,6 @@ async def create_or_update_patient( 'name' : patient_data.get('name'), 'mother_name' : patient_data.get('mother_name'), 'father_name' : patient_data.get('father_name'), - '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']), diff --git a/api/migrations/app/0_20240116134526_init.py b/api/migrations/app/0_20240116142415_init.py similarity index 99% rename from api/migrations/app/0_20240116134526_init.py rename to api/migrations/app/0_20240116142415_init.py index c57837b4..9f4450a8 100644 --- a/api/migrations/app/0_20240116134526_init.py +++ b/api/migrations/app/0_20240116142415_init.py @@ -70,7 +70,6 @@ async def upgrade(db: BaseDBAsyncClient) -> str: "father_name" VARCHAR(512), "mother_name" VARCHAR(512), "name" VARCHAR(512) NOT NULL, - "naturalization" VARCHAR(512), "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, "birth_city_id" UUID REFERENCES "city" ("id") ON DELETE CASCADE, "gender_id" UUID NOT NULL REFERENCES "gender" ("id") ON DELETE CASCADE, @@ -171,7 +170,6 @@ async def upgrade(db: BaseDBAsyncClient) -> str: "father_name" VARCHAR(512), "mother_name" VARCHAR(512), "name" VARCHAR(512) NOT NULL, - "naturalization" VARCHAR(32), "race" VARCHAR(8) NOT NULL, "gender" VARCHAR(7) NOT NULL, "nationality" VARCHAR(1) NOT NULL, diff --git a/api/tests/conftest.py b/api/tests/conftest.py index bd7b15be..6386b183 100644 --- a/api/tests/conftest.py +++ b/api/tests/conftest.py @@ -84,7 +84,6 @@ async def initialize_tests(patient_cpf: str): deceased_date=None, mother_name="Maria", father_name="João", - naturalization="", nationality=nationality, race=race, birth_city=city, diff --git a/api/tests/test_mrg.py b/api/tests/test_mrg.py index 4d04662f..4016fcd5 100644 --- a/api/tests/test_mrg.py +++ b/api/tests/test_mrg.py @@ -66,7 +66,6 @@ async def test_put_mrgpatient(client: AsyncClient, token: str, patient_cpf : str "mother_name": "Gabriela Marques da Cunha", "name": "Fernando Marques Farias", "nationality": "B", - "naturalization": "n", "protected_person": False, "race": "parda", "cns_list": [ diff --git a/api/tests/test_std.py b/api/tests/test_std.py index 90b5a963..ac521041 100644 --- a/api/tests/test_std.py +++ b/api/tests/test_std.py @@ -27,7 +27,6 @@ async def test_post_stdpatientrecord(client: AsyncClient, token: str, patient_cp "mother_name": "Gabriela Marques da Cunha", "name": "Fernando Marques Farias", "nationality": "B", - "naturalization": "n", "protected_person": False, "race": "parda", "cns_list": [