diff --git a/sigi/apps/casas/admin.py b/sigi/apps/casas/admin.py index b210c72..cf49311 100644 --- a/sigi/apps/casas/admin.py +++ b/sigi/apps/casas/admin.py @@ -466,17 +466,17 @@ class OrgaoAdmin(AsciifyQParameter, CartExportReportMixin, admin.ModelAdmin): ) return super().save_related(request, form, formsets, change) + @admin.display( + description=_("Unidade da Federação"), ordering="municipio__uf__nome" + ) def get_uf(self, obj): return obj.municipio.uf.nome - get_uf.short_description = _("Unidade da Federação") - get_uf.admin_order_field = "municipio__uf__nome" - + @admin.display(description=_("Gerente Interlegis")) def get_gerentes(self, obj): return mark_safe(obj.lista_gerentes()) - get_gerentes.short_description = _("Gerente Interlegis") - + @admin.display(description=_("Convênios")) def get_convenios(self, obj): return mark_safe( "" ) - get_convenios.short_description = _("Convênios") - + @admin.display(description=_("Serviços")) def get_servicos(self, obj): return mark_safe( "" ) - get_servicos.short_description = _("Serviços") - def lookup_allowed(self, lookup, value): return super(OrgaoAdmin, self).lookup_allowed( lookup, value diff --git a/sigi/apps/casas/forms.py b/sigi/apps/casas/forms.py index 86fb4c9..1fb3c39 100644 --- a/sigi/apps/casas/forms.py +++ b/sigi/apps/casas/forms.py @@ -1,9 +1,11 @@ from django import forms +from django.core.exceptions import ValidationError from django.utils.translation import gettext as _ from localflavor.br.forms import BRZipCodeField from material.admin.widgets import MaterialAdminTextareaWidget from sigi.apps.casas.models import Funcionario, Orgao from sigi.apps.servidores.models import Servidor +from sigi.apps.utils import valida_cnpj class AtualizaCasaForm(forms.Form): @@ -23,6 +25,47 @@ class OrgaoForm(forms.ModelForm): model = Orgao fields = "__all__" + def clean(self): + cleaned_data = super().clean() + nome = cleaned_data.get("nome") + tipo = cleaned_data.get("tipo") + municipio = cleaned_data.get("municipio") + if tipo.sigla == "CM": + nome_correto = [f"Câmara Municipal de {municipio.nome}"] + elif tipo.sigla == "AL": + nome_correto = [ + f"Assembleia Legislativa {conj} {municipio.uf.nome}" + for conj in ["da", "de", "do"] + ] + else: + nome_correto = [nome] + if nome not in nome_correto: + self.add_error( + "nome", + ValidationError( + _( + "O nome '%(nome)s' não é adequado para uma %(tipo)s. " + "O correto deve ser '%(nome_correto)s'." + ), + code="invalid_nome", + params={ + "nome": nome, + "tipo": tipo.nome, + "nome_correto": nome_correto[0], + }, + ), + ) + return cleaned_data + + def clean_cnpj(self): + cnpj = self.cleaned_data.get("cnpj") + if cnpj != "" and not valida_cnpj(cnpj): + raise ValidationError( + _("CNPJ inválido. Dígito verificador não confere."), + code="invalid_cnpj", + ) + return cnpj + class PortfolioForm(forms.Form): ACAO_CHOICES = (("ADD", _("Adicionar")), ("DEL", _("Remover"))) diff --git a/sigi/apps/casas/models.py b/sigi/apps/casas/models.py index 222e9e1..d5fcf35 100644 --- a/sigi/apps/casas/models.py +++ b/sigi/apps/casas/models.py @@ -9,7 +9,7 @@ from django.utils.translation import gettext as _ from sigi.apps.contatos.models import Municipio from sigi.apps.servidores.models import Servidor -from sigi.apps.utils import SearchField +from sigi.apps.utils import SearchField, mask_cnpj, valida_cnpj class TipoOrgao(models.Model): @@ -224,6 +224,14 @@ class Orgao(models.Model): if address_changed: self.ult_alt_endereco = timezone.localtime() + # Mascara corretamente o CNPJ + if ( + self.cnpj != "" + and valida_cnpj(self.cnpj) + and self.cnpj != mask_cnpj(self.cnpj) + ): + self.cnpj = mask_cnpj(self.cnpj) + return super(Orgao, self).save(*args, **kwargs) diff --git a/sigi/apps/utils/__init__.py b/sigi/apps/utils/__init__.py index c340708..21b06f6 100644 --- a/sigi/apps/utils/__init__.py +++ b/sigi/apps/utils/__init__.py @@ -1,3 +1,4 @@ +import re from unicodedata import normalize from django.contrib import admin as django_admin from django.core.exceptions import FieldDoesNotExist @@ -88,3 +89,20 @@ def abreviatura(name): for conector in [" da ", " de ", " do ", " das ", " dos ", " e "]: name = name.replace(conector, " ") return ("".join([w[0] for w in name.split()])).upper() + + +def valida_cnpj(cnpj): + cnpj = re.sub("[^\d]", "", cnpj).zfill(14) + if cnpj == (cnpj[0] * len(cnpj)): + return False + calc_dv = f"{0 if 11-(sum([(i%8+2)*int(d) for i, d in enumerate(reversed(list(cnpj[:-2])))])%11) >= 10 else 11-(sum([(i%8+2)*int(d) for i, d in enumerate(reversed(list(cnpj[:-2])))])%11)}{0 if 11-(sum([(i%8+2)*int(d) for i, d in enumerate(reversed(list(cnpj[:-1])))])%11) >= 10 else 11-(sum([(i%8+2)*int(d) for i, d in enumerate(reversed(list(cnpj[:-1])))])%11)}" + return calc_dv == cnpj[-2:] + + +def mask_cnpj(cnpj): + if cnpj == "": + return "" + cnpj = re.sub("[^\d]", "", cnpj).zfill(14) + return re.sub( + r"(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})", r"\1.\2.\3/\4-\5", cnpj + ) diff --git a/sigi/static/css/change_form.css b/sigi/static/css/change_form.css index 5e3076d..a8f7949 100644 --- a/sigi/static/css/change_form.css +++ b/sigi/static/css/change_form.css @@ -22,4 +22,7 @@ .readonly-label { height: unset; +} +.form-row.errors { + flex-direction: column; } \ No newline at end of file