From d4fd3af7555276241bf00c23f07f69048ec4314e Mon Sep 17 00:00:00 2001 From: rodrigmars Date: Wed, 1 May 2024 10:10:07 -0300 Subject: [PATCH] =?UTF-8?q?Ajustes=20e=20novas=20funcionalidades=20para=20?= =?UTF-8?q?formul=C3=A1rio=20pacientes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 7 - common/__init__.py | 0 common/util.py | 35 ++ pacientes/forms.py | 420 ++++++------------ ...plemento_alter_paciente_numero_and_more.py | 38 ++ .../0017_alter_paciente_agendamento_fixo.py | 18 + .../migrations/0018_alter_paciente_numero.py | 18 + pacientes/models.py | 15 +- pacientes/templates/formulario_paciente.html | 12 +- pacientes/templatetags/poll_extras.py | 8 +- pacientes/tests/test_forms.py | 75 +++- pacientes/utils.py | 2 +- pacientes/views.py | 2 +- templates/static/css/patient-form.css | 3 +- templates/static/js/patient-form.js | 54 ++- templates/static/js/util.js | 8 +- 16 files changed, 362 insertions(+), 353 deletions(-) create mode 100644 common/__init__.py create mode 100644 common/util.py create mode 100644 pacientes/migrations/0016_alter_paciente_complemento_alter_paciente_numero_and_more.py create mode 100644 pacientes/migrations/0017_alter_paciente_agendamento_fixo.py create mode 100644 pacientes/migrations/0018_alter_paciente_numero.py diff --git a/.gitignore b/.gitignore index 412016a..5780dee 100644 --- a/.gitignore +++ b/.gitignore @@ -153,10 +153,3 @@ dmypy.json # Cython debug symbols cython_debug/ - -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ \ No newline at end of file diff --git a/common/__init__.py b/common/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/common/util.py b/common/util.py new file mode 100644 index 0000000..8e52e85 --- /dev/null +++ b/common/util.py @@ -0,0 +1,35 @@ +import re + + +class CommonsUtil: + + ALPHA_PATTERN = "[A-Za-záàâãéèêíïóôõöúçñÁÀÂÃÉÈÍÏÓÔÕÖÚÇÑ\\-_\\s]+$" + + ALPHA_NUMERIC_PATTERN = "[A-Za-z0-9.-_]+$" + + ALPHA_NUMERIC_CHARACTER_PATTERN = "[A-Za-z0-9_À-ÿ.-_\\s]+$" + + NUMERIC_PATTERN = "[0-9]+$" + + PHONE_NUMERIC_PATTERN = "([0-9]{2})?([0-9]{2})([0-9]{4,5})([0-9]{4})" + + def __init__(self): + pass + + def remove_characters(self, text: str) -> str: + return re.sub("[^0-9]", "", text) + + def find_numbers(self, text: str): + return re.findall(r"[0-9]+", text) + + def is_alpha_pattern(self, text: str): + return re.match(self.ALPHA_PATTERN, text) + + def is_numeric_pattern(self, text: str): + return re.match(self.NUMERIC_PATTERN, text) + + def is_alpha_numeric_character_pattern(self, text: str): + return re.match(self.ALPHA_NUMERIC_CHARACTER_PATTERN, text) + + def is_phone_pattern(self, text: str): + return re.match(self.PHONE_NUMERIC_PATTERN, text) diff --git a/pacientes/forms.py b/pacientes/forms.py index f7734ea..5eab260 100644 --- a/pacientes/forms.py +++ b/pacientes/forms.py @@ -1,8 +1,7 @@ -from tkinter import Widget from django import forms from .utils import AGENDAMENTO_FIXO_CHOICES, GENERO_CHOICES from .models import Paciente -import re +from common.util import CommonsUtil from django.core.validators import ( MinLengthValidator, @@ -12,56 +11,21 @@ from datetime import datetime -class PacienteForm(forms.ModelForm): - - # nome = forms.CharField( - # validators=[ - # MinLengthValidator( - # 3, "Limite mínimo de 3 caracteres permitido para campo Nome" - # ), - # MaxLengthValidator( - # 30, - # message="Limite máximo de 30 caracteres permitido para campo Nome", - # ), - # RegexValidator( - # regex=r"^([a-zA-Zà-úÀ-Ú]\s)+$", - # message="Informe apenas texto para campo Nome", - # ), - # ], - # required=False, - # max_length=30, - # widget=forms.TextInput( - # attrs={ - # "placeholder": "olá papai", - # "name": "nome", - # "id": "nome", - # "class": "", - # } - # ), - # ) +class PacienteForm(forms.ModelForm, CommonsUtil): nome = forms.CharField( label="Nome", - max_length=30, + max_length=60, required=False, widget=forms.TextInput( - attrs={"name": "nome", "id": "nome", "autocomplete": "off"} + attrs={ + "name": "nome", + "id": "nome", + "autocomplete": "off", + } ), ) - # data_de_nascimento = forms.DateField( - # label="Data de Nascimento", - # input_formats=("%m/%d/%Y"), - # required=False, - # widget=forms.DateInput( - # attrs={ - # "type": "date", - # "name": "dataNascimento", - # "id": "dataNascimento", - # "autocomplete": "off", - # } - # ), - # ) data_de_nascimento = forms.DateField( label="Data de Nascimento", required=False, @@ -76,16 +40,19 @@ class PacienteForm(forms.ModelForm): }, ), ) + genero = forms.ChoiceField( + label="Gênero", required=False, widget=forms.RadioSelect(), choices=GENERO_CHOICES, ) - cartao_sus = forms.IntegerField( + cartao_sus = forms.CharField( label="Cartão SUS", + max_length=15, required=False, - widget=forms.NumberInput( + widget=forms.TextInput( attrs={ "name": "cartaoSUS", "id": "cartaoSUS", @@ -100,12 +67,11 @@ class PacienteForm(forms.ModelForm): required=False, choices=AGENDAMENTO_FIXO_CHOICES, widget=forms.RadioSelect(), - initial=2, ) telefone = forms.CharField( label="Telefone", - max_length=30, + max_length=18, required=False, widget=forms.TextInput( attrs={ @@ -119,31 +85,42 @@ class PacienteForm(forms.ModelForm): rua = forms.CharField( label="Rua", - max_length=50, + max_length=60, required=False, widget=forms.TextInput( attrs={"name": "rua", "id": "rua", "autocomplete": "off"} ), ) - numero = forms.IntegerField( + numero = forms.CharField( label="Número", + max_length=7, required=False, - widget=forms.NumberInput(attrs={"name": "numero", "id": "numero"}), + widget=forms.TextInput( + attrs={ + "name": "numero", + "id": "numero", + "autocomplete": "off", + } + ), ) complemento = forms.CharField( label="Complemento", - max_length=40, + max_length=60, required=False, widget=forms.TextInput( - attrs={"name": "complemento", "id": "complemento", "autocomplete": "off"} + attrs={ + "name": "complemento", + "id": "complemento", + "autocomplete": "off", + } ), ) ponto_referencia = forms.CharField( label="Ponto de Referência", - max_length=40, + max_length=60, required=False, widget=forms.TextInput( attrs={ @@ -154,213 +131,6 @@ class PacienteForm(forms.ModelForm): ), ) - # nome = ( - # forms.CharField( - # validators=[ - # MinLengthValidator( - # 3, "Limite mínimo de 3 caracteres permitido para campo Nome" - # ), - # MaxLengthValidator( - # 30, - # message="Limite máximo de 30 caracteres permitido para campo Nome", - # ), - # RegexValidator( - # regex=r"^([a-zA-Zà-úÀ-Ú]\s)+$", - # message="Informe apenas texto para campo Nome", - # ), - # ], - # max_length=30, - # required=True, - # widget=forms.TextInput( - # attrs={ - # "placeholder": "* Nome", - # "class": "form-text-input", - # "name": "nome", - # "id": "nome", - # } - # ), - # ), - # ) - - # sobre_nome = ( - # forms.CharField( - # validators=[ - # MinLengthValidator(3, "Limite mínimo de 3 caracteres"), - # MaxLengthValidator( - # 60, - # message="Limite máximo de 30 caracteres", - # ), - # RegexValidator( - # regex=r"^([a-zA-Zà-úÀ-Ú]\s)+$", - # message="Formato texto inválido", - # ), - # ], - # max_length=60, - # required=True, - # widget=forms.TextInput( - # attrs={ - # "placeholder": "* Sobre nome", - # "class": "form-text-input", - # "name": "sobreNome", - # "id": "sobreNome", - # } - # ), - # ), - # ) - - # # '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2024-01-15', '01/15/2024', '01/15/24' - # data_de_nascimento = ( - # forms.DateField( - # required=True, - # widget=forms.DateInput( - # format="%m/%d/%Y", - # attrs={ - # "type": "date", - # "placeholder": "* dd/mm/yyyy", - # "class": "form-text-input", - # "name": "dataNascimento", - # "id": "dataNascimento", - # }, - # ), - # error_messages={"invalid": "Formato data inválido"}, - # ), - # ) - - # genero = forms.ChoiceField(choices=GENERO_CHOICES, widget=forms.RadioSelect()) - - # cartao_sus = forms.CharField() - - # telefone = ( - # forms.CharField( - # validators=[ - # RegexValidator( - # regex=r"(\([0-9]{2}\))\s([9]{1})?([0-9]{4})-([0-9]{4})", - # message="Formato inválido", - # ), - # ], - # max_length=15, - # required=True, - # widget=forms.TextInput( - # attrs={ - # "type": "tel", - # "placeholder": "* (99) 9999-9999", - # "class": "form-text-input", - # "name": "telefone", - # "id": "telefone", - # } - # ), - # ), - # ) - - # rua = ( - # forms.CharField( - # validators=[ - # MinLengthValidator(5, "Limite mínimo de 5 caracteres"), - # MaxLengthValidator( - # 80, - # message="Limite máximo de 80 caracteres", - # ), - # RegexValidator( - # regex=r"^([a-zA-Zà-úÀ-Ú0-9]|-|_|.|º|\s)+$", - # message="Formato texto inválido", - # ), - # ], - # max_length=60, - # required=True, - # widget=forms.TextInput( - # attrs={ - # "placeholder": "* Sobre nome", - # "class": "form-text-input", - # "name": "sobreNome", - # "id": "sobreNome", - # } - # ), - # ), - # ) - - # numero = ( - # forms.IntegerField( - # required=True, - # widget=forms.NumberInput( - # attrs={ - # "placeholder": "* Número", - # "class": "form-text-input", - # "name": "sobreNome", - # "id": "sobreNome", - # } - # ), - # error_messages={"invalid": "Campo necessário"}, - # ), - # ) - - # complemento = ( - # forms.CharField( - # validators=[ - # MinLengthValidator(5, "Limite mínimo de 5 caracteres"), - # MaxLengthValidator( - # 60, - # message="Limite máximo de 60 caracteres", - # ), - # RegexValidator( - # regex=r"[^A-Za-z0-9\\s]+", - # message="Formato texto inválido", - # ), - # ], - # max_length=60, - # required=True, - # widget=forms.TextInput( - # attrs={ - # "placeholder": "Sobre nome", - # "class": "form-text-input", - # "name": "sobreNome", - # "id": "sobreNome", - # } - # ), - # ), - # ) - - # ponto_referencia = ( - # forms.CharField( - # validators=[ - # RegexValidator( - # regex=r"^([a-zA-Zà-úÀ-Ú]\s)+$", - # message="Formato texto inválido", - # ), - # ], - # max_length=15, - # required=True, - # widget=forms.TextInput( - # attrs={ - # "placeholder": "", - # "class": "form-text-input", - # "name": "pontoReferencia", - # "id": "pontoReferencia", - # } - # ), - # ), - # ) - - # def clean(self): - - # super(PacienteForm, self).clean() - - # nome = forms.CharField( - # validators=[ - # # MinLengthValidator( - # # 3, "Limite mínimo de 3 caracteres permitido para campo Nome" - # # ), - # MaxLengthValidator( - # 30, - # message="Limite máximo de 30 caracteres permitido para campo Nome", - # ), - # RegexValidator( - # regex=r"^([a-zA-Zà-úÀ-Ú]\s)+$", - # message="Informe apenas texto para campo Nome", - # ), - # ], - # error_messages={"required": "Campo necessário"}, - # ) - class Meta: model = Paciente @@ -373,14 +143,14 @@ def clean(self): super().clean() - valid_alpha = "[A-Za-záàâãéèêíïóôõöúçñÁÀÂÃÉÈÍÏÓÔÕÖÚÇÑ\\-_\\s]+$" - - valid_alpha_numeric = "[A-Za-z0-9_À-ÿ.-_\\s]+$" + errors = {} nome = self.cleaned_data.get("nome") data_de_nascimento = self.cleaned_data.get("data_de_nascimento") + genero = self.cleaned_data.get("genero") + cartao_sus = self.cleaned_data.get("cartao_sus") agendamento_fixo = self.cleaned_data.get("agendamento_fixo") @@ -397,38 +167,118 @@ def clean(self): # NOME if not nome: - raise forms.ValidationError( - {"nome": "Campo obrigatório, deve conter de 5 a 60 caracteres"} - ) + errors["nome"] = "Campo nome obrigatório" - if len(nome) < 5 or len(nome) > 60: - raise forms.ValidationError( - {"nome": "Campo deve conter de 5 a 60 caracteres"} - ) + if nome: - if re.match(valid_alpha, nome) is None: - raise forms.ValidationError( - {"nome": "Campo inválido, informe apenas texto"} - ) + if len(nome) < 5 or len(nome) > 60: + errors["nome"] = ( + "Certifique-se de que o valor tenha entre 5 a 60 caracteres" + ) + + elif not self.is_alpha_pattern(nome): + errors["nome"] = ( + "Certifique-se de que o valor tenha apenas caracteres texto" + ) # DATA_DE_NASCIMENTO if not data_de_nascimento: - raise forms.ValidationError({"data_de_nascimento": "Campo obrigatório"}) + errors["data_de_nascimento"] = "Campo data de nascimento obrigatório" + + if data_de_nascimento: + + ano = int(datetime.now().year - (data_de_nascimento.year)) - ano = int(datetime.now().year - (data_de_nascimento.year)) + if ano == -1 or ano > 100: + errors["data_de_nascimento"] = "Informe uma data de nascimento válida" - if ano == -1 or ano > 100: - raise forms.ValidationError( - {"data_de_nascimento": "Informe uma data válida"} - ) + if not genero: + errors["genero"] = "Campo gênero obrigatório" # CARTAO_SUS if not cartao_sus: - raise forms.ValidationError({"cartao_sus": "Campo obrigatório"}) + errors["cartao_sus"] = "Campo cartão SUS obrigatório" - if not cartao_sus: - raise forms.ValidationError({"cartao_sus": "Campo obrigatório"}) + if cartao_sus: - # CARTAO_SUS + if len(cartao_sus) != 15: + errors["cartao_sus"] = ( + "Campo cartão SUS deve possuir um tamanho de 15 dígitos" + ) + + elif not self.is_numeric_pattern(cartao_sus): + errors["cartao_sus"] = ( + "Formato de campo inválido para cartão SUS, informe apenas números" + ) + + if not agendamento_fixo: + errors["agendamento_fixo"] = "Selecione uma opção para agendamento fixo" + + if not telefone: + errors["telefone"] = "Campo telefone obrigatório" + + if telefone: + + if len(self.remove_characters(telefone)) != 13 or not self.is_phone_pattern( + self.remove_characters(telefone) + ): + errors["telefone"] = ( + "Certifique-se de que o número de telefone esteja correto" + ) + + if not rua: + errors["rua"] = "Campo rua obrigatório" + + if rua: + + if len(rua) < 5 or len(rua) > 60: + errors["rua"] = ( + "Certifique-se de que o valor tenha entre 5 a 60 caracteres" + ) + + elif not self.is_alpha_numeric_character_pattern(rua): + errors["rua"] = ( + "Certifique-se de que o valor tenha apenas caracteres texto" + ) + + if not numero: + errors["numero"] = "Campo número obrigatório" + + if numero: + + if len(numero) > 7: + errors["numero"] = ( + "Certifique-se de que o valor tenha no máximo 7 caracteres" + ) + + elif not self.find_numbers(numero): + errors["numero"] = "Número de endereço obrigatório" + + if complemento: + + if len(complemento) < 5 or len(complemento) > 60: + errors["complemento"] = ( + "Certifique-se de que o valor tenha entre 5 a 60 caracteres" + ) + + elif not self.is_alpha_numeric_character_pattern(complemento): + errors["complemento"] = ( + "Certifique-se de que o valor tenha apenas caracteres texto" + ) + + if ponto_referencia: + + if len(ponto_referencia) < 5 or len(ponto_referencia) > 60: + errors["ponto_referencia"] = ( + "Certifique-se de que o valor tenha entre 5 a 60 caracteres" + ) + + elif not self.is_alpha_numeric_character_pattern(ponto_referencia): + errors["ponto_referencia"] = ( + "Certifique-se de que o valor tenha apenas caracteres texto" + ) + + if errors: + raise forms.ValidationError(errors) return self.cleaned_data diff --git a/pacientes/migrations/0016_alter_paciente_complemento_alter_paciente_numero_and_more.py b/pacientes/migrations/0016_alter_paciente_complemento_alter_paciente_numero_and_more.py new file mode 100644 index 0000000..990afeb --- /dev/null +++ b/pacientes/migrations/0016_alter_paciente_complemento_alter_paciente_numero_and_more.py @@ -0,0 +1,38 @@ +# Generated by Django 5.0.4 on 2024-04-30 14:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("pacientes", "0015_alter_paciente_cartao_sus_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="paciente", + name="complemento", + field=models.CharField(max_length=60), + ), + migrations.AlterField( + model_name="paciente", + name="numero", + field=models.CharField(max_length=5), + ), + migrations.AlterField( + model_name="paciente", + name="ponto_referencia", + field=models.CharField(max_length=60), + ), + migrations.AlterField( + model_name="paciente", + name="rua", + field=models.CharField(max_length=60), + ), + migrations.AlterField( + model_name="paciente", + name="telefone", + field=models.CharField(max_length=13), + ), + ] diff --git a/pacientes/migrations/0017_alter_paciente_agendamento_fixo.py b/pacientes/migrations/0017_alter_paciente_agendamento_fixo.py new file mode 100644 index 0000000..18e5a02 --- /dev/null +++ b/pacientes/migrations/0017_alter_paciente_agendamento_fixo.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.4 on 2024-04-30 14:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("pacientes", "0016_alter_paciente_complemento_alter_paciente_numero_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="paciente", + name="agendamento_fixo", + field=models.IntegerField(choices=[(1, "SIM"), (2, "Não")]), + ), + ] diff --git a/pacientes/migrations/0018_alter_paciente_numero.py b/pacientes/migrations/0018_alter_paciente_numero.py new file mode 100644 index 0000000..770dbd3 --- /dev/null +++ b/pacientes/migrations/0018_alter_paciente_numero.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.4 on 2024-04-30 18:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("pacientes", "0017_alter_paciente_agendamento_fixo"), + ] + + operations = [ + migrations.AlterField( + model_name="paciente", + name="numero", + field=models.CharField(max_length=7), + ), + ] diff --git a/pacientes/models.py b/pacientes/models.py index c0a648f..b613687 100644 --- a/pacientes/models.py +++ b/pacientes/models.py @@ -17,20 +17,17 @@ class Status(models.IntegerChoices): cartao_sus = models.CharField(max_length=15, unique=True) - agendamento_fixo = models.IntegerField( - choices=AGENDAMENTO_FIXO_CHOICES, - default=Status.ATIVO, - ) + agendamento_fixo = models.IntegerField(choices=AGENDAMENTO_FIXO_CHOICES) - telefone = models.CharField(max_length=18) + telefone = models.CharField(max_length=13) - rua = models.CharField(max_length=50) + rua = models.CharField(max_length=60) - numero = models.IntegerField() + numero = models.CharField(max_length=7) - complemento = models.CharField(max_length=40) + complemento = models.CharField(max_length=60) - ponto_referencia = models.CharField(max_length=40) + ponto_referencia = models.CharField(max_length=60) status = models.IntegerField(default=Status.ATIVO) diff --git a/pacientes/templates/formulario_paciente.html b/pacientes/templates/formulario_paciente.html index 571df96..6c8bd9d 100644 --- a/pacientes/templates/formulario_paciente.html +++ b/pacientes/templates/formulario_paciente.html @@ -25,23 +25,21 @@

