Skip to content

Commit

Permalink
feat/ format and check integrity to patient
Browse files Browse the repository at this point in the history
  • Loading branch information
ThiagoTrabach committed Aug 31, 2023
1 parent c22630d commit 444e703
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 18 deletions.
160 changes: 148 additions & 12 deletions fhir_utils/fhir/patient/resource.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,175 @@
# -*- coding: utf-8 -*-
from fhir_utils.utils import (
capitalize_each_word,
keep_alpha_characters,
keep_numeric_characters,
remove_wrong_whitespaces,
is_valid_cpf,
is_valid_date_format)
from dataclasses import dataclass, field
from datetime import datetime
import re

@dataclass
class Patient:
source : str
name : str
birth_date : str
cpf : str
gender : str
birth_date : str
birth_country : str
cns : str = ""
gender : str = "unknow"
active : bool = True
address : list = field(default_factory=list)
birth_city : str = ""
birth_country : str = "01"
deceased : bool = True
nationality : str = ""
naturalization : str = ""
mother : str = ""
father : str = ""
protected_person : bool = False
protected_person : bool = ""
race: str = ""
ethnicity : str = ""
register_quality : float = 0
register_quality : float = ""
telecom : list = field(default_factory=list)
_is_valid: bool = True
_invalid_elements: list = field(default_factory=list)

def __post_init__(self):
self.name = self.name.title()
# verifica validade da pk
# format values
self.format_cpf()
self.format_cns()
self.name = self.format_name(self.name)
self.mother = self.format_name(self.mother)
self.father = self.format_name(self.father)
self.format_cep()
self.format_phone()

# check if input is correct
self.check_cpf()
self.check_cns()
self.check_birth_country()
self.check_birth_date()
self.check_gender()
self.check_address()
self.check_telecom()


def format_cpf(self):
self.cpf = keep_numeric_characters(self.cpf)

def format_cns(self):
self.cns = keep_numeric_characters(self.cns)

def format_name(self, name):
name = remove_wrong_whitespaces(name)
name = keep_alpha_characters(name)
name = capitalize_each_word(name)
return name

def format_cep(self):
for i in self.address:
self.address[i]["postalCode"] = keep_numeric_characters(self.address[i]["postalCode"])

def format_phone(self):
for i in self.address:
if self.telecom[i]["system"] == "phone":
self.telecom[i]["value"] = keep_numeric_characters(self.telecom[i]["value"])


def check_cpf(self):
if not is_valid_cpf(self.cpf):
self._is_valid = False
self._invalid_elements.append("cpf")
#raise ValueError("CPF not valid")

def check_cns(self):
if len(self.cns) > 0 and len(self.cns) != 15:
self._is_valid = False
self._invalid_elements.append("cns")
#raise ValueError("CNS must have 15 digits")

def check_birth_country(self):
if self.gender not in ["B", "E", "N"]:
self._is_valid = False
self._invalid_elements.append("birth_country")

def check_birth_date(self):
if not is_valid_date_format(self.birth_date):
self._is_valid = False
self._invalid_elements.append("birth_date")
#raise ValueError("Birth date must be formated like 'YYYY-MM-DD'")
elif datetime.strptime(self.birth_date, "%Y-%m-%d") > datetime.now():
self._is_valid = False
self._invalid_elements.append("birth_date")
#raise ValueError("So you were born in the future?")
elif datetime.strptime(self.birth_date, "%Y-%m-%d") < datetime(1900, 1, 1):
self._is_valid = False
self._invalid_elements.append("birth_date")
#raise ValueError("You cant be that old!")

def check_gender(self):
if self.gender not in ["male", "female", "unknown"]:
self._is_valid = False
self._invalid_elements.append("gender")

def check_address(self):

keys = ["use", "type", "line", "city", "state", "postalCode"]

for i in self.address:
# if all must have keys are present
if not all(key in self.address[i] for key in keys):
self._is_valid = False
self._invalid_elements.append("address")

# accepted values
if self.address[i]["use"] not in ["home", "work", "temp", "old", "billing"]:
self._is_valid = False
self._invalid_elements.append("address")

if self.address[i]["type"] not in ["postal", "physical", "both"]:
self._is_valid = False
self._invalid_elements.append("address")