Cadastro de Paciente

{% if field.name in FIELDSET_LEGENDS %}
- {{ field.label_tag }} + {{ field.errors|yesno:"* ," }}{{ field.label_tag }} {{ field }}
{% else %}
-
- {{ field.errors|yesno:"* ," }}{{ field.label_tag }} -
+
{{ field.errors|yesno:"* ," }}{{ field.label_tag }}
{{ field }}
-
-
{{ field.errors }}
-
{% endif %} +
+
{{ field.errors }}
+
{% endfor %}
diff --git a/pacientes/templatetags/poll_extras.py b/pacientes/templatetags/poll_extras.py index 30bffb7..2e62723 100644 --- a/pacientes/templatetags/poll_extras.py +++ b/pacientes/templatetags/poll_extras.py @@ -10,12 +10,12 @@ def set_column_label(field: BoundField) -> str: fields = { "nome": "col-1", "data_de_nascimento": "col-2", - "cartao_sus": "col-1", + "cartao_sus": "col-2", "telefone": "col-1", "rua": "col-1", "numero": "col-1", - "complemento": "col-1", - "ponto_referencia": "col-2", + "complemento": "col-3", + "ponto_referencia": "col-3", } # print(f"{type(field)} {fields[field.name]} {field.name}") @@ -34,7 +34,7 @@ def set_column_input(field: BoundField) -> str: "agendamento_fixo": "col-5", "telefone": "col-2", "rua": "col-5", - "numero": "col-1", + "numero": "col-2", "complemento": "col-4", "ponto_referencia": "col-4", } diff --git a/pacientes/tests/test_forms.py b/pacientes/tests/test_forms.py index d33adc1..702fab3 100644 --- a/pacientes/tests/test_forms.py +++ b/pacientes/tests/test_forms.py @@ -1,32 +1,77 @@ +from http import client from unicodedata import numeric from django.test import TestCase -from ..forms import PacienteForm -import re +from common.util import CommonsUtil -class PacienteFormTestCase(TestCase): +class PacienteFormTestCase(TestCase, CommonsUtil): - def setUp(self): + def setUp(self) -> None: - self.alpha_pattern = "[A-Za-záàâãéèêíïóôõöúçñÁÀÂÃÉÈÍÏÓÔÕÖÚÇÑ\\-_\\s]+$" + self.paciente_ok = { + "nome": "Tatiane Eliane Aparício", + "telefone": "+55(62) 98833-9109", + "cartao_sus": "237186420750009", + } - self.alpha_numeric_pattern = "[A-Za-z0-9_À-ÿ.-_\\s]+$" + self.paciente_nok = { + "nome": "Tatiane Eliane. Aparício", + "telefone": "+55(62) +._=98833-91509", + "cartao_sus": "237186420750.A009+", + } - self.numeric_pattern = "[^0-9]" + def test_acerto_verifica_se_cartao_sus_existe(self): - self.phone_number_pattern = "([0-9]{2})?([0-9]{2})([0-9]{4,5})([0-9]{4})" + self.assertIsNotNone(self.paciente_ok["cartao_sus"], "Campo obrigatório") - self.phone_number = "+55(62) +._=98833-91509" + def test_acerto_verifica_tamanho_de_campo_cartao_sus(self): - def test_acerto_para_formato_numerico_campo_telefone(self): + self.assertEqual( + len(self.paciente_ok["cartao_sus"]), + 15, + "Campo deve possuir um tamanho de 15 dígitos", + ) + + def test_acerto_verifica_formato_de_campo_cartao_sus(self): + + self.assertIsNotNone( + self.is_numeric_pattern(self.paciente_ok["cartao_sus"]), + "Formato de campo inválido, informe apenas números", + ) + + def test_acerto_no_tamanho_campo_telefone(self) -> None: + + self.assertEqual( + len(self.remove_characters(self.paciente_ok["telefone"])), + 13, + "Tamanho inválido para telefone", + ) + + def test_acerto_remove_caracteres_alpha(self) -> None: - self.assertTrue( - re.sub(self.numeric_pattern, "", self.phone_number).isnumeric(), + self.assertEqual( + self.remove_characters(self.paciente_ok["telefone"]), + "5562988339109", "Formato inválido para telefone", ) - def test_falha_no_formato_campo_nome(self): + def test_acerto_verifica_formato_telefone(self) -> None: + + self.assertIsNotNone( + self.is_phone_pattern(self.remove_characters(self.paciente_ok["telefone"])), + "Formato inválido para telefone", + ) + + def test_falha_no_formato_campo_nome(self) -> None: + + self.assertIsNone(self.is_alpha_pattern(self.paciente_nok["nome"])) + + def test_falha_no_tamanho_campo_telefone(self) -> None: + + self.assertFalse( + len(self.remove_characters(self.paciente_nok["telefone"])) == 13 + ) - nome = "Tatiane Eliane. Aparício" + def test_falha_no_formato_campo_telefone(self) -> None: - self.assertIsNone(re.match(self.alpha_pattern, nome)) + self.assertIsNone(self.is_phone_pattern(self.paciente_nok["telefone"])) diff --git a/pacientes/utils.py b/pacientes/utils.py index 2ec0dab..169f4ac 100644 --- a/pacientes/utils.py +++ b/pacientes/utils.py @@ -1,5 +1,5 @@ from django.db import models -AGENDAMENTO_FIXO_CHOICES = ((1, "SIM"), (2, "Não")) +AGENDAMENTO_FIXO_CHOICES = ((1, "Sim"), (2, "Não")) GENERO_CHOICES = ((1, "Feminino"), (2, "Masculino"), (3, "Outros")) diff --git a/pacientes/views.py b/pacientes/views.py index 61350d4..05da5d4 100644 --- a/pacientes/views.py +++ b/pacientes/views.py @@ -44,7 +44,7 @@ def cadastrar(request): return render(request, "formulario_paciente", context) print("---------------") - print(context["form"].errors) + print(context["form"].errors.as_data()) context["erros"] = context["form"].errors.as_data() diff --git a/templates/static/css/patient-form.css b/templates/static/css/patient-form.css index 696e822..36c8f8b 100644 --- a/templates/static/css/patient-form.css +++ b/templates/static/css/patient-form.css @@ -10,7 +10,8 @@ } .form_row .error { - color: red; + color: #FF204E; + /* color: red; */ font-weight: bold; } diff --git a/templates/static/js/patient-form.js b/templates/static/js/patient-form.js index b04ea9e..c9a11cd 100644 --- a/templates/static/js/patient-form.js +++ b/templates/static/js/patient-form.js @@ -1,62 +1,72 @@ // Immediately-Invoked Function Expression (IIFE) ; (atlas => { - const name = atlas.document.getElementById("nome"); + const nome = atlas.document.getElementById("nome"); - const phone = atlas.document.getElementById("telefone"); + const telefone = atlas.document.getElementById("telefone"); - const card = atlas.document.getElementById("cartaoSUS"); + const cartaoSUS = atlas.document.getElementById("cartaoSUS"); - const street = atlas.document.getElementById("rua"); + const rua = atlas.document.getElementById("rua"); - const number = atlas.document.getElementById("numero"); + const numero = atlas.document.getElementById("numero"); - const complement = atlas.document.getElementById("complemento") + const complemento = atlas.document.getElementById("complemento") - const reference = atlas.document.getElementById("pontoReferencia") + const pontoReferencia = atlas.document.getElementById("pontoReferencia") - name.focus(); + nome.focus(); - name.addEventListener("input", event => { + nome.addEventListener("input", event => { event.target.value = atlas.maximum(event.target.value, 50); - event.target.value = atlas.replace(event.target.value, atlas.alpha); + event.target.value = atlas.replace(event.target.value, atlas.isAlpha); }); - phone.addEventListener("input", event => { + telefone.addEventListener("input", event => { if (event.inputType === "insertText") { event.target.value = atlas.mask(event.target.value) } }); - card.addEventListener('input', event => event.target.value = atlas.maximum(event.target.value, 15)); + cartaoSUS.addEventListener('input', event => { - street.addEventListener("input", event => { + event.target.value = atlas.maximum(event.target.value, 15); + + event.target.value = atlas.replace(event.target.value, atlas.isNumeric); + }); + + rua.addEventListener("input", event => { event.target.value = atlas.maximum(event.target.value, 50); - event.target.value = atlas.replace(event.target.value, atlas.alphaNumeric); + event.target.value = atlas.replace(event.target.value, atlas.isAlphaNumericCharacter); }); - number.addEventListener("input", event => event.target.value = atlas.maximum(event.target.value, 5)); + numero.addEventListener("input", event => { + + event.target.value = atlas.maximum(event.target.value, 7); + + event.target.value = atlas.replace(event.target.value, atlas.isAlphaNumeric); + }); - complement.addEventListener("input", event => { + complemento.addEventListener("input", event => { event.target.value = atlas.maximum(event.target.value, 40); - event.target.value = atlas.replace(event.target.value, atlas.alphaNumeric); + event.target.value = atlas.replace(event.target.value, atlas.isAlphaNumericCharacter); }); - reference.addEventListener("input", event => { + pontoReferencia.addEventListener("input", event => { event.target.value = atlas.maximum(event.target.value, 40); - event.target.value = atlas.replace(event.target.value, atlas.alphaNumeric); + event.target.value = atlas.replace(event.target.value, atlas.isAlphaNumericCharacter); }); @@ -67,8 +77,10 @@ })({ document, window, - "alpha": alpha, - "alphaNumeric": alphaNumeric, + "isAlpha": isAlpha, + "isNumeric": isNumeric, + "isAlphaNumeric": isAlphaNumeric, + "isAlphaNumericCharacter": isAlphaNumericCharacter, "mask": maskPhone, "replace": replaceCharacter, "maximum": maximumCharacters diff --git a/templates/static/js/util.js b/templates/static/js/util.js index e7fb381..8ed2d35 100644 --- a/templates/static/js/util.js +++ b/templates/static/js/util.js @@ -1,8 +1,12 @@ "use strict"; -const alpha = /[^A-Za-z\u00C0-\u00FF\s\b]/g; +const isAlpha = /[^A-Za-z\u00C0-\u00FF\s\b]/g; -const alphaNumeric = /[^A-Za-z0-9\u00C0-\u00FF._-\s\b]/g; +const isNumeric = /[^0-9\b]/g; + +const isAlphaNumeric = /[^A-Za-z0-9.-]/g; + +const isAlphaNumericCharacter = /[^A-Za-z0-9\u00C0-\u00FF._-\s\b]/g; function maskPhone(text) {