line = self.address[i]["line"]
if not 4 <= len(line) <= 5 or line[0] not in ["008", "081"]:
self._is_valid = False
self._invalid_elements.append("address")

if len(keep_numeric_characters(self.address[i]["city"])) != 6:
self._is_valid = False
self._invalid_elements.append("address")

if len(keep_numeric_characters(self.address[i]["state"])) != 2:
self._is_valid = False
self._invalid_elements.append("address")

if len(keep_numeric_characters(self.address[i]["postalCode"])) != 8:
self._is_valid = False
self._invalid_elements.append("address")

# verifica presença dos campos obrigatórios
def check_telecom(self):

keys = ["system", "value", "use"]

#def compliance_check
for i in self.telecom:
# if all must have keys are present
if not all(key in self.telecom[i] for key in keys):
self._is_valid = False
self._invalid_elements.append("telecom")

#def padroniza textos
# accepted values
if self.telecom[i]["system"] not in ["phone", "fax", "email", "pager", "url", "sms", "other"]:
self._is_valid = False
self._invalid_elements.append("telecom")

#def dicarcad_incomplinat
tel_number = keep_alpha_characters(self.telecom[i]["value"])
if self.telecom[i]["system"] == "phone" and not 12 <= len(tel_number) <=13: # ddi+ddd+phone
self._is_valid = False
self._invalid_elements.append("telecom")

#def to_fhir
email = self.telecom[i]["value"]
if not re.match(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$", email):
self._is_valid = False
self._invalid_elements.append("telecom")
64 changes: 62 additions & 2 deletions fhir_utils/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import json
import xmltodict
from datetime import datetime


# FILE FUNCTIONS

def json_to_dict(json_file_path):
try:
Expand Down Expand Up @@ -27,6 +31,62 @@ def xml_to_dict(xml_file_path):
return None


def save_to_json(dict, json_path,):
def save_to_json(dict, json_path):
with open(json_path, "w") as file:
json.dump(dict, file)
json.dump(dict, file)


# TEXT FUNCTIONS

def keep_alpha_characters(input_string):
return ''.join(char for char in input_string if char.isalpha() or char.isspace())

def keep_numeric_characters(input_string):
return ''.join(char for char in input_string if char.isdigit())

def capitalize_each_word(input_string):
return input_string.title()

def remove_wrong_whitespaces(input_string):
return " ".join(input_string.split())


def is_valid_cpf(cpf):
# Remover caracteres não numéricos do CPF
cpf = ''.join(filter(str.isdigit, cpf))

# Verificar se o CPF possui 11 dígitos
if len(cpf) != 11:
return False

# Verificar se todos os dígitos são iguais (CPF inválido)
if cpf == cpf[0] * 11:
return False

# Calcular os dígitos verificadores
total = 0
for i in range(9):
total += int(cpf[i]) * (10 - i)
digit1 = 11 - (total % 11)
if digit1 > 9:
digit1 = 0

total = 0
for i in range(10):
total += int(cpf[i]) * (11 - i)
digit2 = 11 - (total % 11)
if digit2 > 9:
digit2 = 0

# Verificar se os dígitos verificadores calculados coincidem com os dígitos do CPF
if int(cpf[9]) != digit1 or int(cpf[10]) != digit2:
return False

return True

def is_valid_date_format(date_string):
try:
datetime.strptime(date_string, '%Y-%m-%d')
return True
except ValueError:
return False
13 changes: 9 additions & 4 deletions run.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,22 @@
gabriela = Patient(name = patient["name"],
cpf = patient["identifiers"]["tax"],
birth_date = patient["birth_date"],
source ="vitai" )
source ="vitai",
mother = patient["mother"],
father = patient["father"],
gender = "macho")

gabriela2 = Patient(name = patient2["name"],
cpf = patient2["identifiers"]["tax"],
birth_date = patient2["birth_date"],
father = "Deus",
source ="vitai" )
source ="vitai" ,
gender = patient2["gender"])


print(compare_resources(gabriela, gabriela2))
print()
print(replace(gabriela2, name = "Thiago", birth_date = "1988-01-18"))
print(is_dataclass(gabriela))
print(gabriela)
#print(replace(gabriela2, name = "Thiago", birth_date = "1988-01-18"))
#print(is_dataclass(gabriela))

0 comments on commit 444e703

Please sign in to comment.